9

我一直在尝试将 SQLite 与 PHP 中的 PDO 包装器一起使用,但效果好坏参半。我可以很好地从数据库中读取,但是当我在浏览器中查看页面时,我的更新都没有提交到数据库中。奇怪的是,从我的 shell 运行脚本确实会更新数据库。我怀疑文件权限是罪魁祸首,但即使数据库提供完全访问权限(chmod 777),问题仍然存在。我应该尝试更改文件所有者吗?如果是这样,该怎么办?

顺便说一句,我的机器是标准的 Mac OS X Leopard 安装并激活了 PHP。

@汤姆马丁

感谢你的回复。我刚刚运行了您的代码,看起来 PHP 以用户 _www 运行。然后我尝试将数据库由_www拥有,但这也不起作用。

我还应该注意 PDO 的 errorInfo 函数并不表示发生了错误。这可能是 PDO 的设置以某种方式打开数据库以进行只读吗?我听说 SQLite 对整个文件执行写锁定。数据库是否有可能被阻止写入的其他东西锁定?

我决定包含有问题的代码。这将或多或少将格兰特的脚本移植到 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>";

?>
4

6 回答 6

12

Kyle,为了使 PDO/Sqlite 工作,您需要对数据库所在目录的写入权限。

另外,我看到您在循环中执行多项选择。如果您正在构建小型而不是重载的东西,这可能没问题。否则,我建议构建返回多行并在单独的循环中处理它们的单个查询。

于 2008-09-14T10:04:25.077 回答
2

我在PHP 手册中找到了答案“存放数据库文件的文件夹必须是可写的。”

于 2010-11-25T19:14:58.197 回答
1

我认为 PHP 通常以用户“nodody”的身份运行。虽然不确定在Mac上。如果 Mac 有 whoami,您可以尝试echo exec('whoami');找出答案。

于 2008-09-14T03:30:45.540 回答
1

对于那些在 OS X 上遇到 SQLite 只读问题的人:

1)确定用户所属的Apache httpd用户和组:

grep "^User" /private/etc/apache2/httpd.conf
组 _www

2) 在/Library/WebServer/Documents中为您的数据库创建一个子目录,并将组更改为 httpd 的组:

sudo chgrp _www /Library/WebServer/Documents/db

一个不太安全的选项是在/Library/WebServer/Documents上打开权限:

sudo chmod a+w /Library/WebServer/Documents

于 2010-09-12T15:11:55.647 回答
0

@Tom 取决于托管的设置方式,如果服务器将 PHP 作为 Apache 模块运行,那么它很可能是“无人”(通常是任何用户 apache 设置为)。但是,如果 PHP 设置为 cgi(例如 fast-cgi)并且服务器运行 SuExec,则 php 以拥有文件的同一用户身份运行。

无论哪种方式,包含数据库的文件夹都必须可由脚本写入,要么是同一用户,要么是为 php 用户设置了写入权限。

@Michal 除此之外,可以使用 beginTransaction(); 执行所有需要的操作然后 commit(); 去实际提交它们。

于 2009-08-29T19:58:26.093 回答
0

好吧,我现在遇到了同样的问题,但我错误地解决了这个问题:只需将每条插入的 SQL 指令放在try...catch它所在的块中。它使您以正确的方式做事,否则将无法正常工作。好吧,它现在可以工作了。祝其他有这个问题的人好运(因为我自己使用这个线程来尝试解决我的问题)。

于 2010-08-12T17:27:51.183 回答