How to export database from Yii2 application
Home » BLOG » Yii2.0 framework » How to export database from Yii2 application

How to export database from Yii2 application

category:  Yii2.0 framework

The export database feature is nice to have for backup and restoring the database from either website or web application. Often I will export the database from my application and import it to my localhost. So I can continue to develop my application features or debug the issues after upgrading the PHP version.

After searching for a while, I found the PHP based MySQL dump library which is easy to use and it is clean code. The library allows you to export the database as raw SQL or a zip file. Moreover, the library doesn’t have two main issues for database exporting. The two main issues are the null value and text data type. For example, some scripts can generate the insert script by PHP but it can not generate the insert script if the field value is a null value. With the PHP based MySQL dump library, it doesn’t have any issues.

What Yii2 version and environment do I use

I test the DB dumping library with the environment below.

What goal we will do

Basically, we will create the custom class in the controllers’ folder in Yii2 and copy the code from the library and paste it into our new custom class. Then, we will change a minor code in our custom class in order to work the library working in Yii2. After our custom class is complete, we will create an export action in the controllers’ folder. This export action will call our custom class in order to export the database file. Finally, we will let the user download the dump file and save it on the user’s computer.

Create our custom class in the controllers in Yii2

  • Download the library from Github
  • In the controllers‘ folder of your Yii2 application, create the ShutterExport folder
  • Under the ShutterExport folder, create a new Shuttle_Dumper.php
  • In the Shuttle_Dumper.php, copy the code from the dumper.php which comes from the downloaded file from Github, and paste the code into the Shuttle_Dumper.php
  • For Yii2, you must add the namespace at the top of the Shuttle_Dumper.php. When you want to include the custom classes into the controllers or models or views in Yii2, you must add the namespace at the top of the file. Below is the namespace I add to the Shuttle_Dumper.php.
<?php
    // "frontend\controllers" is my controllers namespace.
    // The default controllers namespace is "app/controllers".
    // You will need to change the controllers namespace to match your Yii2 application.
    namespace frontend\controllers\ShuttleExport;
  • In the Shuttle_Dumper.php, it uses the PHP exception class. So in order to make it works in Yii2, we need to import the Exception class from Yii2. So I add the Exception class as shown below.
<?php
    namespace frontend\controllers\ShuttleExport;  

    use yii\base\Exception;
  • If you call the classes from the Shuttle_Dumper.php now, you will have the class initializing syntax error. The error comes from the Shuttle_DBConn class. You just need to change the original code to the new code as shown below.
class Shuttle_DBConn {
	public $host;
	public $username;
	public $password;
	public $name;

	protected $connection;

	function __construct($options) {
		$this->host = $options['host'];
		if (empty($this->host)) {
			$this->host = '127.0.0.1';
		}
		$this->username = $options['username'];
		$this->password = $options['password'];
		$this->name = $options['db_name'];
	}

	static function create($options) {
		if (class_exists('mysqli')) {	
			// # change code here		
			// $class_name = "Shuttle_DBConn_Mysqli";
			$dbConn = new Shuttle_DBConn_Mysqli($options);
		} else {
			// # change code here
			// $class_name = "Shuttle_DBConn_Mysql";
			$dbConn = new Shuttle_DBConn_Mysql($options);
		}

		// # change code here
		// return new $class_name($options);
		return $dbConn;
	}
}
  • Fixing a namespace issue in the Shuttle_DBConn_Mysqli class. Because we add our custom class in the controllers’ namespace. Then in the Shuttle_DBConn_Mysqli class, it creates the DB connection by MySQLi class which is not in the controller’s namespace. To fix it, we will add a backslash symbol in front of the MySQLi class as shown below.
class Shuttle_DBConn_Mysqli extends Shuttle_DBConn {
	function connect() {
		// # add a backslash in front of MySQLi for fixing the namespace issue
		$this->connection = @new \MySQLi($this->host, $this->username, $this->password, $this->name);
		...
  • Next but not least, we will add the UTF-8 support for the DB export file. We will add two lines to the Shuttle_DBConn_Mysqli class and the Shuttle_DBConn_Mysql class as shown below.
class Shuttle_DBConn_Mysql extends Shuttle_DBConn {
	function connect() {
		$this->connection = @mysql_connect($this->host, $this->username, $this->password);
		mysql_set_charset('utf8',$this->connection);  // add support UTF8
                ...
class Shuttle_DBConn_Mysqli extends Shuttle_DBConn {
	function connect() {
		
		$this->connection = @new \MySQLi($this->host, $this->username, $this->password, $this->name);
		mysqli_set_charset($this->connection,'utf8');  // add support UTF-8
                ...
  • Finally, we will add one parameter to avoid the out-of-memory issue. We will add the MYSQLI_USE_RESULT parameter into the query function in the Shuttle_DBConn_Mysqli class as shown below.
class Shuttle_DBConn_Mysqli extends Shuttle_DBConn {
	function connect() {
		$this->connection = @new \MySQLi($this->host, $this->username, $this->password, $this->name);
		mysqli_set_charset($this->connection,'utf8');  // add support UTF-8

		if ($this->connection->connect_error) {
			throw new Shuttle_Exception("Couldn't connect to the database: " . $this->connection->connect_error);
		}

		return true;
	}

	function query($q) {
		if (!$this->connection) {
			$this->connect();
		}
		// $res = $this->connection->query($q);
		$res = $this->connection->query($q, MYSQLI_USE_RESULT);

Here is the final code in the Shuttle_Dumper.php

<?php
// IMPORTANT NOTE:
// namespace is very important to include the classs file into controllers or models or views.
// it needs to follow the Yii2 rule which is

// => namespace <root>\YourFolder path

// <root> is app in the Yii2 basic template
// or frontend, common, api in the Yii2 advanced template
// YourFolder path

// When you want to include the classes into the controllers or models or views files,
// you must add namespace like this:

// => use frontend\controllers\TestCustomClass\Test;
// Then in function, you can call the function from the custom class below:
// => Test::test();  

// Refer Link: https://github.com/2createStudio/shuttle-export

namespace frontend\controllers\ShuttleExport;

use yii\base\Exception;

/**
 * Abstract dump file: provides common interface for writing
 * data to dump files. 
 */
abstract class Shuttle_Dump_File {
	/**
	 * File Handle
	 */
	protected $fh;

	/**
	 * Location of the dump file on the disk
	 */
	protected $file_location;

	abstract function write($string);
	abstract function end();

	static function create($filename) {
		if (self::is_gzip($filename)) {
			return new Shuttle_Dump_File_Gzip($filename);
		}
		return new Shuttle_Dump_File_Plaintext($filename);
	}
	function __construct($file) {
		$this->file_location = $file;
		$this->fh = $this->open();

		if (!$this->fh) {
			throw new Shuttle_Exception("Couldn't create gz file");
		}
	}

	public static function is_gzip($filename) {
		return preg_match('~gz$~i', $filename);
	}	
}

/**
 * Plain text implementation. Uses standard file functions in PHP. 
 */
class Shuttle_Dump_File_Plaintext extends Shuttle_Dump_File {
	function open() {
		return fopen($this->file_location, 'w');
	}
	function write($string) {
		return fwrite($this->fh, $string);
	}
	function end() {
		return fclose($this->fh);
	}
}

/**
 * Gzip implementation. Uses gz* functions. 
 */
class Shuttle_Dump_File_Gzip extends Shuttle_Dump_File {
	function open() {
		return gzopen($this->file_location, 'wb9');
	}
	function write($string) {
		return gzwrite($this->fh, $string);
	}
	function end() {
		return gzclose($this->fh);
	}
}

/**
 * MySQL insert statement builder. 
 */
class Shuttle_Insert_Statement {
	private $rows = array();
	private $length = 0;
	private $table;

	function __construct($table) {
		$this->table = $table;
	}

	function reset() {
		$this->rows = array();
		$this->length = 0;
	}

	function add_row($row) {
		$row = '(' . implode(",", $row) . ')';
		$this->rows[] = $row;
		$this->length += strlen($row);
	}

	function get_sql() {
		if (empty($this->rows)) {
			return false;
		}

		return 'INSERT INTO `' . $this->table . '` VALUES ' . 
			implode(",\n", $this->rows) . '; ';
	}

	function get_length() {
		return $this->length;
	}
}

/**
 * Main facade
 */
abstract class Shuttle_Dumper {
	/**
	 * Maximum length of single insert statement
	 */
	const INSERT_THRESHOLD = 838860;
	
	/**
	 * @var Shuttle_DBConn
	 */	
	public $db;

	/**
	 * @var Shuttle_Dump_File
	 */
	public $dump_file;

	/**
	 * End of line style used in the dump
	 */
	public $eol = "\r\n";

	/**
	 * Specificed tables to include
	 */
	public $include_tables;

	/**
	 * Specified tables to exclude
	 */
	public $exclude_tables = array();

	/**
	 * Factory method for dumper on current hosts's configuration. 
	 */
	static function create($db_options) {
		$db = Shuttle_DBConn::create($db_options);

		$db->connect();

		if (self::has_shell_access() 
				&& self::is_shell_command_available('mysqldump')
				&& self::is_shell_command_available('gzip')
			) {
			$dumper = new Shuttle_Dumper_ShellCommand($db);
		} else {
			$dumper = new Shuttle_Dumper_Native($db);
		}

		if (isset($db_options['include_tables'])) {
			$dumper->include_tables = $db_options['include_tables'];
		}
		if (isset($db_options['exclude_tables'])) {
			$dumper->exclude_tables = $db_options['exclude_tables'];
		}

		return $dumper;
	}

	function __construct(Shuttle_DBConn $db) {
		$this->db = $db;
	}

	public static function has_shell_access() {
		if (!is_callable('shell_exec')) {
			return false;
		}
		$disabled_functions = ini_get('disable_functions');
		return stripos($disabled_functions, 'shell_exec') === false;
	}

	public static function is_shell_command_available($command) {
		if (preg_match('~win~i', PHP_OS)) {
			/*
			On Windows, the `where` command checks for availabilty in PATH. According
			to the manual(`where /?`), there is quiet mode: 
			....
			    /Q       Returns only the exit code, without displaying the list
			             of matched files. (Quiet mode)
			....
			*/
			$output = array();
			exec('where /Q ' . $command, $output, $return_val);

			if (intval($return_val) === 1) {
				return false;
			} else {
				return true;
			}

		} else {
			$last_line = exec('which ' . $command);
			$last_line = trim($last_line);

			// Whenever there is at least one line in the output, 
			// it should be the path to the executable
			if (empty($last_line)) {
				return false;
			} else {
				return true;
			}
		}
		
	}

	/**
	 * Create an export file from the tables with that prefix.
	 * @param string $export_file_location the file to put the dump to.
	 *		Note that whenever the file has .gz extension the dump will be comporessed with gzip
	 * @param string $table_prefix Allow to export only tables with particular prefix
	 * @return void
	 */
	abstract public function dump($export_file_location, $table_prefix='');

	protected function get_tables($table_prefix) {
		if (!empty($this->include_tables)) {
			return $this->include_tables;
		}
		
		// $tables will only include the tables and not views.
		// TODO - Handle views also, edits to be made in function 'get_create_table_sql' line 336
		$tables = $this->db->fetch_numeric('
			SHOW FULL TABLES WHERE Table_Type = "BASE TABLE" AND Tables_in_'.$this->db->name.' LIKE "' . $this->db->escape_like($table_prefix) . '%"
		');

		$tables_list = array();
		foreach ($tables as $table_row) {
			$table_name = $table_row[0];
			if (!in_array($table_name, $this->exclude_tables)) {
				$tables_list[] = $table_name;
			}
		}
		return $tables_list;
	}
}

class Shuttle_Dumper_ShellCommand extends Shuttle_Dumper {
	function dump($export_file_location, $table_prefix='') {
		$command = 'mysqldump -h ' . escapeshellarg($this->db->host) .
			' -u ' . escapeshellarg($this->db->username) . 
			' --password=' . escapeshellarg($this->db->password) . 
			' ' . escapeshellarg($this->db->name);

		$include_all_tables = empty($table_prefix) &&
			empty($this->include_tables) &&
			empty($this->exclude_tables);

		if (!$include_all_tables) {
			$tables = $this->get_tables($table_prefix);
			$command .= ' ' . implode(' ', array_map('escapeshellarg', $tables));
		}

		$error_file = tempnam(sys_get_temp_dir(), 'err');

		$command .= ' 2> ' . escapeshellarg($error_file);

		if (Shuttle_Dump_File::is_gzip($export_file_location)) {
			$command .= ' | gzip';
		}

		$command .= ' > ' . escapeshellarg($export_file_location);

		exec($command, $output, $return_val);

		if ($return_val !== 0) {
			$error_text = file_get_contents($error_file);
			unlink($error_file);
			throw new Shuttle_Exception('Couldn\'t export database: ' . $error_text);
		}

		unlink($error_file);
	}
}

class Shuttle_Dumper_Native extends Shuttle_Dumper {
	public function dump($export_file_location, $table_prefix='') {
		$eol = $this->eol;

		$this->dump_file = Shuttle_Dump_File::create($export_file_location);

		$this->dump_file->write("-- Generation time: " . date('r') . $eol);
		$this->dump_file->write("-- Host: " . $this->db->host . $eol);
		$this->dump_file->write("-- DB name: " . $this->db->name . $eol);
		$this->dump_file->write("/*!40030 SET NAMES UTF8 */;$eol");
		
		$this->dump_file->write("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;$eol");
		$this->dump_file->write("/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;$eol");
		$this->dump_file->write("/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;$eol");
		$this->dump_file->write("/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;$eol");
		$this->dump_file->write("/*!40103 SET TIME_ZONE='+00:00' */;$eol");
		$this->dump_file->write("/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;$eol");
		$this->dump_file->write("/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;$eol");
		$this->dump_file->write("/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;$eol");
		$this->dump_file->write("/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;$eol$eol");


		$tables = $this->get_tables($table_prefix);
		foreach ($tables as $table) {
			$this->dump_table($table);
		}
		
		$this->dump_file->write("$eol$eol");
		$this->dump_file->write("/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;$eol");
		$this->dump_file->write("/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;$eol");
		$this->dump_file->write("/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;$eol");
		$this->dump_file->write("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;$eol");
		$this->dump_file->write("/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;$eol");
		$this->dump_file->write("/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;$eol");
		$this->dump_file->write("/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;$eol$eol");

		unset($this->dump_file);
	}

	protected function dump_table($table) {
		$eol = $this->eol;

		$this->dump_file->write("DROP TABLE IF EXISTS `$table`;$eol");

		$create_table_sql = $this->get_create_table_sql($table);
		$this->dump_file->write($create_table_sql . $eol . $eol);

		$data = $this->db->query("SELECT * FROM `$table`");

		$insert = new Shuttle_Insert_Statement($table);

		while ($row = $this->db->fetch_row($data)) {
			$row_values = array();
			foreach ($row as $value) {
				$row_values[] = $this->db->escape($value);
			}
			$insert->add_row( $row_values );

			if ($insert->get_length() > self::INSERT_THRESHOLD) {
				// The insert got too big: write the SQL and create
				// new insert statement
				$this->dump_file->write($insert->get_sql() . $eol);
				$insert->reset();
			}
		}

		$sql = $insert->get_sql();
		if ($sql) {
			$this->dump_file->write($insert->get_sql() . $eol);
		}
		$this->dump_file->write($eol . $eol);
	}
	
	public function get_create_table_sql($table) {
		$create_table_sql = $this->db->fetch('SHOW CREATE TABLE `' . $table . '`');
		return $create_table_sql[0]['Create Table'] . ';';
	}
}

class Shuttle_DBConn {
	public $host;
	public $username;
	public $password;
	public $name;

	protected $connection;

	function __construct($options) {
		$this->host = $options['host'];
		if (empty($this->host)) {
			$this->host = '127.0.0.1';
		}
		$this->username = $options['username'];
		$this->password = $options['password'];
		$this->name = $options['db_name'];
	}

	static function create($options) {
		if (class_exists('mysqli')) {
			// NOTE: Apple fixes the code in order to use in Yii2 controller
			// $class_name = "Shuttle_DBConn_Mysqli";
			$dbConn = new Shuttle_DBConn_Mysqli($options);
		} else {
			// NOTE: Apple fixes the code in order to use in Yii2 controller
			// $class_name = "Shuttle_DBConn_Mysql";
			$dbConn = new Shuttle_DBConn_Mysql($options);
		}

		// NOTE: Apple fixes the code in order to use in Yii2 controller
		// return new $class_name($options);
		return $dbConn;
	}
}

class Shuttle_DBConn_Mysql extends Shuttle_DBConn {
	function connect() {
		$this->connection = @mysql_connect($this->host, $this->username, $this->password);
		mysql_set_charset('utf8',$this->connection);  // add support UTF8

		if (!$this->connection) {
			throw new Shuttle_Exception("Couldn't connect to the database: " . mysql_error());
		}

		$select_db_res = mysql_select_db($this->name, $this->connection);
		if (!$select_db_res) {
			throw new Shuttle_Exception("Couldn't select database: " . mysql_error($this->connection));
		}

		return true;
	}

	function query($q) {
		if (!$this->connection) {
			$this->connect();
		}
		$res = mysql_query($q);
		if (!$res) {
			throw new Shuttle_Exception("SQL error: " . mysql_error($this->connection));
		}
		return $res;
	}

	function fetch_numeric($query) {
		return $this->fetch($query, MYSQL_NUM);
	}

	function fetch($query, $result_type=MYSQL_ASSOC) {
		$result = $this->query($query, $this->connection);
		$return = array();
		while ( $row = mysql_fetch_array($result, $result_type) ) {
			$return[] = $row;
		}
		return $return;
	}

	function escape($value) {
		if (is_null($value)) {
			return "NULL";
		}
		return "'" . mysql_real_escape_string($value) . "'";
	}

	function escape_like($search) {
		return str_replace(array('_', '%'), array('\_', '\%'), $search);
	}

	function get_var($sql) {
		$result = $this->query($sql);
		$row = mysql_fetch_array($result);
		return $row[0];
	}

	function fetch_row($data) {
		return mysql_fetch_assoc($data);
	}
}


class Shuttle_DBConn_Mysqli extends Shuttle_DBConn {
	function connect() {
		// NOTE: Apple fixes the code in order to use in Yii2 controller
		$this->connection = @new \MySQLi($this->host, $this->username, $this->password, $this->name);
		mysqli_set_charset($this->connection,'utf8');  // add support UTF-8

		if ($this->connection->connect_error) {
			throw new Shuttle_Exception("Couldn't connect to the database: " . $this->connection->connect_error);
		}

		return true;
	}

	function query($q) {
		if (!$this->connection) {
			$this->connect();
		}
		// $res = $this->connection->query($q);
		$res = $this->connection->query($q, MYSQLI_USE_RESULT);  
		
		if (!$res) {
			throw new Shuttle_Exception("SQL error: " . $this->connection->error);
		}
		
		return $res;
	}

	function fetch_numeric($query) {
		return $this->fetch($query, MYSQLI_NUM);
	}

	function fetch($query, $result_type=MYSQLI_ASSOC) {
		$result = $this->query($query, $this->connection);
		$return = array();
		while ( $row = $result->fetch_array($result_type) ) {
			$return[] = $row;
		}
		return $return;
	}

	function escape($value) {
		if (is_null($value)) {
			return "NULL";
		}
		return "'" . $this->connection->real_escape_string($value) . "'";
	}

	function escape_like($search) {
		return str_replace(array('_', '%'), array('\_', '\%'), $search);
	}

	function get_var($sql) {
		$result = $this->query($sql);
		$row = $result->fetch_array($result, MYSQLI_NUM);
		return $row[0];
	}

	function fetch_row($data) {
		return $data->fetch_array(MYSQLI_ASSOC);
	}
}

class Shuttle_Exception extends Exception {};

Create the UtilitiesController

Now we have the Shuttle_Dumper class which is ready to be called by any action in Yii2. Next, we will create a new UtilitiesController for calling the Shuttle_Dumper class.

UtilitiesController and action methods

  • Under the controllers’ folder, create a new UtilitiesController.php
  • In the UtilitiesController.php, we will have three methods as below
    • behaviors – we add the access control in the behaviors method
    • actionIndex – we add the frontend page in actionIndex method
    • actionExport – we call the Shuttle_Dumper class in actionExport method

Here is a complete source code in UtilitiesController.php

<?php

namespace frontend\controllers;

use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii; // we import Yii class in order to use Yii::$app->db->createCommand()

// # import the Shuttle_Dumper class
use frontend\controllers\ShuttleExport\Shuttle_Dumper;

class UtilitiesController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['index', 'create', 'delete', 'update', 'view'], 
                'rules' => [
                    [
                        'actions' => ['index', 'create', 'delete', 'update', 'view'],  
                        'allow' => true,
                        'roles' => ['@'], 
                    ],
                ],
              
                'denyCallback' => function ($rule, $action) {
                    //-- You are not allowed to access this page. denyCallback function is executed if no rules are mathced.
                    $this->goHome();
                }
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }


    /**
     * @return mixed
     */
    public function actionIndex()
    {
        return $this->render('index');
    }


    /**
     * Export the dump database 
     * @link https://github.com/2createStudio/shuttle-export
     */
    public function actionExport()
    {

        // access the DB connection using Yii class       
        $db_connection_yii2 = \Yii::$app->db;
        // extract the db config
        $db_config = explode(';', str_replace('mysql:', '', $db_connection_yii2->dsn));
        $host = str_replace('host=', '', $db_config[0]);
        $db_name = str_replace('dbname=', '', $db_config[1]);

        // call our custom class
        $db_dumper = Shuttle_Dumper::create(array(
            'host' => $host,
            'username' => $db_connection_yii2->username,
            'password' => $db_connection_yii2->password,
            'db_name' => $db_name,
        ));

        // option 1: dump the database to gzipped file      
        $db_dumper->dump($db_name . date('Y-m-d') . '.sql.gz');

        // option 2: dump the database to plain text file
        // $db_dumper->dump('YouCanChangeFileName.sql');    

        // Process the downloadable file for the user
        $filepath = Yii::getAlias('@frontend') . '/web/' . $db_name . date('Y-m-d') . '.sql.gz';
        if (file_exists($filepath)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($filepath) . '"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($filepath));
            flush(); // Flush system output buffer
            readfile($filepath);

            // delete the dump file
            unlink($filepath);

            exit;
        }
    }
}

The code above is very straightforward. It is simple and works as I expect.

Create the frontend page

Lastly, we will create the index page for exporting the database from the frontend. My export page looks like this.

Export DB from Yii2

In Yii2, I will go to the views folder. Then create a new utilities folder under the views folder. After that, create the new index.php inside the utilities folder.

The file structure looks like this.

  • views
    • utilities
      • index.php

Here is the code in the index.php.

<?php 
use yii\helpers\Html;
?>

<div class="vendor-index box box-default">
  <div class="box-header with-border"> 
    <h1><?php echo Yii::t('frontend', 'Export database') ?></h1>
  </div>

  <div class="box-body"> 
    <p><span class="fa fa-info-circle"></span> <?php echo Yii::t('frontend','Export the database by mysqldump command and let you download the zip file to your computer.'); ?></p>
    <?= Html::a( '<span class="fa fa-download"></span> ' . Yii::t('frontend','Export'), ['/utilities/export'], ['class'=>'btn bg-olive btn-flat']) ?>
  </div>
</div>

As you can see from the index.php, I create the link to “utilities/export” so when the user clicks on the export button, the export action will be called. When the export action is called, it will call the Shuttle_Dumper class. Then the DB dump file will be created. Once the dump file is created successfully, you will get the prompt for downloading the dump file to your computer.

Overview of the file structure we create

Here is an overview of the file structure we create in this post.

  • controllers
    • ShuttleExport
      • Shuttle_Dumper.php
    • UtilitiesController.php
  • views
    • utilities
      • index.php

That’s it. If it is helpful and saves your time, please consider buying me a coffee. It will make me smile.