SQLite / PHP只读?
我一直在尝试将SQLite与PHP中的PDO包装器一起使用,但取得了成功。我可以从数据库中正常读取,但是当我在浏览器中查看页面时,没有任何更新提交到数据库。奇怪的是,从我的shell运行脚本确实会更新数据库。我怀疑文件权限是罪魁祸首,但是即使数据库提供了完全访问权限(chmod 777),问题仍然存在。我应该尝试更改文件所有者吗?如果是这样,该怎么办?
顺便说一句,我的机器是标准的Mac OS X Leopard安装,并激活了PHP。
@汤姆·马丁
感谢你的回复。我只运行了代码,看起来PHP以用户_www的身份运行。然后,我尝试将数据库归于_www所有,但这也不起作用。
我还要注意,PDO的errorInfo函数并不表示发生了错误。这可能是PDO的设置,以某种方式打开了只读数据库吗?我听说SQLite对整个文件执行写锁定。数据库是否可能被阻止写入的其他方式锁定?
我决定包括相关代码。这将或者多或者少地将Grant的脚本移植到PHP。到目前为止,这只是"问题"部分:
<?php $db = new PDO('sqlite:test.db'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://stackoverflow.com/users/658/kyle"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_COOKIE, "shhsecret=1293706652"); $page = curl_exec($ch); preg_match('/summarycount">.*?([,\d]+)<\/div>.*?Reputation/s', $page, $rep); $rep = preg_replace("/,/", "", $rep[1]); preg_match('/iv class="summarycount".{10,60} (\d+)<\/d.{10,140}Badges/s', $page, $badge); $badge = $badge[1]; $qreg = '/question-summary narrow.*?vote-count-post"><strong.*?>(-?\d*).*?\/questions\/(\d*).*?>(.*?)<\/a>/s'; preg_match_all($qreg, $page, $questions, PREG_SET_ORDER); $areg = '/(answer-summary"><a href="\/questions\/(\d*).*?votes.*?>(-?\d+).*?href.*?>(.*?)<.a)/s'; preg_match_all($areg, $page, $answers, PREG_SET_ORDER); echo "<h3>Questions:</h3>\n"; echo "<table cellpadding=\"3\">\n"; foreach ($questions as $q) { $query = 'SELECT count(id), votes FROM Questions WHERE id = '.$q[2].' AND type=0;'; $dbitem = $db->query($query)->fetch(PDO::FETCH_ASSOC); if ($dbitem['count(id)'] > 0) { $lastQ = $q[1] - $dbitem['votes']; if ($lastQ == 0) { $lastQ = ""; } $query = "UPDATE Questions SET votes = '$q[1]' WHERE id = '$q[2]'"; $db->exec($query); } else { $query = "INSERT INTO Questions VALUES('$q[3]', '$q[1]', 0, '$q[2]')"; echo "$query\n"; $db->exec($query); $lastQ = "(NEW)"; } echo "<tr><td>$lastQ</td><td align=\"right\">$q[1]</td><td>$q[3]</td></tr>\n"; } echo "</table>"; ?>
解决方案
回答
我认为PHP通常以用户" nodody"的身份运行。不确定在Mac上。如果Mac有whoami,我们可以尝试使用echo exec('whoami');`来查找。
回答
凯尔(Kyle),为了使PDO / Sqlite工作,我们需要对数据库所在目录具有写许可权。
另外,我看到我们在循环中执行多个选择。如果我们要构建的东西很小而不是很重,那可能没问题。否则,我建议构建单个查询以返回多个行并在单独的循环中对其进行处理。
回答
汤姆
取决于托管的设置方式,如果服务器将PHP作为Apache模块运行,则它很可能是"没人"(通常将用户apache设置为)。但是,如果将PHP设置为cgi(例如fast-cgi)并且服务器运行SuExec,则php将以拥有文件的同一用户身份运行。
无论哪种方式,包含该数据库的文件夹都必须是脚本可写的,或者是同一用户,或者是将写权限设置为php用户。
@米哈尔
除此之外,可以使用beginTransaction();。执行所有需要的操作,然后comit();真正承认他们。
回答
好吧,我现在遇到了同样的问题,并通过一个错误解决了这个问题:只需将每条插入的SQL指令放在一个" try ... catch"块中即可。它使我们以正确的方式进行操作,否则将无法正常工作。好吧,现在可以了。对于遇到此问题的其他人,祝我们好运(因为我自己使用此线程来尝试解决我的问题)。
回答
对于那些在OS X上遇到SQLite只读问题的人:
1)确定Apache httpd用户和该用户所属的组:
grep "^User" /private/etc/apache2/httpd.conf groups _www
2)在/ Library / WebServer / Documents中为数据库创建一个子目录,并将该组更改为httpd的组:
sudo chgrp _www /Library/WebServer/Documents/db
一个不太安全的选项是打开/ Library / WebServer / Documents上的权限:
sudo chmod a+w /Library/WebServer/Documents
回答
我在PHP手册"包含数据库文件的文件夹必须是可写的"中找到了答案。