PHP + MySQL. Parsejador de scripts SQL. Exemple pràctic

De wikijoan
Salta a la navegació Salta a la cerca

Objectius

En aquest exercici faràs un parser de scripts SQL. En aquest cas parsejar significa recórrer l'arxiu línia a línia i distingir les comandes SQL a executar, i enviar-les a execució amb la connexió que hauràs establert amb el MySQL.

Desenvolupament

El script langtrainer.sql que ja has vist anteriorment el tens en el següent enllaç:

Exercicis a realitzar

Hem vist a teoria que podem accedir al MySQL des de PHP de tres maneres diferents: orientat a objecte; procedimental; i PDO. Per realitzar els següents exercicis hauràs d'escollir una de les maneres. En el 4rt exercici (voluntari), se't demana que ho facis de les altres maneres.

1. Parser de scripts mysql. Partim del script langtrainer.sql que conté tota l'estructura de la base de dades i dades d'exemple. Crearàs el script importarbd.php, que el que farà és llegir línia a línia el fitxer i les comandes SQL que conté el script les executarà contra la base de dades.

nota. Les dificultats que et trobaràs en aquest exercici és que hi ha comnetaris multilínia (comencen per /* i acaben per */), i comentaris d'una sola línia (comencen per #). Les sentències SQL poden ser multilínia (com ara els CREATE TABLE i sentències SQL d'una sola línia (com ara els INSERT). Per tant, el que distingeix que s'acaba una sentència SQL és la presència del ; (punt i coma), igual que passa en la consola de. MySQL.

2. Base de dades d'exemple mysqlsampledatabase.sql.

De l'anterior link pots descarregar una base de dades d'exemple de clients, empleats i oficines. Mira detingudament el contingut del script, i importa el script al teu Mysql amb el parsejador que has creat.

quasi solució: Fitxer:Parser v2.zip

NOTA: el script original està malament en una cosa: hi ha referències a taules quan aquestes no existeixen. Per exemple, quan s'està creant la taula customers posa:

CONSTRAINT `customers_ibfk_1` FOREIGN KEY (`salesRepEmployeeNumber`) REFERENCES `employees` (`employeeNumber`)

fa referència a la taula employees, però aquesta taula es crea més avall en el script. Per tant, és un error del script, no pas nostre.

Nosaltres hem suposat que els punts i coma sempre es troben al final de la frase, i ens serveix de referència per saber que la sentència s'ha acabat i la podem portar a execució. Però això no sempre és així. Això és el que passa en la següent línia, que ens dóna un error si no modifiquen en una nova versió el script:

(10164,'2003-10-21','2003-10-30','2003-10-23','Resolved','This order was disputed, but resolved on 11/1/2003; Customer doesn\\'t like the colors and precision of the models.',452),

3. Crea el fitxer vocabulari.php. Volcaràs en el navegador web el contingut de les taules word i translation (la informació creuada), de tres maneres diferents: 1) cada paraula amb un retorn de carro:

<br />

2) cada paraula com a element d'una llista:

<li>

3) cada paraula en una fila d'una taula:

<tr><td>


4. Script generar_vocabulari.php. Escriure el contingut del teu diccionari (word i translation) en el fitxer vocabulari.txt.


5. Ampliació (voluntari): Hem vist a teoria que podem accedir al MySQL des de PHP de tres maneres diferents: orientat a objecte; procedimental; i PDO. Els exercicis anteriors, fes-los de les tres maneres diferents.

Annex: llegir i escriure fitxers amb PHP

NOTA: no hi ha cap motiu per executar els següents scripts des del navegador web. Ho pots fer des de la línia de comandes. Això sí, hauràs de tenir en compte els permisos dels fitxers i el directori en el que treballes.

escriure_fitxer.php

 <?php
$myfile = fopen("newfile.txt", "w") or die("Unable to open file!");
$txt = "John Doe\
";
fwrite($myfile, $txt);
$txt = "Jane Doe\
";
fwrite($myfile, $txt);
fclose($myfile);
?>

Hem creat i escrit en el fitxer newfile.txt.

llegir_fitxer.php

 <?php
$handle = fopen("newfile.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        // process the line read.
\t\t\techo $line."<br />";
    }
} else {
    // error opening the file.
} 
fclose($handle);
?>

Hem llegit del fitxer newfile.txt.

Una combinació de tots dos és llegir un fitxer, i a mida que anem llegint, anem escrivint el contingut en un altre fitxer:

llegir_i_escriure.php:

 <?php
$handle = fopen("newfile.txt", "r");
$myfile = fopen("newfile2.txt", "w") or die("Unable to open file!");

if ($handle) {
    while (($line = fgets($handle)) !== false) {
        // process the line read.
\t\t\techo $line."<br />";
\t\t\t//escrivim el que llegim
\t\t\tfwrite($myfile, $line);
    }
} else {
    // error opening the file.
} 
fclose($handle);
fclose($myfile);
?>

Hem llegit del fitxer newfile.txt, i escrivim en el fitxer newfile2.txt

Entrega

Tota la documentació generada (scripts PHP bàsicament) la inclouràs en un fitxer comprimit i l'entregaràs en el Schoology. El professor també demana incloure el fitxer LLEGEIX-ME.txt on expliquis les dificultats i descobertes que has realitzat.

Recorda la normativa per entregar les pràctiques al Google Classroom: ASIX-M10-UF2#Normativa_d.27entrega_de_les_pr.C3.A0ctiques_al_Google_Classroom

Solució del parsejador

parser_langtrainer.php:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>Parsejador de un script SQL de MySQL</h1>
<?php
$servername = "localhost";
$username = "alumne";
$password = "keiL2lai";
$dbname = "langtrainer";

// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);

// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully<br /><br />";

$handle = fopen("langtrainer.sql", "r");
$comentari_multiple = 0;
$cadsql = "";

if ($handle) {
    while (($line = fgets($handle)) !== false) {
        // process the line read.
\t\t\tif (strcmp($line,"\
")!=0) {
\t\t\t//echo $line."<br />";
\t\t\t//http://stackoverflow.com/questions/2396713/php-5-strpos-difference-between-returning-0-and-false
\t\t\tif (strpos($line,"/*")===0) {
\t\t\t\t$comentari_multiple = 1; //comença un comentari múltiple, no processem
\t\t\t} else if (($comentari_multiple == 1) && (strpos($line,"*/")===0)) {
\t\t\t\t$comentari_multiple = 0; //acaba un comentari múltiple, ja podem processar
\t\t\t} else if ($comentari_multiple == 0) {
\t\t\t\tif (strpos($line,";")) {
\t\t\t\t\t$cadsql .= strstr($line,";", true); //http://www.w3schools.com/php/func_string_strstr.asp
\t\t\t\t\texecutar_comanda ($conn, $cadsql);
\t\t\t\t\t$cadsql = "";
\t\t\t\t} else { //comanda múltiple
\t\t\t\t\t$cadsql .= $line;
\t\t\t\t}
\t\t\t}
\t\t\t}
    } 
} else {
    // error opening the file.
} 
fclose($handle);

mysqli_close($conn);
?>
</body>
</html>

<?php
function executar_comanda($conn, $cadsql) {
\techo "$cadsql<br />";

\tif (mysqli_query($conn, $cadsql)) {
\t\t echo "OK<br /><br />";
\t} else {
\t\t echo "Error: ". mysqli_error($conn) . "<br /><br />";
\t}

}
?>

Durarda

2 hores



creat per Joan Quintana Compte, desembre 2019