web-dev-qa-db-fra.com

Exécution de fichiers MySQL * .sql dans PHP

J'ai deux fichiers *.sql Que j'utilise lors de la création d'une nouvelle base de données de site Web. Le premier fichier crée toutes les tables. Le deuxième fichier remplit certains enregistrements par défaut. Je voudrais exécuter ces fichiers depuis PHP. J'utilise également le Zend_Framework, si cela peut aider à accomplir cela.

Informations supplémentaires

  1. Je n'ai pas accès à la console
  2. J'essaie d'automatiser la génération de sites à partir de notre application.

[~ # ~] solution [~ # ~]

Utilisation de Shell_exec()...

$command = 'mysql'
        . ' --Host=' . $vals['db_Host']
        . ' --user=' . $vals['db_user']
        . ' --password=' . $vals['db_pass']
        . ' --database=' . $vals['db_name']
        . ' --execute="SOURCE ' . $script_path
;
$output1 = Shell_exec($command . '/site_db.sql"');
$output2 = Shell_exec($command . '/site_structure.sql"');

... Je n'ai jamais obtenu de sortie utile, mais j'ai suivi quelques suggestions sur n autre fil et finalement tout a fonctionné. Je passe au format --option=value Pour les commandes et j'utilise --execute="SOURCE ..." Au lieu de < Pour exécuter le fichier.

De plus, je n'ai jamais eu une bonne explication de la différence entre Shell_exec() et exec().

44
Sonny

Cette question revient de temps en temps. Il n'y a pas de bonne solution pour exécuter un script .sql directement à partir de PHP. Il existe des cas Edge où les instructions courantes dans un script .sql ne peuvent pas être exécutées en tant qu'instructions SQL. Par exemple, l'outil mysql a commandes intégrées qui ne sont pas reconnues par le serveur MySQL, par ex. CONNECT, TEE, STATUS et DELIMITER.

Je donne donc +1 à @Ignacio Vazquez-Abrams réponse . Vous devez exécuter votre script .sql dans PHP en appelant l'outil mysql, par exemple avec Shell_exec() .


J'ai réussi ce test:

$command = "mysql --user={$vals['db_user']} --password='{$vals['db_pass']}' "
 . "-h {$vals['db_Host']} -D {$vals['db_name']} < {$script_path}";

$output = Shell_exec($command . '/shellexec.sql');

Voir aussi mes réponses à ces questions connexes:

41
Bill Karwin
$commands = file_get_contents($location);   
$this->_connection->multi_query($commands);
18
Farid Movsumov

Voici ce que j'utilise:


function run_sql_file($location){
    //load file
    $commands = file_get_contents($location);

    //delete comments
    $lines = explode("\n",$commands);
    $commands = '';
    foreach($lines as $line){
        $line = trim($line);
        if( $line && !startsWith($line,'--') ){
            $commands .= $line . "\n";
        }
    }

    //convert to array
    $commands = explode(";", $commands);

    //run commands
    $total = $success = 0;
    foreach($commands as $command){
        if(trim($command)){
            $success += (@mysql_query($command)==false ? 0 : 1);
            $total += 1;
        }
    }

    //return number of successful queries and total number of queries found
    return array(
        "success" => $success,
        "total" => $total
    );
}


// Here's a startsWith function
function startsWith($haystack, $needle){
    $length = strlen($needle);
    return (substr($haystack, 0, $length) === $needle);
}
14
Ibrahim Lawal

Vous devrez créer un analyseur SQL complet pour cela. Je vous recommande d'utiliser plutôt l'outil de ligne de commande mysql pour cela, en l'invoquant en externe depuis PHP.

12

Je n'ai jamais eu à l'utiliser mais la classe mysqli a une méthode multi_query:

http://php.net/manual/en/mysqli.multi-query.php

6
Dave

Je sais que je suis assez tard pour la fête mais PHP Mini Admin a été une bouée de sauvetage à quelques reprises. Il s'agit essentiellement d'un PHPMyAdmin "allégé" contenu dans un seul fichier, donc pas besoin d'installations compliquées, téléchargez-le et connectez-vous. Simples!

6
Matthew

N'oubliez pas phpMyAdmin . Interface assez solide pour interagir avec MySQL.

Je ne sais pas si cela résout votre problème, car je ne sais pas si vous pouvez interagir directement avec lui à partir du code, mais je voulais juste le jeter là-bas.

2
jocull

J'ai créé un script de migration avec multi_query. Il peut traiter la sortie mysqldump et les exportations phpmyadmin sans outil de ligne de commande mysql. J'ai également créé une logique pour traiter plusieurs fichiers de migration en fonction de l'horodatage stocké dans la base de données comme Rails. Je sais qu'il a besoin de plus de gestion des erreurs mais fait actuellement le travail pour moi.

Découvrez-le: https://github.com/kepes/php-migration

Je pense que si vous ne traitez pas les entrées utilisateur avec uniquement des scripts créés par des développeurs ou des outils d'exportation, vous pouvez les utiliser en toute sécurité.

1
kepes

Vous pouvez utiliser ce script pour exécuter des fichiers de script MySQL. Vous devrez bien entendu définir $ hostName, $ userName, $ password, $ dataBaseName, $ port et $ fileName.

<?php

function parseScript($script) {

  $result = array();
  $delimiter = ';';
  while(strlen($script) && preg_match('/((DELIMITER)[ ]+([^\n\r])|[' . $delimiter . ']|$)/is', $script, $matches, PREG_OFFSET_CAPTURE)) {
    if (count($matches) > 2) {
      $delimiter = $matches[3][0];
      $script = substr($script, $matches[3][1] + 1);
    } else {
      if (strlen($statement = trim(substr($script, 0, $matches[0][1])))) {
        $result[] = $statement;
      }
      $script = substr($script, $matches[0][1] + 1);
    }
  }

  return $result;

}

function executeScriptFile($fileName, $dbConnection) {
  $script = file_get_contents($scriptFleName);
  $statements = parseScript($script);
  foreach($statements as $statement) {
    mysqli_query($dbConnection, $statement);
  }
}

$hostName = '';
$userName = '';
$password = '';
$dataBaseName = '';
$port = '';
$fileName = '';

if ($connection = @mysqli_connect($hostName, $userName, $password, $dataBaseName, $port)) {
  executeScriptFile($fileName, $connection);
} else {
  die('Can not connect to MySQL');
}
1
Sergiy Lavryk

Pour exécuter la génération de table à partir de l'application, vous pouvez créer un fichier php qui fera exactement cela lorsque vous l'exécuterez.

$hostname  = "localhost";
$database  = "databasename";
$username  = "rootuser";
$UserPassword  = "password";

$myconnection = mysql_pconnect($hostname, $username , $UserPassword) or trigger_error(mysql_error(),E_USER_ERROR); 
mysql_connect($hostname , $username , $UserPassword ) or die(mysql_error());
mysql_select_db($database) or die(mysql_error());

if ( !$myconnection ){ echo "Error connecting to database.\n";}


$userstableDrop = " DROP TABLE IF EXISTS `users`";
$userstableCreate = " CREATE TABLE IF NOT EXISTS `users` (
`UserID` int(11) NOT NULL,
  `User_First_Name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15" ;

$userstableInsert = "INSERT INTO `users` (`UserID`, `User_First_Name`) VALUES
(1, 'Mathew'),
(2, 'Joseph'),
(3, 'James'),
(4, 'Mary')";

$userstableAlter1 = "ALTER TABLE `users` ADD PRIMARY KEY (`UserID`)";
$userstableAlter2 = " ALTER TABLE `users` MODIFY `UserID` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=15";

$createDb_sql = $userstableDrop;
$insertSite = mysql_query($createDb_sql);

$createDb_sql = $userstableCreate;
$insertSite = mysql_query($createDb_sql);

$createDb_sql = $userstableInsert;
$insertSite = mysql_query($createDb_sql);

$createDb_sql = $userstableAlter1;
$insertSite = mysql_query($createDb_sql);

$createDb_sql = $userstableAlter2;
$insertSite = mysql_query($createDb_sql);

echo "Succesful!";
mysql_close($myconnection );
0
kizito Ikapel

Une suggestion:

// connect to db.
if (mysql_query("SOURCE myfile.sql")) {

  echo "Hello Sonny";

} 
0
zerodin

Voici ma solution et le code ci-dessous explique ce que cela fait. Le principe est de lire le fichier ligne par ligne, de construire une requête et d'exécuter chacun d'eux. J'ai vu de nombreuses solutions utilisant le "file_get_contents", ce qui n'est pas une bonne solution car cela pourrait provoquer un problème de tampon lors de la lecture de tout le contenu du fichier dans la variable de chaîne. Ma solution prend également en compte les requêtes des TRIGGER. Il n'y a pas d'allocation de tableau, les commentaires et les lignes vides sont supprimés.

<?php
 /**
 * Get a connection from database
 * @param type $db_Host database hostname
 * @param type $db_user database username
 * @param type $db_password database password
 * @param type $db_name database name
 * @return \PDO
 */
 function get_db_connection($db_Host, $db_user, $db_password, $db_name)
{
    $dns = "mysql:Host=$db_Host;dbname=$db_name";
    try
    {
        return new PDO($dns, $db_user, $db_password);
    } catch (PDOException $ex)
    {
        return null;
    }
}

/**
 * Runs SQL queries from file
 */

 function exec_sql_queries_from_file($script_file, $db_Host, $db_user, $db_password, $db_name)
{
    // to increase the default PHP execution time
    set_time_limit ( 60 ); // Max time = 60 seconds

    // Connect to database
    $connection = get_db_connection($db_Host, $db_user, $db_password, $db_name);

    // If the connection is acquired
    if($connection != null){

        // Open sql file
        $f = fopen($script_file, 'r');

        // sql query
        $query = '';

        // Default delimiter for queries
        $delimiter = ';';

        // read line by line
        while (!feof($f))
        {           
            $line = str_replace(PHP_EOL, '', fgets($f)); // read a line and remove the end of line character

            /* if the current line contains the key Word 'DELIMITER'. Ex: DELIMITER ;; or DELIMITER $$
             * mostly used for TRIGGERS' queries
             */
            if(strpos($line, 'DELIMITER') !== false)
            {
                // change the delimiter and read the next line
                $delimiter = str_replace('DELIMITER ', '', $line);
                continue;
            }   

            // Consider the line as part of a query if it's not empty and it's not a comment line
            if (!empty($line) && !starts_with($line, '/*') && !starts_with($line, '--'))
            {
                // the query hasn't reach its end: concatenate $line to $query if $line is not a delimiter
                $query .= $line !== $delimiter ? $line : '';

                // if the current line ends with $delimiter: end of current query
                if (ends_with($line, $delimiter))
                {                
                    // exec the query
                    $connection->exec($query) or die($connection->errorInfo());
                    // start new query
                    $query = '';
                }
            }                    
        }

        fclose($f);
    }
}

 /**
 * Starts with function
 */
function starts_with($haystack, $needle)
{
    return $haystack{0} === $needle{0} ? stripos($haystack, $needle) === 0 : false;
}

/**
 * Ends with function
 */
function ends_with($haystack, $needle)
{
    $pos = stripos($haystack, $needle);
    return $pos === FALSE ? FALSE : substr($haystack, $pos) === $needle;

}

0
N'faly Kaba