fetch photos of an album in Yii (relation case) - php

I have two tables , one album and one photo. the photo table has a FK (album_id) which refer to id in album table.
now I want to show photos in CListview but I don't know how. :(
As I see it is uses dataProvider and I don't know how to combine relation with it.
would you help me?
Thank you masters.

It's simple
$dataProvider=new CActiveDataProvider('Photo', array(
'criteria'=>array(
'condition'=>'album_id=:album_id',
'params'=>['album_id'=>$album_id]
)
));
Then in view use this dataProvider:
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_photo'
));

First you should create the relation in you models.
In Album.php add sth like this:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'photos'=>array(self::HAS_MANY, 'Photo',array('album_id'=>'id')),
);
}
Similar in Photo.php:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'album'=>array(self::BELONGS_TO, 'Album',array('id'=>'album_id')),
);
}
Now you can use it in your code:
$dataProvider=new CActiveDataProvider('Photo', array(
'criteria'=>array(
'condition'=>'album_id='.$yourAlbumId,
)
));
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
...
));
If you need to refer to the Album in the CListview (let's say you have a field called "title" in the Album model), you can refer to it as $data->album->title in your items template.

Related

CActiveDataProvider using relations accessing foreign key data from another table

I have a relatively simple setup using Yii application but I'm struggling to access data across tables in the following scenario:
Two tables:
payments_info (id, data): where id is the primary auto increment key, model class name PaymentInfo
payments (id, payment_id, other_columns): here id is again a primary key and payment_id is foreign key pointing to one of the records in the payment_info table, model class name Payment
In the relations array inside the Payment model class I have the following:
'payment_id'=>array(self::BELONGS_TO, 'PaymentInfo', 'id'),
I haven't added anything in the PaymentInfo model's relations as technically it doesn't know anything about the other table.
I have a controller creating a CActiveDataProvider from the Payments model and showing all the records. In it, I'd like to have a field which would be showing the 'data' column from the PaymentInfo model but I have no idea how to get there.
In the cdbcriteria in the controller, used to create the data provider I tried using:
$criteria->with = array('payment_id');
And then in the view, inside the columns variable of the CGridView which displays the data provider I added:
array(
'name'=>'payment_id',
'visible'=>true,
'value'=> $data->payment_id->data,
),
I also tried different combinations of adding ' or " around the $data variable but with no success so far. I manage to get the correct payment_id displayed but I can't figure out how to display the 'data' value from the other table. Any tips appreciated!
you can use below method to Get Data From Another Relational Table in YII
Payment Model In Relation Function
public function relations()
{
return array(
'pinfos' => array(self::BELONGS_TO, 'PaymentInfo', 'payment_id'),
);
}
PaymentInfo Model In Relation Function
public function relations()
{
return array(
'payments' => array(self::HAS_MANY, 'Payment', 'payment_id'),
);
}
And In zii.widgets.grid.CGridView put this
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'post-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'pinfos.data',
/* other fields goes here*/
array(
'class'=>'CButtonColumn',
),
),
)); ?>
No need to do anything else.

Yii - Change column in CGridView for another model's field

In my model (let's say Model A) I have a field corresponding to the id of another model (Model B). In a CGridView composed of Model A items, instead of showing the id of Model B, I want to show another field of that model instance.
Here's how I am showing my CGridView;
$dataProvider = new CArrayDataProvider('Model A');
$dataProvider->setData($model_A_Data); // $model_A_data is an array of Model A Objects
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'data-id',
'dataProvider'=>$dataProvider, //$objects->search(),
'columns'=>array(
array('header'=>'Model A Id', 'name'=>'id'),
array('header'=>'Name', 'name'=>'name'),
array('header'=>'Date', 'name'=>'date_created'),
array('header'=>'Model B Id', 'name'=>'model_b_id'), // *HERE SHOW ANOTHER FIELD OF MODEL B*
),
));
How can I change that column in order to show another field of model B clasS?
Thanks
OK, I figured out how to solve this after discovering the $data var in CGridView which holds the corresponding row data.
Simply add this:
array('name'=>'Model B Another Field',
'value'=> 'ModelB::model()->FindByPk($data->id)->another_field'
),
say in Model A i have a relation
array('modelbrelationname','ModelB','id'),
So You can have the value like this
$dataProvider = new CArrayDataProvider('Model A');
$dataProvider->setData($model_A_Data); // $model_A_data is an array of Model A Objects
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'data-id',
'dataProvider'=>$dataProvider, //$objects->search(),
'columns'=>array(
array('header'=>'Model A Id', 'name'=>'id'),
array('header'=>'Name', 'name'=>'name'),
array('header'=>'Date', 'name'=>'date_created'),
array('header'=>'Model B Id', 'value'=>'modelbrelationname.id'), // *HERE SHOW ANOTHER FIELD OF MODEL B*
),
));

cake php accessing a table

I just started cakephp following there tutorials
I'm able to grab the posts table in my post controller and spew it onto my index.ctp
In my view for the post controller i also want to list the User name that posted the article. My post table has a user_id, so i need to match it to my user table and pass it along
class PostsController extends AppController {
public function index() {
//passes values to the view
$this->set('posts', $this->Post->find('all'));
//is "Post" a post method? or is it the name of the table? i'm unsure of the syntax
$this->set('users', $this->Users->find('all')); //this does not work
}
}
thank you for your help with this basic question
You must use 'recursive'
$this->Post->find('all', array(
'recursive' => 2,
// ...
));
Of course, you first need to link models together
I assume that you have already set a belongsTo association (Post belongsTo User) and/or a hasMany association (User hasMany Post). If so, cake will automaticly brings the associated models (unless you put $recursive = -1 on your model).
Thus you'll have access to the users related to each post on the view: posts[i]['User']
You can also use this on your view to see the view variables:
debug($this->viewVars)
put this on your Post model if you don't:
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
)
);
Make sure that you load models corretly (in case you want to load the User model inside PostsController).
So simply add this attribute inside your class controller.
public $uses = array('Post','User');
to link models together . u need to add the association inside your Post model .
public $belongsTo = array(
'User'=>array(
'className'=> 'User',
'foreignKey'=>'user_id'
)
);
and i you want to retrieve data from database you have to set your recursivity and there is two ways
first one :
$posts = $this->Post->find('all',array('recursive'=>2));
// or
$this->Post->recursive = 2;
$posts = $this->Post->find('all');
second one : use the Containable behavior
set the recursivity to -1 in the AppModel and include the behavior
public $recursive = -1;
public $actsAs = array('Containable');
so simply u can retieve posts with any other linked models like that
$posts = $this->Post->find('all',array(
'contain'=>array('User'),
// ...
)));

Change yii crud generated page

I have 2 models: taxiDrivers and taxiOrders. In taxiOrders I have a field driver_id, but instead of just an id, I want to output driver's name (which is located in taxiDrivers). Both models are generated via gii, and crud tools are also generated. The page which is needed to be changed is taxiOrders/admin (view: admin.php, models: TaxiOrders.php, TaxiDrivers.php and respective controllers)
2 DCoder: Thanks dude! but one more query I have and hope you can clearify: I have a standart generated admin.php view page with following code:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'taxi-orders-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'uid',
'did',
'type',
'notes',
//'or_lat',
//'or_lng',
//'des_lat',
//'des_lng',
'cost',
'rating',
'date',
'time',
'status',
array(
'class'=>'CButtonColumn',
),
),
)); ?>
and below code is for controller:public function actionAdmin()
{
$model=new TaxiOrders('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['TaxiOrders']))
$model->attributes=$_GET['TaxiOrders'];
$this->render('admin',array(
'model'=>$model,
));
}
So can u please show me where I could put your manipulations.
The Yii way would be to define a Relation between the two model classes (and enforce it with a Foreign Key). Then Yii would know how the two classes are related and you would have an easier time loading the related data.
In the TaxiOrders model class, a relation would look like this:
/**
* #property TaxiDrivers $Driver
*/
class TaxiOrders extends CActiveRecord {
// ...
public function relations() {
return array(
'Driver' => array(self::BELONGS_TO, 'TaxiDrivers', 'driver_id'),
);
}
// ...
}
In the controller, when you load the order data, you can prefetch the associated driver data like this:
public function actionOrderInfo($orderID) {
$order = TaxiOrders::model()->with('Driver')->findByPk($orderID);
// render it
}
with('Driver') will make sure that each returned order has its driver info already loaded, no matter if you need to find one record or a lot of records. It is a lot more efficient than trying to load that related data yourself.
In the view, you can output the driver info like this:
echo CHtml::encode($order->Driver->Name);
Unless you have a foreign key to ensure data integrity, it is possible that the Driver has been deleted without clearing his existing orders... In that case $order->Driver will be NULL and the line above will cause an error. Figuring out how to avoid it should be obvious.
In TaxiOrders admin use this to display driver name
TaxiDrivers::getName($data->driver_id);
Now in the TaxiDrivers Model write a function with sql query to get the driver name like this...
public function getName($getid) {
$sql = "SELECT name from `taxi_drivers` where `driver_id`='$getid'";
$command=yii::app()->db->createCommand($sql);
$rs = $command->queryScalar();
return $rs;
}
I Hope it will help you..
I always prefer Query Builder approach instead of Active record approach in joined scenarios. Like that
First Get Data through Query Builder
public function getTaxtOrder($id) {
$select = Yii::app()->db->createCommand()
->select('to.*, td.name as driver_name')
->from('TaxiOrders to')
->join('TaxiDriver td', 'td.id = to.driver_id')
->where('to.id = :id', array(':id' => $id));
return $select->queryRow();
}
Then Pass through controller
$data = TaxiOrders::model()->getTaxtOrder($id);
$this->render('view',array(
'data' => $data
));
Last use this into views
$this->widget('zii.widgets.CDetailView', array(
'data'=>$data,
'attributes'=>array(
array('label' => 'Order No', 'value' =>$model['order_no']),
array('label' => 'Driver Name', 'value' =>$model['driver_name']),
array('label' => 'Date', 'value' =>$model['order_date']),
),
));
This approach easily and flexibly work with multiple joined tables than Active Record Approach.

unable to fetch records from multiple tables using join

I am using Yii framework. i am wonder how i can get records from multiple tables i did research but couldn't find any usefull link i am using following code for this please let me know where i am missing
my model Task.php
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'prj_user' => array(self::BELONGS_TO, 'User', 'id'),
);
}
model User.php
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
array('task', self::HAS_MANY, 'Task','project_id')
);
}
and this is my main controller
$criteria = new CDbCriteria;
$criteria->compare('t.id', 1);
$criteria->with = array( 'prj_user' => array('select' => 'username,title,roles', 'joinType'=>'inner join'));
$rows = Task::model()->findAll( $criteria );
but still i am getting columns only from task table but i need more three columns from users table please help me
Let Yii worry about joining your tables. Your relations looks fine so you should be able to access them directly
For example, what does this return?
foreach ($rows as $task)
{
if ( isset($task->prj_user) )
echo $task->prj_user->username . "<br>";
}
Or this?
this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>new CActiveDataProvider('Task'),
'columns'=>array(
'id',
'prj_user.username',
'prj_user.title',
'prj_user.roles',
)
));
->with() is used for eager loading, so at this point you probably don't need it. In fact, unless I misread you completely, you can remove your criteria all together.

Categories