我一直在尝试将SQLite与PHP中的PDO包装器一起使用,但取得了成功。我可以从数据库中正常读取,但是当我在浏览器中查看页面时,没有任何更新提交到数据库。奇怪的是,从我的shell运行脚本确实会更新数据库。我怀疑文件权限是罪魁祸首,但是即使数据库提供了完全访问权限(chmod 777),问题仍然存在。我应该尝试更改文件所有者吗?如果是这样,该怎么办?
顺便说一句,我的机器是标准的Mac OS X Leopard安装,并激活了PHP。
@汤姆·马丁
谢谢您的回复。我只运行了您的代码,看起来PHP以用户_www的身份运行。然后,我尝试将数据库归于_www所有,但这也不起作用。
我还要注意,PDO的errorInfo函数并不表示发生了错误。这可能是PDO的设置,以某种方式打开了只读数据库吗?我听说SQLite对整个文件执行写锁定。数据库是否可能被其他阻止写入的东西锁定了?
我已决定包括相关代码。这将或多或少地将Grant的脚本移植到PHP。到目前为止,这只是"问题"部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <?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">(-?\\d*).*?\\/questions\\/(\\d*).*?>(.*?)<\\/a>/s';
preg_match_all($qreg, $page, $questions, PREG_SET_ORDER);
$areg = '/(answer-summary">(-?\\d+).*?href.*?>(.*?)<.a)/s';
preg_match_all($areg, $page, $answers, PREG_SET_ORDER);
echo"Questions:\
";
echo"<table cellpadding=\"3\">\
";
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\
";
$db->exec($query);
$lastQ ="(NEW)";
}
echo"<tr><td>$lastQ</td><td align=\"right\">$q[1]</td><td>$q[3]</td></tr>\
";
}
echo"</table>";
?> |
凯尔(Kyle),为了使PDO / Sqlite工作,您需要对数据库所在目录具有写许可权。
另外,我看到您在循环中执行多个选择。如果您要构建的东西很小而不是很重,那可能没问题。否则,我建议构建单个查询以返回多个行并在单独的循环中对其进行处理。
我在PHP手册"包含数据库文件的文件夹必须是可写的"中找到了答案。
对于那些在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通常以用户" nodody"的身份运行。虽然不确定在Mac上。如果Mac具有whoami,则可以尝试echo exec('whoami');进行查找。
好吧,我现在遇到了同样的问题,并通过一个错误解决了这个问题:只需将每个插入的SQL指令放在一个try...catch块中即可。它使您以正确的方式进行操作,否则将无法正常工作。好吧,现在可以了。对于遇到此问题的其他人,祝您好运(因为我自己使用此线程来尝试解决我的问题)。
汤姆
取决于托管的设置方式,如果服务器将PHP作为Apache模块运行,则它很可能是"没人"(通常将任何用户apache设置为)。但是,如果将PHP设置为cgi(例如fast-cgi),并且服务器运行SuExec,则php将以拥有文件的同一用户身份运行。
无论哪种方式,包含该数据库的文件夹都必须是脚本可写的,或者是同一用户,或者是将写权限设置为php用户。
@米哈尔
除此之外,可以使用beginTransaction();。执行所有需要的操作,然后comit();真正承认他们。