Returning Database Results Based on User ID – Yii Framework

Since I’m new when it comes to working with the Yii framework it took me a few of hours to figure out how to selectively pull data from the database when loading a model and it’s data. So in order for this to make sense to those of you that have no idea on what I was  trying to achieve I need to give a little background.

For the current Yii project that I’m making I first needed a solid foundation for user management and instead of potentially re-creating the wheel I searched to see if there was an existing solution. I found a Yii module entitled Yii User. Yii User gives a Yii project basic user management functionality. This module also has a few basic class functions that allow to check if a user is an admin, list all admins, various calls to get information on users, and most importantly for us their user id. I will also be doing an entry for installing this module because the directions that are given on that link that I provided aren’t the clearest.

After I got the Yii User module squared away I made a new Model and CRUD operations for this new model via the Gii functionality. For the purposes of this howto we’ll go ahead and call our new model Cars.

When a user creates a new entry using the Cars model their user id is saved along with this data. Now when we go to the index page of this Cars model on the site it lists all entries from the database. This out-of-the-box functionality isn’t realistic to a real world application because when I’m logged into the site and go to the cars index I should be able to only see my list of cars and not the entire site’s list of cars. So we have to somehow tell the system that we only want to list the cars that are associated with the currently logged-in user.

To the point:

When a model’s data is loaded it utilizes a function in it’s controller called actionIndex and within this function we can see that it initializes an object called CActiveDataProvider. When someone views the main index page of a model it loads all of the information from the database via a variable called $dataProvider. You can see this in action if we go to the following file and look at the bottom portion: “protected->views->cars->index.php”. So where does the $dataProvider variable get it’s data? Well the CActiveDataProvider object of course.

When a model and it’s controller are made by the automation process provided by the Gii functionality it fails to fully utilize all of CActiveDataProvider’s functionality which is why it took me forever to figure out that this is indeed where I need to be in order to accomplish what I needed. During my hours long search for an answer I came upon this link that gives an example of how we could use some advanced features of CActiveDataProvider. In Yii there’s an object that works in conjunction with CActiveDataProvider that provides these advanced features called CDbCriteria. This object basically gives the developer the ability to provide some arguments to CActiveDataProvider in order to narrow/filter it’s results. So if we go to Yii’s API documentation for CDbCriteria we can see that there is a function called addSearchCondition.

Putting it all together:

Going back to the actionIndex function within the Cars controller we can see that the original code looks something like the following:

public function actionIndex()
{
    $dataProvider=new CActiveDataProvider('Cars');
    $this->render('index',array(
        'dataProvider'=>$dataProvider,
    ));
}

Combining the Yii User module functionality with CDbCriteria to achieve a more realistic database interaction:

public function actionIndex()
{
    // Get the user object and assign the user id
    $userObject = Yii::app()->getModule('user')->user();
    $userId = $userObject->id;
    // Create a new CDbCriteria object
    $criteria = new CDbCriteria();
    // Assign search criteria
    $criteria->addSearchCondition( 'user_id', $userId, true, 'OR' );
    // If the user is an admin then show all.
    // Otherwise show only cars that belong to the user.
    if(Yii::app()->getModule("user")->isAdmin()){
	$dataProvider=new CActiveDataProvider('Cars');
    }else{
	$dataProvider=new CActiveDataProvider('Cars',array(
                              'criteria'=>$criteria,
                          ));
    }
    // Initialize the $dataProvider variable that will be used
    // on the index.php page
    $this->render('index',array(
	'dataProvider'=>$dataProvider,
    ));
}

Explanation of above code:

First we are initializing the user module and assigning the user object to a variable called $userObject. Remember, this object is for the current user that is logged in. Then we are pulling the user id out of the user object and assigning it to a variable that we’ll use within our criteria filter. After we’re done with getting our user information we need to initialize the CDbCriteria object ($criteria) and add a search parameter via the addSearchCondition function. Then we implement a simple if/else statement basically saying “If the current user is an admin then thay can see all of the data. (Else) If they aren’t an admin then they can only return data that is associated with their user id.”. The last part is essentially assigning the data that has been retrieved from the database to the $dataProvider variable that will be used on the index.php that was mentioned earlier.

For more information on CActiveDataProvider go here and for more information on CDbCriteria go here.

If you have any questions feel free to leave a comment and I’ll get back to you as soon as possible.

This entry was posted in Web Development, Yii and tagged , , , , , , , , , , , . Bookmark the permalink.

5 Responses to Returning Database Results Based on User ID – Yii Framework

  1. Ray Stoeckicht says:

    Looks like things are going well with development. What kind of project are you currently working on? Have you run into any object relation mapping class requirements? My colleague and I have been working on a CRM system built on top of Yii and have utilized RedbeanPHP (www.redbeanphp.com). Might be handy down the road.

    • dvarney says:

      I don’t really want to go into great details at this moment as to what exactly I’m working on with Yii. So far I haven’t had any issues with Yii and what it offers. My only complaint with Yii is that it should be slightly more user-friendly within the documentation. There is some parts of it that just doesn’t go into great detail.

    • dvarney says:

      I just checked out the redbeanphp.com link and it looks pretty interesting. I could see myself using it and it reminds me a little of the Recess framework (not entirely but a little bit). You could sum up Recess as a cross between Yii and Red Bean.

  2. Your homemade distillation controller looks very interesting. It is evident that you have solid technical acumen. We have been working on a new open source CRM project over the past year. It is written in PHP utilizing JQuery, Yii, and RedBeanPHP and relies heavily on test driven development. It would be incredibly helpful to get your technical feedback and recommendations so that we can improve the application.
    http://zurmo.org

  3. Kibe Wachira says:

    Thanks dvarney. i am a newbie in developing with yii but this article helped me a great deal, i was able to display data for only logged users in a CGridView by rendering the model in the controller together with the dataprovider then in the CGridView widget changed the attribute dataProvider to use the rendered provider. However with doing this the search functionality is not working

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>