Writing an installer for your CakePHP application
If you write an application which the user must install on his own server, you have to think about the installation process of your application. In this article I will describe the approach I have used in my application.
This approach is heavily inspired by the one used by WordPress. That means the user has to create the database and to define the database settings in app/config/database.php himself. When this is done, the user must run the installer, which then creates the tables and does some application-specific stuff like creating a default user.
The installer is a usual controller, which is automatically called when the user accesses the application for the first time. For this purpose I added a bit of logic to app/config/routes.php:
if (file_exists(TMP.'installed.txt')) {
// the routes for when the application has been installed
} else {
Router::connect('/:action', array('controller' => 'installer'));
}
So as long as there is no “installed.txt” file, the user gets the first page of the installer when he requests the url of the application. The consequence of this logic is that we have to create such a file at the end of the installation process (see below).
The installer controller itself is straight-forward, each action is one step in the installation process. You can find a minimal version of the installer below:
// app/controllers/
uses('model' . DS . 'connection_manager');
class InstallerController extends AppController {
var $uses = array();
function beforeFilter() {
if (file_exists(TMP.'installed.txt')) {
echo 'Application already installed. Remove app/config/installed.txt to reinstall the application';
exit();
}
}
function index() {
}
function database() {
$db = ConnectionManager::getDataSource('default');
if(!$db->isConnected()) {
echo 'Could not connect to database. Please check the settings in app/config/database.php and try again';
exit();
}
$this->__executeSQLScript($db, CONFIGS.'sql'.DS.'app.sql');
$this->redirect('/installer/thanks');
}
function thanks() {
file_put_contents(TMP.'installed.txt', date('Y-m-d, H:i:s'));
}
function __executeSQLScript($db, $fileName) {
$statements = file_get_contents($fileName);
$statements = explode(';', $statements);
foreach ($statements as $statement) {
if (trim($statement) != '') {
$db->query($statement);
}
}
}
}
It is a pragmatic solution with the drawback that it is not really reusable,..




That’s a pretty nice solution. How would you prevent someone from deleting the installed.txt and accidentally re-running the installation? Provide some sort of install prompt? Maybe write a some junk to installed.txt and save the md5sum in the db for comparison?
@Damian: Hm, good question. A possible solution could be to have a command line installer so you don’t need that “installed.txt” file.
nate suggested:
add route file with default route to /install/
after install, replace route.php with app production route.php
chmod before…
Nice! Now, all Cake needs is a package manager :)
@majna: Good idea, thanks!
@brandon: Yeah, a package manager would be cool :)
Yea, a package manager would be great. I think a good way of doing this would be to have the installer check if /app/config/database.php exisits. If it does, prompt the user to type in their database details and have the installer write it.
As well as then executing the SQL, you could use something like the ConfComponent from the bakery to manage all main site settings.
@Digital Spaghetti: Yes, that’s a possible approach. I was too lazy to implement it as I saw the Wordpress guys simply force the users to make the settings directly in the database config file ;-)
Maybe it would be better to have a not_installed.txt file, so once installed it gets deleted. Then no problems about people deleting it by accident.
@charlie: That’s a good idea, thanks!