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 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: http://www.yiiframework.com/doc/guide/1.1/en/database.arr#dynamic-relational-query-options
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 ' );
There is a Yii error I come across every now and again, and each time it stumps me.
If you ever get SomeModel.id 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'));
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("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-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()
'expression' => 'User::model()->hasRightsToFile()',
array('deny', // deny all users
And that’s about it. Controlled and forced file download with rewritten file urls.