使用PHP+SQLite时,跨目录文件如何正确连接数据库?
解决PHP+SQLite文件分散目录后的运行问题
你现在遇到的核心问题其实是文件路径不统一导致的:一方面是require_once的引用路径容易出错,另一方面是SQLite数据库文件会被创建在当前执行脚本的目录下,导致不同目录的脚本操作的不是同一个数据库。下面我一步步帮你调整代码和结构:
先明确当前的文件结构(根据你的代码推断)
incDB/(第一目录)testCreate.phptestAPI.php
actions/(第二目录)insert.php
views/(第三目录)select.php
问题1:数据库文件路径混乱
原来的testCreate.php里用$this->open('test.db'),当insert.php或select.php执行时,会在它们所在的目录创建新的test.db,而不是和incDB目录下的数据库统一。所以我们要给数据库指定绝对路径。
修改testCreate.php
<?php // 定义项目根目录常量:__FILE__是当前文件路径,dirname取到incDB目录,再dirname就是项目根目录 define('PROJECT_ROOT', dirname(dirname(__FILE__))); class mySqlite extends SQLite3{ function __construct(){ // 用根目录拼接数据库路径,确保所有脚本都操作同一个db文件 $this->open(PROJECT_ROOT . '/test.db'); } } $db = new mySqlite(); $db->exec("CREATE TABLE IF NOT EXISTS `test` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL);" ); ?>
问题2:require引用路径错误
不同目录的脚本用相对路径引用时,层级变化容易出错,最好也基于PROJECT_ROOT来引用文件。
修改testAPI.php
<?php // 直接引用同目录的testCreate.php,或者用PROJECT_ROOT都可以 require_once(dirname(__FILE__) . '/testCreate.php'); function insert($name){ global $db; $stmt = $db->exec("INSERT INTO `test`(`name`) VALUES ('$name')"); return $stmt !== false; } function select(){ global $db; if($stmt = $db->prepare('SELECT id,name FROM test ORDER BY `id` DESC ')) { $result = $stmt->execute(); $names=array(); while($arr=$result->fetchArray(SQLITE3_ASSOC)) { $names[]=$arr; } return $names; } return []; // 增加默认返回,避免无数据时出错 } ?>
修改insert.php
<?php // 定义根目录:当前文件在actions/,dirname两次到项目根 define('PROJECT_ROOT', dirname(dirname(__FILE__))); if(isset($_POST['new_menu']) && !empty($_POST['new_menu'])){ require_once(PROJECT_ROOT . '/incDB/testAPI.php'); $qry = insert($_POST['new_menu']); echo $qry ? 'ok' : 'no'; } ?> <form method='post'> <input type="text" name="new_menu"> <button type="submit">ADD</button> </form>
修改select.php
<?php define('PROJECT_ROOT', dirname(dirname(__FILE__))); require_once(PROJECT_ROOT . '/incDB/testAPI.php'); $rows = select() ?? []; ?> <table> <thead> <tr> <!-- 补全缺失的tr标签,保证HTML结构规范 --> <td style="border: solid 1px #000">id</td> <td style="border: solid 1px #000">name</td> </tr> </thead> <tbody> <?php foreach($rows as $row){ ?> <tr> <td style="border: dashed 1px #000"><?php echo htmlspecialchars($row['id']); ?></td> <td style="border: dashed 1px #000"><?php echo htmlspecialchars($row['name']); ?></td> </tr> <?php } ?> </tbody> </table>
重要优化:防止SQL注入
原insert函数直接把用户输入拼进SQL,非常危险,改成预处理语句彻底解决风险:
更新testAPI.php里的insert函数
function insert($name){ global $db; // 用预处理语句绑定参数,彻底避免注入 $stmt = $db->prepare("INSERT INTO `test`(`name`) VALUES (:name)"); $stmt->bindValue(':name', $name, SQLITE3_TEXT); $result = $stmt->execute(); return $result !== false; }
这样调整后,不管你的文件放在哪个子目录,只要PROJECT_ROOT定义正确,就能正常引用文件和操作同一个数据库了。
内容的提问来源于stack exchange,提问作者Abdu Hawi
相关产品推荐
相关产品推荐

