Posts categorized “Yii”.

Yii (and Yii2) wildcard / catch all url rules

Sometimes you might want to do various checks of the url in yii config main and then send every other request to a particular controller.

The rule you need to add last to the urlManager is…

'(.*)' => 'controller/action',

… and now any rule that isn’t matched previously will end up being sent to your defined controller and action.

In Yii2 you can do the following:

'<url:(.*)>' => 'controller/action',

Reordering Yii Results Without Another Select


In case you weren’t aware, you can reorder the results you already have from a previous Yii call. For example…

$users = User::model()->findByPk(2);
$posts = $user->posts(array('order'=>' created Desc '));

There were just ordered our users posts by created date descending.

We can also do filtering…

$users = User::model()->findByPk(2);
$posts = $user->posts(array('condition'=>' status=1 '));

So now we only have active posts. We could also combine a condition and a status.

You can find out more here:

Yii (and Yii2) UpdateAll Example


This is a simple example of how to use Yii’s updateAll():

In this example we want to set status = 1 WHERE type_id = 1 AND status = 0

Note this is a simple example where we are only updating one column and using a string for our condition. There are more complex options available.

Comment::model()->updateAll(array( 'status' => 1 ), 'type_id = 1 AND status = 0' );

So as you can see first comes an array of column => new_value pairs, then a condition string which is pretty much used as the WHERE clause.

An example of updating more than one column:

Comment::model()->updateAll(array( 'status' => 1, 'updated' => '2011-08-25 09:33:23' ), 'type_id = 1 AND status = 0 ' );

Update. Yii2 example:

Updating a single column:

Comment::updateAll(['status' => 1], 'type_id = 1 AND status = 0');

Updating multiple columns:

Comment::updateAll(['status' => 1, 'updated' => '2011-08-25 09:33:23'], 'type_id = 1 AND status = 0' );

Yii – “” not defined for CArrayDataProvider and CSqlDataProvider etc


There is a Yii error I come across every now and again, and each time it stumps me.

If you ever get not defined error when trying to put your dataprovider results into a cgridview or similar then it’s likely because

1) Your model doesn’t have an id column, it might use file_id or user_id etc instead and

2) You haven’t defined which other column should be used.

We do this using what’s known as keyField:

new CArrayDataProvider($users, array('keyField' => 'user_id'));
new CSqlDataProvider($users, array('keyField' => 'user_id'));

Yii – Rewrite file or image urls for download or display


I recently had a need to track files and images which were uploaded and for their urls to be secret. This meant that they couldn’t sit in a folder waiting to be found and had to be saved below the site root.

To get access to them I wanted to the check the user permissions followed by forcing download of all files (including images). Here are the steps I took to accomplish this…

For the sake of this page, my (fake) file urls are something like:

Update the urlmanager to rewrite files to my filemanager/view:

	'user/<user_id:\d+>/file/<id:\d+>.[a-z0-9]+' => 'filemanager/view',

Update the filemanager class’ actionView function:

	public function actionView($id)
		$file = $this->loadModel($id);
		header("Pragma: public"); // required
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: private",false); // required for certain browsers 
		//header("Content-Type: " . $file->mime_type);
		header("Content-Disposition: attachment; filename=\"" . str_replace(" ", "-", preg_replace("@[^a-z0-9 ]@", "", strtolower($file->file_name))) . '.' . $file->file_extension . "\";" );
		header("Content-Transfer-Encoding: binary");
		header("Content-Length: ".filesize(Yii::app()->basePath . '/../../uploads/user_files/' . $file->file_id . '.' . $file->file_extension));
		readfile(Yii::app()->basePath . '/../../uploads/user_files/' . $file->file_id . '.' . $file->file_extension);

I also of course required filemanager access to be strict:

	public function accessRules()
		return array(
				'actions'=>array('view', 'create','delete'),
				'expression' => 'User::model()->hasRightsToFile()',
			array('deny',  // deny all users

And that’s about it. Controlled and forced file download with rewritten file urls.