- Getting Started
- Initial Prototyping
- Post Management
- Comment Management
- Portlets
- Final Work
With the Post model ready, we need to fine-tune the actions and views for the controller PostController. In this section, we first customize the access control of CRUD operations; we then modify the code implementing the create and update operations.
The first thing we want to do is to customize the access control because the code generated by yiic does not fit our needs.
We modify the accessRules() method in the file /wwwroot/blog/protected/controllers/PostController.php as follows,
public function accessRules() { return array( array('allow', // allow all users to perform 'list' and 'show' actions 'actions'=>array('index', 'view'), 'users'=>array('*'), ), array('allow', // allow authenticated users to perform any action 'users'=>array('@'), ), array('deny', // deny all users 'users'=>array('*'), ), ); }
The above rules state that all users can access the index and view actions, and authenticated users can access any actions, including the admin action. The user should be denied access in any other scenario. Note that these rules are evaluated in the order they are listed here. The first rule matching the current context makes the access decision. For example, if the current user is the system owner who tries to visit the post creation page, the second rule will match and it will give the access to the user.
create and update OperationsThe create and update operations are very similar. They both need to display an HTML form to collect user inputs, validate them, and save them into database. The main difference is that the update operation will pre-populate the form with the existing post data found in the database. For this reason, the yiic tool generates a partial view /wwwroot/blog/protected/views/post/_form.php that is embedded in both the create and update views to render the needed HTML form.
We first change the _form.php file so that the HTML form only collects the inputs we want: title, content, tags and status. We use plain text fields to collect inputs for the first three attributes, and a dropdown list to collect input for status. The dropdown list options are the text displays of the possible post statuses:
echo $form->dropDownList($model,'status',Lookup::items('PostStatus'));
In the above, we call Lookup::items('PostStatus') to bring back the list of post statuses.
We then modify the Post class so that it can automatically set some attributes (e.g. create_time, author_id) before a post is saved to the database. We override the beforeSave() method as follows,
protected function beforeSave() { if(parent::beforeSave()) { if($this->isNewRecord) { $this->create_time=$this->update_time=time(); $this->author_id=Yii::app()->user->id; } else $this->update_time=time(); return true; } else return false; }
When we save a post, we want to update the tbl_tag table to reflect the change of tag frequencies. We can do this work in the afterSave() method, which is automatically invoked by Yii after a post is successfully saved into the database.
protected function afterSave() { parent::afterSave(); Tag::model()->updateFrequency($this->_oldTags, $this->tags); } private $_oldTags; protected function afterFind() { parent::afterFind(); $this->_oldTags=$this->tags; }
In the implementation, because we want to detect if the user changes the tags in case he is updating an existing post, we need to know what the old tags are. For this reason, we also write the afterFind() method to keep the old tags in the variable _oldTags. The method afterFind() is invoked automatically by Yii when an AR record is populated with the data from database.
We are not going to give details of the Tag::updateFrequency() method here. Interested readers may refer to the file /wwwroot/yii/demos/blog/protected/models/Tag.php.
See the Using Transactions in the Guide.
Hello,
first of all Thanks for Yii (TFY) !
As for my comment :
Maybe i ovelooked part of this tutorial so far but should it not specify that you need to add the tags input field in the form view for the saving of the tags to work ?
And also add a name attribute to the submit button in the form view for the changes to the PostController to work ?
CHtml::submitButton($update ? 'Save' : 'Create', array('name' => 'submitPost'));
Thank you for letting us know if this is intentional (or if I actually have not read correctly)
A non well formed numeric value encountered
And it is singling out this line as being the source of the error:
00024:
Also worth noting:
When the date/time value is being submitted to the database, it is going in as all 0's - 0000-00-00 00:00:00
Any help or suggestions would be helpful.
Thanks.
Peace
I've been missing a Query Object to avoiding SQL hardcoding
I wonder if it is better to use a transaction for the post and relative tag associations rows instead of using the beforeSave method
Change $post to $model in the 1.0.6 release:
<?php echo CHtml::activeDropDownList($post,'status',Post::model()->statusOptions); ?>
<?php echo CHtml::activeDropDownList($model,'status',Post::model()->statusOptions); ?>
The new code for the actionCreate function, checks which button (Submit or Preview) has been pressed by looking at:
$_POST'previewPost' or $_POST'submitPost'
This means you'll have to name both buttons. The code for the new Preview button looks like:
<?php echo CHtml::submitButton('Preview',array('name'=>'previewPost')); ?>Doing the same for submit button would result in:
<?php echo CHtml::submitButton($update ? 'Save' : 'Create', array('name'=>**'submitPost'**)); ?>I get this far with the tutorial, then when I try to post a comment I get the following error:
Missing argument 1 for Post::beforeValidate(), called in C:\wamp\www\yii\framework\base\CModel.php on line 147 and defined
Am not sure if i skipped something but the CRUD generates with me $model... but all references here use $post
beforeValidate timestamps do not work in mysql...
This helped me with the 00000 timestamp problem:
http://www.yiiframework.com/doc/cookbook/10/
Hello, thanks for this wonderful tutorial. How can we implement saving the data in one transaction, so we are free of orphan or missing records in case of a server failure? This applies here and on many other cases where you have to update or insert data in multiple tables.
Thanks again. Claudio.