Tutorial: Remove index.php on localhost in Yii framework

This is another simple tutorial i find it useful for every Yii framework developer to know. Especially people who really want SEO capability on their Yii project. Without further crap from me, i will demonstrate how this can be done.

Setup Apache

The most important thing to get the thing you want in a local environment is to setup your Apache properly. Luckily setting up Apache for this tutorial wasn't that difficult, all you have to do is two step. Firstly, fire up your httpd.conf and look for the following line.

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>

Change AllowOverride None to Allow as shown below,

<Directory />
    Options FollowSymLinks
    AllowOverride All
    Order deny,allow
    Deny from all
</Directory>

Next we will have to enable mod_rewrite. Look for the following line,

#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule rewrite_module modules/mod_rewrite.so
LoadModule setenvif_module modules/mod_setenvif.so
#LoadModule speling_module modules/mod_speling.so
#LoadModule ssl_module modules/mod_ssl.so
#LoadModule status_module modules/mod_status.so

And uncomment LoadModule rewrite_module bla bla bla and we should get something like this.

#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule setenvif_module modules/mod_setenvif.so
#LoadModule speling_module modules/mod_speling.so
#LoadModule ssl_module modules/mod_ssl.so
#LoadModule status_module modules/mod_status.so

Now, save this changes and restart your Apache server and we are done here.

Setup .htaccess

Now, the important thing is to tell Apache how to handle things that we are going to setup on our Yii framework. Hence, we will have to write some .htaccess rule to cater this. Firstly, where to place this?! Simple, we will put this just at the level where the "/protected/" folder is located (not inside the protected folder). Next, we should create a new .htaccess file with the following rules.

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
RewriteBase /project name/

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

The whole world are using this rule so i won't bother to explain but do take note that you will need to rebase your project by changing "project name" to your folder name on this .htaccess file. And we are done here too.

Setup Yii Config

Finally, we can setup our Yii config! Fire up your /config/main.php file and overwrite your UrlManager rules with the following one.

		'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>',
			),
			'showScriptName'=>false,
			'caseSensitive'=>false,
		),

Once you do this, you should be gettting your index.php removed permanently!

Tutorial: How To Reuse Yii Contact Form

Here's another tutorial on Yii framework that i find it useful to write it down. I was using Yii framework on a project currently and wanted to reuse Yii built-in contact from into another view. Reusing Yii framework contact form is pretty straight forward until i find my captcha not showing out for some reason. Lucky, i manage to get it work with a little debugging and decides to write it down just in case someone gets stuck as well.

Contact Form Model

In order to reuse Yii contact form, we do not need to rebuild another new model for our contact form. Unless you want to do something extra that will affect your existing contact form model, you can actually reuse the model without creating a new one. In short, we can skip the model 😀

Contact Form View

Next, the model part will also be pretty straight forward. Since we are using the same model, all you have to do is to copy the content on the contact form view into your own view file. In this case, it will be these:

<?php $form=$this->beginWidget('CActiveForm'); ?>

	<p class="note">Fields with <span class="required">*</span> are required.</p>

	<?php echo $form->errorSummary($model); ?>

	<div class="row">
		<?php echo $form->labelEx($model,'name'); ?>
		<?php echo $form->textField($model,'name'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'email'); ?>
		<?php echo $form->textField($model,'email'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'subject'); ?>
		<?php echo $form->textField($model,'subject',array('size'=>60,'maxlength'=>128)); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'body'); ?>
		<?php echo $form->textArea($model,'body',array('rows'=>6, 'cols'=>50)); ?>
	</div>

	<?php if(extension_loaded('gd')): ?>
	<div class="row">
		<?php echo $form->labelEx($model,'verifyCode'); ?>
		<div>
		<?php $this->widget('CCaptcha'); ?>
		<?php echo $form->textField($model,'verifyCode'); ?>
		</div>
		<div class="hint">Please enter the letters as they are shown in the image above.
		<br/>Letters are not case-sensitive.</div>
	</div>
	<?php endif; ?>

	<div class="row buttons">
		<?php echo CHtml::submitButton('Submit'); ?>
	</div>

<?php $this->endWidget(); ?>

That's it.

Contact Form Controller

The trick to reuse Yii contact form lies on the controller. The main code without saying would be the following one.

		$model=new ContactForm;
		if(isset($_POST['ContactForm']))
		{
			$model->attributes=$_POST['ContactForm'];
			if($model->validate())
			{
				$headers="From: {$model->email}\r\nReply-To: {$model->email}";
				mail(Yii::app()->params['adminEmail'],$model->subject,$model->body,$headers);
				Yii::app()->user->setFlash('contact','Thank you for contacting us. We will respond to you as soon as possible.');
				$this->refresh();
			}
		}
		$this->render('contact',array('model'=>$model));

The render part you would need to change that because it will most likely be your view file instead. Next important things to take note of would be the captcha part.

You would need to add another method called 'action' which will define a need method for your captcha image to be created as shown below,

/**
	 * Declares class-based actions.
	 */
	public function actions()
	{
		return array(
			// captcha action renders the CAPTCHA image displayed on the contact page
			'captcha'=>array(
				'class'=>'CCaptchaAction',
				'backColor'=>0xFFFFFF,
			),
		);
	}

Next, you will need to add captcha action into your permission list in order for it to display out else you would find that your image will always be empty although you did everything correctly. (no permission. Hence, permission denial)

	/**
	 * Specifies the access control rules.
	 * This method is used by the 'accessControl' filter.
	 * @return array access control rules
	 */
	public function accessRules()
	{
		return array(
			array('allow',  // allow all users to perform 'index' and 'view' actions
				'actions'=>array('index','view', 'captcha'),
				'users'=>array('*'),
			),
			array('allow', // allow authenticated user to perform 'create' and 'update' actions
				'actions'=>array('create','update'),
				'users'=>array('@'),
			),
			array('allow', // allow admin user to perform 'admin' and 'delete' actions
				'actions'=>array('admin','delete'),
				'users'=>array('admin'),
			),
			array('deny',  // deny all users
				'users'=>array('*'),
			),
		);
	}

Once this is done, you should get your reused Yii contact form working on your new view file!

Summary

In case you are not interested in all of the tutorial, Here are the summary that you should take note of:

  • Contact Form is also build in MVC
  • You do not need to rebuild the model class unless you wanted something different
  • You will need to placed the code on the contact form controller into your own controller file
  • You will need to copy and paste the contact form view file into your own view file
  • Remmeber to add the action sections in order to use 'captcha' on your contact form.
  • Remember to allow 'captcha' action by users or else the image will never display