SQLite / PHP只读?

SQLite / PHP只读?

SQLite/PHP read-only?

我一直在尝试将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();真正承认他们。


推荐阅读