This is the third post in my series on Yii, my favorite PHP framework. In the first, I show how to download and test the framework itself. In the second, I show how to create a basic Web application. The end of that post also discusses the files and folders in the application directory. You’ll want to be familiar with those as you go forward. In this post, I discuss how you’ll want to configure your Yii-based application, including handling errors, adding components, and establishing a database connection. This post does assume you have an existing application to work with; if you don’t, follow the steps in the previous two posts.
(Note: In October 2010, I’ve updated this entire series to reflect changes in Yii since this series was written, and to take into account feedback provided through the comments. Some outdated material will be crossed out, but left in to reflect how things have changed since the series was begun in June 2009.)
There are a couple of ways you can configure how your Yii application behaves. For the most part, you’ll do this through the protected/config/main.php file, but first I want to talk about the index.php file, created in the root of your Web application directory. This is a “bootstrap” file, meaning that all user interactions actually go through it. For example, showing an employee record might be through the URL www.example.com/index.php/employee/show/id/34 and updating a department record might involve submitting a form to www.example.com/index.php/department/update/id/3. Both URLs request just that one PHP script.
The index.php file is generated when you use the command-line yiic script. There’s only seven lines of non-commented code in it. The first identifies the location of the Yii framework:
The path indicated should already be correct (because it’s created when the framework is used to make the application), but you can change this value if you move the framework or the index file.
The second line identifies where the configuration file is:
The default behavior is to put the protected directory, where all the application files reside, in the same directory as the index file. My inclination is to move it outside of the Web directory, like so:
In such a case, I edit my index.php file to read:
Note that it’s perfectly reasonable to move the location of your application files (i.e., the protected folder), but you should not change the names or structure of the folders found within the protected directory.
Tip: Moving the protected folder outside of the Web root directory is just an extra security precaution. It’s not required, and you may not want to bother with the change, especially as you’re just getting started.
The next line of code turns on debugging mode:
defined('YII_DEBUG') or define('YII_DEBUG',true);
You’ll want debugging enabled when developing a site, but disabled once live. To disable debuggin, remove or comment out that line. I normally just comment it out, so that I can re-enabled debugging later. Or you can change it to something like this, so that you can add debugging to a page on the fly:
if (isset($_GET['debug'])) define('YII_DEBUG', true);
If you do that, then to debug any page on the fly, change the URL from, for example,www.example.com/index.php/site/contact to www.example.com/index.php/site/contact/debug/true.
The next line of code dictates how many levels of “call stack” are shown in a message log:
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
The “call stack” is a history of what files, functions, etc., are included, invoked, and so forth. With a framework, the simple loading of the home page could easily involve a dozen actions. In order to limit the logged (i.e., recorded) data to the most recent, useful information, the call stack is limited by that line to just the most recent three actions.
The last two lines of the bootstrap file include the framework and start the application. Don’t mess with these!
And that’s really all there is to do in the index.php page. As of Yii 1.1., the framework creates another bootstrap file: index-test.php. It is exactly the same as index.php, except that index-test.php includes a different configuration file: /protected/config/test.php instead of /protected/config/main.php. However, the test configuration file just includes the main configuration file, then also enables the CDbFixtureManager component, which is used for unit testing. The index-test.php file also omits the call stack limitation.
Most of the configuration occurs in the main.php configuration file, found within the protected/config directory (see the above image). There’s also a console.php config file, but that’s for a command-line version of the application. I won’t discuss that here, but you would edit it if you have command-line scripts associated with your application.
The configuration file returns a multi-dimensional array of information, some of which is pre-defined. You do want to make sure that the proper syntax is maintained as you edit this, so be careful in matching parentheses and using commas where necessary.
For starters, you’ll want to change the name of the application, which is used in the default HTML design, in page titles, and so forth:
'name'=>'Wicked Cool Yii Site',
Next, under the modules section of the returned array, you should enable Gii. Gii is a Web-based tool that you’ll use to generate Models, Views, and Controllers for the application. To enable Gii, just remove the comment tags—/* and */—that surround this code:
'gii'=>array( 'class'=>'system.gii.GiiModule', 'password'=>'SECURE', ),
Also enter a secure password in the code, one that only you will know.
Tip: Gii was added to Yii in version 1.1.2, and it replaces functionality available using the command-line Yii tools.
Moving down the file, in the components section of the returned array, you’ll probably want to enable urlManager. Just remove the comment code that surround the following:
'urlManager'=>array( 'urlFormat'=>'path', 'rules'=>array( '<controller:w+>/<id:d+>'=>'<controller>/view', '<controller:w+>/<action:w+>/<id:d+>'=>'<controller>/<action>', '<controller:w+>/<action:w+>'=>'<controller>/<action>', ), ),
This component changes URLs to be more search engine and user-friendly. For example, the default URL for a page could be something like www.example.com/index.php?r=site/contact, but urlManager will turn that into www.example.com/index.php/site/contact. If you want to take this further, it’s possible to configure urlManager, along with an Apache .htaccess file, so that index.php no longer needs to be part of the URL.
Next, you’ll almost always want to establish the database connection (unless you’re not using a database, of course). To do so, return an array that includes a connection string, a username, and a password. By default, a connection string is predefined for the SQLite database:
'db'=>array( 'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db', ),
If you’re using SQLLite, just change the code so that it points to the location of your SQLLite database. If you’re not using SQLLite, comment out or remove those three lines of code.
If you’re using MySQL, the proper code looks like:
'db'=>array( 'connectionString' => 'mysql:host=localhost;dbname=testdrive', 'emulatePrepare' => true, 'username' => 'username', 'password' => 'password', 'charset' => 'utf8', ),
The connection string is a DSN (Database Source Name), which has a precise format. It starts with a keyword indicating the database application being used, like mysql, pgsql (PostgreSQL), mssql (Microsoft’s SQL Server), or oci (Oracle). This keyword is followed by a colon, then, depending upon the database application being used, and the server environment, any number of parameters, each separated by a semicolon:
Indicating the database to be used is most important. For me, when using MAMP on Mac OS X, I had to set the port number as it was not the expected default (of 3306). On Mac OS X Server, I had to specify the socket, as the expected default was not being used there. Also do keep in mind that you’ll need to have the proper PHP extensions installed for the corresponding database, like PDO and PDO MySQL. You should obviously change the username and password values to the proper values for your database. You may or may not want to change the character set.
Within the log component section, I enable CWebLogRoute. This is a wonderfully useful debugging tool that adds tons of details to each rendered page. Here’s the code for the config file:
'log'=>array( 'class'=>'CLogRouter', 'routes'=>array( array( 'class'=>'CFileLogRoute', 'levels'=>'error, warning', ), array ( 'class' => 'CWebLogRoute' ) ), ),
And here’s an example output:
Finally, towards the end of the default configuration file you’ll find the adminEmail parameter. Change this to your email address, so that you receive error messages, contact form submissions, whatever:
'params'=>array( 'adminEmail'=>'firstname.lastname@example.org', ),
As you can tell, editing and adding components is where a lot of the configuration takes place. The ones I’ve highlighted are just the most immediately important, in my opinion, but there are certainly others, involving caching, security, themes, and more. One cool feature of Yii is that not all named components will be loaded for every request. Some, like the logging components are, but others are only loaded when required, thereby minimizing the performance impact of using many components.
One more configuration parameter that used to be in the default configuration file but now needs to be added is an indicator of the default controller. In other words, if no controller is specified in the URL, what controller will be called? Without further configuration, the “site” controller will be the default. To change that to a different controller, add:
'defaultController' => 'login',
Note that this particular line will not work out of the box as only the site controller exists. But you would make this change if you had created a protected/controllers/LoginController.php file (or if any controller file exists for whatever you make be the default). Also note that you add this line so that it’s a top-level array element being returned (i.e., it does not go within any other section; it’s easiest to add it between the “basePath” and “name” elements, for clarity).
And that’s a quick intro to configuring your Yii application. As always, thanks for reading and let me know if you have any questions or comments. In my next post, I’ll discuss a database design I’ll use in subsequent posts. After that, I’ll show you the magic: auto-generated Models, Views, and Controllers using Yii’s tools.