2008-09-14 21 views
9

He estado tratando de usar SQLite con el contenedor PDO en PHP con éxito mixto. Puedo leer bien de la base de datos, pero ninguna de mis actualizaciones se envía a la base de datos cuando veo la página en el navegador. Curiosamente, ejecutar el script desde mi shell actualiza la base de datos. Sospeché que los permisos de los archivos eran los culpables, pero incluso con la base de datos que proporciona acceso completo (chmod 777), el problema persiste. ¿Debo intentar cambiar el propietario del archivo? Si es así, ¿qué?SQLite/PHP de solo lectura?

Por cierto, mi máquina es la instalación estándar de Mac OS X Leopard con PHP activado.

@ Tom Martin

Gracias por su respuesta. Acabo de ejecutar su código y parece que PHP se ejecuta como usuario _www. Luego intenté cambiar la base de datos para que fuera propiedad de _www, pero tampoco funcionó.

También debería tener en cuenta que la función errorInfo de PDO no indica que se haya producido un error. ¿Podría ser una configuración con PDO de alguna manera abriendo la base de datos para solo lectura? Escuché que SQLite realiza bloqueos de escritura en todo el archivo. ¿Es posible que la base de datos esté bloqueada por algo más que impida la escritura?

He decidido incluir el código en cuestión. Este va a ser más o menos un puerto de Grant's script a PHP. Hasta ahora es solo la sección de Preguntas:

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

?> 
+0

Lo siento, hombre, no puedo ayudarlo más. Aún suena como un problema de permisos, si puedes hacer que funcione desde el shell. –

+0

Gracias de todos modos. A mí también me parece una cuestión de permisos, pero no veo cómo es posible aquí. –

+0

Probado cambiando '$ db = new PDO ('sqlite: test.db');' a una ruta completa? Me gusta .. '$ db = new PDO ('sqlite: /tmp/test.db');'? – dbr

Respuesta

10

Kyle, para que PDO/Sqlite funcione, necesita permiso de escritura para el directorio donde reside su base de datos.

Además, veo que realiza selecciones múltiples en el ciclo. Esto puede estar bien si estás construyendo algo pequeño y no pesado. De lo contrario, sugeriría construir una única consulta que devuelva múltiples filas y procesarlas en un bucle separado.

+0

¡Lo arregló! ¡Gracias! La secuencia de comandos ha sido más o menos una copia línea por línea de la secuencia de comandos de Grant, que realiza sus declaraciones SQL de esta manera. Sin embargo, estoy buscando hacer O (1) SELECT y poner en cola las ACTUALIZACIONES y ejecutarlas al final. –

+0

Me gustaría expresar mi agradecimiento, nunca hubiera adivinado que esta fuera la respuesta. Estoy usando SQLite3 (sin PDO) y esto me ayudó mucho. –

1

Creo que PHP comúnmente se ejecuta como el usuario "nodody". No estoy seguro sobre Mac sin embargo. Si Mac tiene whoami puedes probar echo exec('whoami'); para averiguarlo.

0

@Tom Depende de cómo se configura el alojamiento, si el servidor ejecuta PHP como un módulo de Apache, entonces es probable que sea 'nadie' (generalmente cualquier usuario que apache esté configurado). Pero si PHP está configurado como cgi (como fast-cgi) y el servidor ejecuta SuExec entonces php se ejecuta como el mismo usuario que posee los archivos.

En cualquier caso, la secuencia de comandos que contendrá la base de datos debe poder ser escrita por el script, ya sea por ser el mismo usuario o por tener permisos de escritura establecidos para el usuario php.

@Michal Dejando eso de lado, se podría usar beginTransaction(); realice todas las acciones necesarias luego comit(); para realmente comit ellos.

+0

PD: Como recuerdo la instalación 'estándar' de apache/php que viene con OSX, incluso hasta 10.5 (escritorio, no servidor) es solo PHP4, en realidad tiene que recompilar PHP si desea el beneficio de PHP5 (y en esa nota recompile Apache para obtener más funciones que comúnmente vienen con una configuración de Apache + PHP + MySQL). –

0

Bueno, tuve el mismo problema ahora y me di cuenta por un error: simplemente coloque cada pieza de inserción de instrucciones SQL dentro de un bloque try...catch que va. Te obliga a hacerlo de manera correcta, de lo contrario no funciona. Bueno, funciona ahora. Buena suerte para cualquier otra persona con este problema (ya que usé este hilo para tratar de resolver mi problema).

1

Para aquellos que han encontrado sólo lectura problemas con SQLite en OS X:

1) Determinar el Apache httpd usuario y grupo pertenece el usuario:

grep "^ Usuario"/private/etc/apache2/httpd.conf
grupos _www

2) Crea un subdirectorio en /Library/WebServer/Documents para su base de datos (s) y cambiar el grupo al grupo del httpd:

sudo chgrp _www/Library/WebServer/Documents/

una opción menos segura db es abrir permisos en /Library/WebServer/Documents:

sudo chmod a + w/Library/WebServer/Documents

1

he encontrado la respuesta en el PHP manual "La carpeta que contiene el archivo de base de datos debe tener permiso de escritura."