I have three tables that look something like this:
USER
user_id
…
TRIP_USER
user_id
trip_id
f_user_admin
…
TRIP
trip_id
…
What I want to do, in my view index for Trips, is to show only (1) the trips for which the logged-in user has access too (if user and trip are in TRIP_USER), and (2), whether the user is an administrator for each trip (f_user_admin = 1) that is listed.
From what I can see in my research of Relational Active Record in the documentation, Named Scopes could be my answer(see http://www.yiiframework.com/doc/guide/1.1/en/database.ar#named-scopes). I have to admit that I am overwhelmed as to how I will implement this in my application.
Should I create the scope in the TripUser model and then access it through relations in Trip? Or should the scope be defined in the Trip model, by referencing fields from TripUser?
Any guidance, including code to point me in the right direction would be appreciated.
I assume “userTrips” and “trips” are relations? If so, I’ll use the code you suggested, but with my actual relation names. And how exactly would I incorporate your suggestion into the the following functions of my TripController:
public function actionIndex()
{
$dataProvider=new CActiveDataProvider('Trip');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
and
public function actionUpdate($id)
{
$model=$this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Trip']))
{
$model->attributes=$_POST['Trip'];
if($model->save())
$this->redirect(array('view','id'=>$model->trip_id));
}
$this->render('update',array(
'model'=>$model,
));
}
In the last one, I want to make sure that the user has access to the specific trip he is trying to view.
However, I am getting the following CException: Property “Trip.id” is not defined. What’s weird is that the primary key for my Trip table is not id, but in fact trip_id. So I’m not sure why it’s looking for Trip.id.
I know I’m close, because if I do
print_r($user->tblTrips);
The resulting array contains all the data that I’m looking for. Can you shed some light on what I’m missing?
One last thing. I want to make sure that a User can only get to the Update screen if he has access to the Trip he is trying to modify. Essentially, he should only be able to do so if there is a record with his user_id and the trip_id in the TRIP_USER table. I read the documentation on RBAC, but it seems to be overkill for what I am trying to do. I tried modifying the loadModel function as below, but I’m getting a PHP Error of “Object of class User could not be converted to string”:
public function loadModel($id)
{
$user = User::model()->findByPk(Yii::app()->user->getId());
$model=Trip::model()->$user->tblTrips->findByPk((int)$id);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
Should the loadModel be modified for what I am attempting to do? Or should the change instead occur in actionUpdate (see current code bewlow)?
public function actionUpdate($id)
{
$model=$this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Trip']))
{
$model->attributes=$_POST['Trip'];
if($model->save())
$this->redirect(array('view','id'=>$model->trip_id));
}
$this->render('update',array(
'model'=>$model,
));
}
I like what you suggested earlier in your post #3, but that would get ALL trips for the user. In this case, I still have the user_id, but I also have a trip_id that I need to incorporate. I am unsure how to do that.
The problem with that is that it returns the TripUser model, when in fact I am looking for the Trip model according to specific trip_id (from $_GET) and user_id (from Yii::app()->user->getId()).
Maybe I’m going about this all wrong. In actionUpdate(), before calling loadModel(), maybe I should call a custom function to see if there is a record with user_id and trip_id in the TRIP_USER table, meaning that the user has action to the trip? What do you think?
Like with so many things in Yii, I just want to avoid taking an alternate route when there is possibly already built-in functionality that can accomplish what I am trying to do.
Well you have … logic problems, please try to analyse a little more what you are doing and what you need, this is very simple.
what about?
public function loadModel($id)
{
$model = TripUser::model()->findBypk(array("user_id" => Yii::app()->user->getId(), "trip_id" => $id));
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model->trip;
}
That worked beautifully. I wouldn’t say I had logic problems. I knew exactly what I wanted to do. I was just struggling on how to get it done within Yii.
Thanks for your patience and for giving me a hand when, obviously, others chose not to! I have a better understanding on how to apply relations in Yii.
I find that offending and far from the gentle conversation standard we happily have been used to in this forum since Yii was born.
And even if we are, it’s on our own discretion to answer or not.
Personally I use to drop an answer from the top of my memory if I think it will be meaningful and I’m convinced to some extent it would be correct (which it may not).
I don’t think it’s meaningful to answer a person that registered five minutes ago, asking the same question that already was answered in a different thread a couple of hours earlier. Also, there’s most probably some not so fresh newcomers that experienced the same thing just recently and can give a working solution without spending any time at all on research/searching older information somewhere. And very often the person asking the question immediately finds out the answer him/herself.
Sometimes I locate older information if I find it meaningful to refresh my understanding of the topic.
On other occasions I choose to dig into some problem for the reason of educating myself by finding a working solution (not necessarily the best one).
Less often I choose to post an untested answer, pointing that out by adding “not tested”, “IIRC” etc. Especially in those cases it’s even more valuable to get feedback. If feedback is not given, it’s totally meaningless from my point of view to post hints that’s not relying on my own recent testing. Sooner or later somebody that now the working solution most probably will come by.
I hope you now got a better understanding of why you sometimes get an immediate answer and sometimes have to wait, or even refresh the thread if it’s been forgotten of. And if this isn’t acceptable for you, at least you have the definitive guide and api reference to rely on.