SQLite/PHP 只读?

发布于 2024-07-05 06:32:42 字数 2446 浏览 7 评论 0原文

我一直在尝试将 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>";

?>

I've been trying to use SQLite with the PDO wrapper in PHP with mixed success. I can read from the database fine, but none of my updates are being committed to the database when I view the page in the browser. Curiously, running the script from my shell does update the database. I suspected file permissions as the culprit, but even with the database providing full access (chmod 777) the problem persists. Should I try changing the file owner? If so, what to?

By the way, my machine is the standard Mac OS X Leopard install with PHP activated.

@Tom Martin

Thank you for your reply. I just ran your code and it looks like PHP runs as user _www. I then tried chowning the database to be owned by _www, but that didn't work either.

I should also note that PDO's errorInfo function doesn't indicate an error took place. Could this be a setting with PDO somehow opening the database for read-only? I've heard that SQLite performs write locks on the entire file. Is it possible that the database is locked by something else preventing the write?

I've decided to include the code in question. This is going to be more or less a port of Grant's script to PHP. So far it's just the Questions section:

<?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>";

?>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

灯角 2024-07-12 06:32:44

好吧,我现在遇到了同样的问题,并且错误地解决了这个问题:只需将每条插入的 SQL 指令放在它所在的 try...catch 块中即可。 它让你以正确的方式去做,否则它就不起作用。 嗯,现在可以了。 祝其他遇到此问题的人好运(因为我自己使用此线程来尝试解决我的问题)。

Well, I had the same problem now and figured it out by a mistake: just put every inserting piece of SQL instruction inside a try...catch block that it goes. It makes you do it right way otherwise it doesn't work. Well, it works now. Good luck for anyone else with this problem(as I used this thread myself to try to solve my problem).

木森分化 2024-07-12 06:32:44

我认为 PHP 通常以用户“nodody”运行。 不过在 Mac 上不确定。 如果 Mac 有 whoami,您可以尝试 echo exec('whoami'); 来查找。

I think PHP commonly runs as the user "nodody". Not sure about on Mac though. If Mac has whoami you could try echo exec('whoami'); to find out.

会傲 2024-07-12 06:32:44

对于在 OS X 上遇到 SQLite 只读问题的用户:

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

grep“^用户”/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

For those who have encountered read-only issues with SQLite on OS X:

1) Determine the Apache httpd user and group the user belongs to:

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

2) Create a subdirectory in /Library/WebServer/Documents for your database(s) and change the group to the httpd's group:

sudo chgrp _www /Library/WebServer/Documents/db

A less secure option is to open permissions on /Library/WebServer/Documents:

sudo chmod a+w /Library/WebServer/Documents

一笔一画续写前缘 2024-07-12 06:32:44

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

不管怎样,包含数据库的文件夹必须可由脚本写入,要么是同一用户,要么为 php 用户设置写入权限。

@米哈尔
除此之外,可以使用 beginTransaction(); 执行所有需要的操作,然后comit(); 实际执行它们。

@Tom
Depends on how the hosting is setup, If the server runs PHP as an Apache Module then its likely that it is 'nobody' (usually whatever user apache is setup as). But if PHP is setup as cgi (such as fast-cgi) and the server runs SuExec then php runs as the same user who owns the files.

Eitherway the folder that will contain the database must be writable by the script, either by being the same user, or by having write permission set to the php user.

@Michal
That aside, one could use beginTransaction(); perform all the actions needed then comit(); to actually comit them.

墨洒年华 2024-07-12 06:32:43

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

I found the answer on the PHP manual "The folder that houses the database file must be writeable."

浅语花开 2024-07-12 06:32:42

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

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

Kyle, in order for PDO/Sqlite to work you need write permission to directory where your database resides.

Also, I see you perform multiple selects in loop. This may be ok if you are building something small and not heavy loaded. Otherwise I'd suggest building single query that returns multiple rows and process them in separate loop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文