Paginating and retriving data with CakePHP - cakephp

Hi
I'm trying to to do pagination from the KindsController but with data from the LinkModel
Tables :
Kinds links
id id
name title
order url
kind_id
order
model:
class Kind extends AppModel{
var $name = 'Kind';
var $hasMany = 'Link';
}
controller:
class KindsController extends AppController{
var $name = 'Kinds';
var $paginate = array(
'Kind'=> array(
'limit' => 12,
'order'=> array('Kind.order'=>'ASC')
)
);
}
desired result (view) ;
Kind.name ( numbers of links )
links.name
........
..........
Kind.name ( numbers of links )
links.name
........
..........
i'm using the kinds.order and links.order to control how the data is displayed in the view
from an admin area.
i need to retrive data from the kinds table ordered by kinds.order ASC and the number of links, and the links data ordered by links.order
thanks

You can define order in the relation like this:
class Kind extends AppModel{
var $hasMany = array(
'Link' => array(
'className' => 'Link',
'order' => 'Link.name'
),
);
}

Related

How to save multiple images with a hasMany relationship in CakePHP?

How can I save multiple images in the secondary table?
My first table is Car, which has the fields:
id
title
featured_image and
My secondary table is Gallery, which has the fields:
id
car_id
gallery_images
Model Car.php
class Car extends AppModel
{
var $name='Car';
var $hasOne = array(
'Gallery' => array('className' => 'Gallery',
'foreignKey' => 'car_id'
));
}
Model Gallery.php
class Gallery extends AppModel
{
var $name='Gallery';
var $belongsTo = array(
'Car' => array('className' => 'Car',
'foreignKey' => 'car_id',
)
);
}
CarController.php
$this->Car->saveAll($this->data)
To save multiple images associated to a car, first you have to modify your Car model to:
class Car extends AppModel
{
var $hasMany = array(
'Gallery' => array(
'className' => 'Gallery',
'foreignKey' => 'car_id'
));
}
or just
class Car extends AppModel
{
var $hasMany = array('Gallery'); //simplified version, as fields follow convention
}
Then you have to structure you data as follows:
$data = array(
'Car' => array('title' => 'Volvo'),
'Gallery' => array(
array('gallery_images' => '/path/image1'),
array('gallery_images' => '/path/image1'),
array('gallery_images' => '/path/image3'),
),
);
In your view, the form should have the following structure:
echo $this->Form->create('Car', array('action' => 'add'));
echo $this->Form->input('Car.title');
echo $this->Form->input('Gallery.0.gallery_images');
echo $this->Form->input('Gallery.1.gallery_images');
echo $this->Form->input('Gallery.2.gallery_images');
echo $this->Form->end();
In your CarControllers::add() you can save all four records (one car and three images) with:
$this->Car->saveAll($this->request->data);
Please consider renaming your fields to represent better your data. For example, gallery_images should be renamed to something like image_filename, and model Gallery to Image of Photo.
As per Car.featured_image, it can hold a foreign key for galleries, or you can move this field on to the galleries/images table and make it a field named type (holding 'featured, normal, etc'), or perhaps a boolean named is_featured.

CakePHP - linking models together

I have a few Tables/Models and I want to show the content of the models in one view.
My Schema:
My Models:
Adress:
var $name = "Adress";
public $belongsTo = array("Customer", "Country");
public $hasAndBelongsToMany = array(
'Contactperson' => array(
'className' => 'Contactperson'
)
);
ContactPerson:
var $name = "Contactperson";
public $hasAndBelongsToMany = array(
'Adress' => array(
'className' => 'Adress'
)
);
Country:
var $name = "Country";
public $hasMany = "Adress";
Customer:
var $name = "Customer";
public $hasMany = array(
'Adress' => array(
'className' => 'Adress',
'order' => array('Adress.mainadress DESC', 'Adress.created DESC')
)
);
My CustomerController:
$customer = $this->Customer->findByid($customerId);
$this->set('customer', $customer);
The return value is the content of the customer and the adress table but I want to get the content of every table.
I want to get a array with the content from customers, addresses, contactpeople and countries.
Thanks for helping.
Once you setup and linking each table correctly (with foreign key and db design), then you can retrieve all the related field easily with CakePHP.
Read up on CakePHP containable.
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
Recursive will also works, but higher recursive value can hurt your system if its getting too big.

find('all') doing unexpected (unwanted) SQL join in CakePHP

I've set up two models: city, and country. Below is how I've defined them:
class City extends AppModel { // for "cities" table
public $hasOne = 'Country';
}
class Country extends AppModel { // for "countries" table
public $hasMany = array(
'City' => array(
'className' => 'City'
)
);
}
and in my controller:
public function getCities() {
$this->loadModel('City');
$cities = $this->City->find('all');
}
but it's giving me this error:
Database Error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Country.city_id' in 'on clause'
SQL Query: SELECT `City`.`id`, `City`.`country_id`, `City`.`name`, `City`.`latitude`, `City`.`longitude`, `City`.`time_zone`, `City`.`dma_id`, `City`.`code`, `City`.`created`, `City`.`modified`, `Country`.`id`, `Country`.`country_id`, `Country`.`name`, `Country`.`code`, `Country`.`created`, `Country`.`modified` FROM `rtynbiz_ls`.`cities` AS `City` LEFT JOIN `rtynbiz_ls`.`countries` AS `Country` ON (`Country`.`city_id` = `City`.`id`) WHERE 1 = 1
Notice: If you want to customize this error message, create app/View/Errors/pdo_error.ctp
I can't understand why it's trying to do a join with Country table. I only want to fetch cities. How do I stop this from happening? And, why is it trying to make an association using Country.city_id (which doesn't exists) Also, have I named my classes and tables correctly? Thanks
Following lines of code are making relationship so JOIN is present there. To remove the JOIN from the query just replace :
class City extends AppModel { // for "cities" table
public $hasOne = 'Country';
}
class Country extends AppModel { // for "countries" table
public $hasMany = array(
'City' => array(
'className' => 'City'
)
);
}
With:
class City extends AppModel { }// for "cities" table
class Country extends AppModel {} // for "countries" table
You can make relationships in the tables easily by following this
By default, CakePHP will automatically try to pull additional model's data. To stop that from being the default, in your AppModel, set this variable:
public $recursive = -1;
I would also suggest adding Containable behavior, so your app model looks like this:
<?php
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
}
Read more about "recursive" and "Containable Behavior" at the CakePHP book.
If you don't want to do join when you want to retrieve your data make it recursive -1
public function get_cities() {
$this->loadModel('City');
$this->City->recursive=-1;
$cities = $this->City->find('all');
//or
$cities = $this->City->find('all', array('recursive'=>-1));
}
any way this would be your model:
class Country extends AppModel {
public $hasMany = array(
'City' => array(
'className' => 'City',
'foreignKey' => 'country_id',
'dependent' => false,
),
);
}
class City extends AppModel {
public $belongsTo = array(
'Country' => array(
'className' => 'Country',
'foreignKey' => 'country_id',
)
);
}
make sure you don't have messy code on these 2 models

CakePHP Join virtualField as displayField

I'm trying to do one of two things, use a virtual field from a model as the display field in my join model, or use the virtual field as the display in a find('list') on my join model.
Here's the current layout:
MODELS
<?php
class Participant extends AppModel {
public $hasMany = array('Registration');
public $virtualFields = array(
'full_name' => 'CONCAT(last_name, ", ", first_name)'
);
public $displayField = 'full_name';
}
-----
class Contest extends AppModel {
public $hasMany = array('Registration');
}
-----
class Registration extends AppModel {
public $belongsTo = array('Participant', 'Contest');
public $hasMany = array('Assignment');
}
?>
Tables are as follows:
participants contests registrations
------------ --------- --------------
id id id
first_name name contest_id
last_name participant_id
In my contests controller I'm trying to develop a list to be viewed as checkboxes in the view.
Here is the excerpt from my contests controller:
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
)
);
//$contestId is defined previously, and I have verified such.
This all actually runs fine as it is, and in the view will display a column of checkboxes with the registration_id as the label next to the checkbox.
I would like to get a full_name as is defined in the Participant model to be the displayField of the Registration model. I've been searching and can't quite seem to find a good way of doing that. I hope I have been descriptive enough, and please let me know if you have any questions and I'll try to explain better. Thank you.
edit: I'm using CakePHP 2.4.
try to add the 'fields' parameter
$this->loadModel('Registration');
$this->set('registrations', $this->Registration->find(
'list',
array(
'fields' => array('Registration.id', 'Participant.full_name'),
'conditions' => array('contest_id' => $contestId),
'recursive' => 1
)
));
edit: apparently cake does not place virtual fields of associated models when using find() with 'fields' options.
So you have to build your array by yourself, hoping your models use the containable behavior
$registrations = $this->Registration->find(
'all',
array(
'contain' => array(
'Participant' => array('full_name')
),
'conditions' => array('contest_id' => $contestId),
)
);
$registrations = Hash::combine($registrations, '{n}.Registration.id', '{n}.Participant.full_name');
$this->set('registrations', $registrations);

CakePHP bindModel working, preset Model associations not

I am in development of a personal project.
I have two models 'Show' and 'Episode'. I have one controller 'Ops'.
Show model:
class Show extends AppModel
{
var $name = 'Show';
var $hasMany = array(
'Episode' => array(
'className' => 'Episode',
'foreignKey' => 'show_id'
)
);
}
Episode model:
class Episode extends AppModel
{
var $name = 'Episode';
var $belongsTo = array(
'Show' => array(
'className' => 'Show',
'foreignKey' => 'show_id'
)
);
}
Ops controller:
class OpsController extends AppController
{
var $name = 'Ops';
var $uses = array('Show','Episode');
function index()
{
$episodes = $this->Episode->find('all',array(
'limit' => 10,
'order' => array('Episode.first_aired' => 'DESC'),
)
);
debug($this->Episode);
debug($episodes);
}
}
When running the Ops controller I get the 'Episode' records like I want but don't get the associated 'Show' record based on the 'show_id' in the 'belongsTo' configuration. It appears that it is not referencing the model at all as I can purposefully break the model class an the request still goes on.
After doing a lot of checking, researching, and testing, I was able to get it to work by adding the following into the Ops controller before the find() request:
$this->Episode = ClassRegistry::init('Episode');
$this->Episode->bindModel(
array('belongsTo' => array(
'Show' => array(
'className' => 'Show'
)
)
)
);
Now while this works I would still like to know why my models are not being called properly. Any help would be most appreciated. Thanks!
What happens if you query Show in the same way?
Are you certain the id fields are defined correctly?
On both tables you should have id(INTsize) and on episodes there should also be show_id(INTsize).
If it's set up according to Cake convention, you should be able to remove the 'foreignKey' => 'show_id' line and Cake will sort it out itself.`
It sounds like Cake isn't using your model files and instead automagically generating some based on the tables.
It sounds dumb, but check the folders and file names for spelling errors and that they are lowercase.
In your Show model, you have the Episode foreign key set to show_id, which should be episode_id. However, I don't think that is causing the problem.
You aren't changing any CakePHP naming conventions, from what I can tell, so just remove the arrays that define the association and leave as string, e.g.
class Show extends AppModel
{
var $name = 'Show';
var $hasMany = array(
'Episode'
);
}
class Episode extends AppModel
{
var $name = 'Episode';
var $belongsTo = array(
'Show'
);
}
This may not work, but I have bumped into similar issues before and this resolved it. Good luck.

Resources