I am writting my first application with Yii (v1.1.12), and the learning curve is a bit steep for me, so I need some help.

Imagine the following tables (with their relations):

  • detail (n:1) document
  • document (n:1) user
  • user (n:1) department
  • document (n:1) category

user is the table that holds the information about the users that can login and use the application.

I have managed to put together (using Gii and hacking about) a view that lists all the documents, and have also managed to display the category name instead of the category ID in the grid.

One of the features I want to implement is allow the user switch the view so (a) only the documents relating to the logged in user are listed, or (b) only the documents relating to his/her department.

I looked around a bit with no luck. Can anyone help?

Cheers, George

UPDATE: Currenlty I display the list of documents using zii.widgets.grid.CGridView.

UPDATE 2: Following Omar's reference to CDbCriteria I found this URL with a bit more detail on the subject.

I came up with the following model code, that works fine:

public function searchByUser($user_id)
{
   $criteria=new CDbCriteria;
   $criteria->condition = " user_id = ".$user_id;
   return new CActiveDataProvider($this, array(
          'criteria'=>$criteria,
   ));
}
public function searchByDepartment($user_id)
{
   $criteria=new CDbCriteria;
   $criteria->alias="p";
   $criteria->join = "JOIN (SELECT u.id 
                              FROM user u 
                             INNER JOIN user uu 
                                ON u.department_id = uu.department_id 
                             WHERE uu.id = ".$user_id.") uu 
                                ON p.user_id = uu.id";                  
    return new CActiveDataProvider($this, array('criteria'=>$criteria,));
}

While the above works as expected, I was hoping for a solution that would not require me to write chopped SQL code at all. Not due to lazyness, but just to leverage more of the functionality of the framework.

I just have the feeling that this approach doesn't follow best practices (?).

有帮助吗?

解决方案

Try to create your own CDBCriteria and define whatever conditions inside it and pass it as data provider to your grid view.

If you allowed the search inside the grid view, pass the criteria to the search function, and inside it, merge the passed criteria with criteria inside the search.

其他提示

You could use relations to achieve what you're after. For example, to view all the documents and departments of a certain user you first need to set up the relations for that user, in your case you could set your users model up like so;

public function relations()
{
    return array(
        'documents' => array(self::HAS_MANY, 'Document', 'user_id'),
        'department' => array(self::HAS_ONE, 'Department', 'department_id'),
    );
}

You can then pull all the documents for the current user like so:

$user = User::model()->findByPk($userId);
$documents = $user->documents;

$documents will then be an array of active models for all that users documents.

To obtain all the documents of that users department, there's a couple of options. You could use relations again, adding to the Department model the following:

public function relations()
{
    return array(
        'users' => array(self::HAS_MANY, 'User', 'department_id'),
        'documents' => array(self::HAS_MANY, 'Document', 'document_id', 'through'=>'users'),
    );
}

Which should give you the ability to pull all of a departments documents like so;

$department = Department::model()->findByPk($departmentId);
$documents = $department->documents;

Which in turn would mean you could grab the users department documents like so:

$user = User::model()->findByPk($userId);
$documents = $user->department->documents;

There may well be a more efficient way to grab those by using a relation in the Users model, but it's too late for me to work that our right now ;)

Once you have an array of active record models, you can always pass them to a data provider by using CArrayDataProvider like so;

$dataprovider = new CArrayDataProvider($documents);

I've not tested any of those by the way, so they may need some editing!

You need to modify the search function on the appropriate model (I'm going to guess at documents). You'll already be able to see code in there you can use.

Add some parameters to the search function itself, which can be passed in from the controller. Then use these to determine which compare calls to make.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top