0

I looked for a way in PHP to send a mysql database as .sql File to the client as download. I found a bunch of solutions and I really liked the approach of using mysqldump command via exec() (or shell_exec() or system()) but sadly the mysqldump command is not available to me in this case.

And since my database connection cannot be hardcoded either, I found a lot of 'reinventing the wheel' solutions, where you just query 'SHOW TABLES' and start iterating, like in here: Export MySQL database using PHP only (Raju Dudhrejiya's Answer) . This worked perfectly fine until I noticed that it only saves the tables, and so does every other similar approach I found. No Events, Triggers, etc.. which is bad. Really bad.

I need something that also at least backs up events, so my first approach would be to just expand the following method (taken from the link above), though I am not sure how I would go on about it. I guess I must somehow query over all the events and append a 'CREATE EVENT' statement somewhere? Has anyone done something similar?

function Export_Database($host,$user,$pass,$name,  $tables=false, $backup_name=false )
    {
        $mysqli = new mysqli($host,$user,$pass,$name); 
        $mysqli->select_db($name); 
        $mysqli->query("SET NAMES 'utf8'");

    $queryTables    = $mysqli->query('SHOW TABLES'); 
    while($row = $queryTables->fetch_row()) 
    { 
        $target_tables[] = $row[0]; 
    }   
    if($tables !== false) 
    { 
        $target_tables = array_intersect( $target_tables, $tables); 
    }
    foreach($target_tables as $table)
    {
        $result         =   $mysqli->query('SELECT * FROM '.$table);  
        $fields_amount  =   $result->field_count;  
        $rows_num=$mysqli->affected_rows;     
        $res            =   $mysqli->query('SHOW CREATE TABLE '.$table); 
        $TableMLine     =   $res->fetch_row();
        $content        = (!isset($content) ?  '' : $content) . "\n\n".$TableMLine[1].";\n\n";

        for ($i = 0, $st_counter = 0; $i < $fields_amount;   $i++, $st_counter=0) 
        {
            while($row = $result->fetch_row())  
            { //when started (and every after 100 command cycle):
                if ($st_counter%100 == 0 || $st_counter == 0 )  
                {
                        $content .= "\nINSERT INTO ".$table." VALUES";
                }
                $content .= "\n(";
                for($j=0; $j<$fields_amount; $j++)  
                { 
                    $row[$j] = str_replace("\n","\\n", addslashes($row[$j]) ); 
                    if (isset($row[$j]))
                    {
                        $content .= '"'.$row[$j].'"' ; 
                    }
                    else 
                    {   
                        $content .= '""';
                    }     
                    if ($j<($fields_amount-1))
                    {
                            $content.= ',';
                    }      
                }
                $content .=")";
                //every after 100 command cycle [or at last line] ....p.s. but should be inserted 1 cycle eariler
                if ( (($st_counter+1)%100==0 && $st_counter!=0) || $st_counter+1==$rows_num) 
                {   
                    $content .= ";";
                } 
                else 
                {
                    $content .= ",";
                } 
                $st_counter=$st_counter+1;
            }
        } $content .="\n\n\n";
    }
    //$backup_name = $backup_name ? $backup_name : $name."___(".date('H-i-s')."_".date('d-m-Y').")__rand".rand(1,11111111).".sql";
    $backup_name = $backup_name ? $backup_name : $name.".sql";
    header('Content-Type: application/octet-stream');   
    header("Content-Transfer-Encoding: Binary"); 
    header("Content-disposition: attachment; filename=\"".$backup_name."\"");  
    echo $content; exit;
}

1 Answer 1

1

Nevermind, I figured it out myself.

This adds events and tables, triggers/ stored procedures should work in a similar fashion:

function Export_Database($host,$user,$pass,$name,$tables=false,$backup_name=false){
  $mysqli = new mysqli($host,$user,$pass,$name);
  $mysqli->select_db($name);
  $mysqli->query("SET NAMES 'utf8'");
  $queryTables    = $mysqli->query("SHOW TABLES");
  while($row = $queryTables->fetch_row()){
    $target_tables[] = $row['0']; //put each table name into array
  }
  if($tables){
    $target_tables = array_intersect($target_tables, $tables);
  }
  foreach($target_tables as $table){
    $result         =   $mysqli->query('SELECT * FROM '.$table);
    $fields_amount  =   $result->field_count;
    $rows_num       =   $mysqli->affected_rows;
    $res            =   $mysqli->query('SHOW CREATE TABLE '.$table);
    $TableMLine     =   $res->fetch_row();
    $content        = (!isset($content) ?  '' : $content) . "\n\n".$TableMLine[1].";\n\n";

    for ($i = 0, $st_counter = 0; $i < $fields_amount;   $i++, $st_counter=0){
      while($row = $result->fetch_row()){
        //when started (and every after 100 command cycle):
        if ($st_counter%100 == 0 || $st_counter == 0 ){
          $content .= "\nINSERT INTO ".$table." VALUES";
        }
        $content .= "\n(";
        for($j=0; $j<$fields_amount; $j++){
          $row[$j] = str_replace("\n","\\n", addslashes($row[$j]) );
          if (isset($row[$j])){
            $content .= '"'.$row[$j].'"' ;
          } else {
            $content .= '""';
          }
          if ($j<($fields_amount-1)){
            $content.= ',';
          }
        }
        $content .=")";
        //every after 100 command cycle [or at last line] ....p.s. but should be inserted 1 cycle eariler
        if ( (($st_counter+1)%100==0 && $st_counter!=0) || $st_counter+1==$rows_num){
          $content .= ";";
        } else {
          $content .= ",";
        }
        $st_counter=$st_counter+1;
      }
    } $content .="\n\n\n";
  }

  $events = $mysqli->query("SHOW EVENTS");
  while($events && ($row = $events->fetch_row())){
    $res = $mysqli->query("SHOW CREATE EVENT ".$row[0].'.'.$row[1]);
    $TableMLine = $res->fetch_row();
    $content .= "\n\n".$TableMLine[3].";\n\n";
  }

  $backup_name = $backup_name ? $backup_name : $name.".sql";
  header('Content-Type: application/octet-stream');
  header("Content-Transfer-Encoding: Binary");
  header("Content-disposition: attachment; filename=\"".$backup_name."\"");
  echo $content;  exit;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Changed it to fit databases with no events

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.