error in joining table in cakephp - cakephp

Controller
public function index(){
$this->Store->unbindModel(
array('belongsTo' => array('Employee')), true
);
$options=array(
'joins' =>
array(
array(
'table' => 'Employee',
'alias' => 'Employee',
'foreignKey' => true,
'conditions'=> array('Employee.employee_store = Store.store_name')
)
));
$coupons = $this->Store->find('all', $options);
}
Model
class Store extends AppModel {
var $useTable = 'store'; }
Sql :
SELECT `Store`.`id`,
`Store`.`store_name`,
`Store`.`store_address`,
`Store`.`store_phone`,
`Store`.`store_email`,
`Store`.`store_website`,
`Store`.`date_enter`,
`Store`.`store_shortcode`
FROM `billing`.`store` AS `Store`
JOIN `billing`.`Employee` AS `Employee` ON (`Employee`.`employee_store` = `Store`.`store_name`)
WHERE 1 = 1
I need to display Both Employee and Store table columns. (employee_name,employee_mail etc from employee table, Store_name,store_add from store table )

$options = array(
array(
'table' => 'Employee',
'alias' => 'Employee',
'foreignKey' => true,
'conditions'=> array('Employee.employee_store = Store.store_name')
)
);
$coupons = $this->Store->find('all',array(
"fields"=>array("Employee.*","Store.*"),
"joins"=>$options
));

$this->Store->Behaviors->load('Containable');
$options = array(
'contain' => array(
'Employee' => array(
'conditions' => array(
'Employee.employee_store' => 'Store.store_name'
)
)
)
);
$coupons = $this->Store->find('all', $options);

Related

cakephp contain twice model association

I have to fetch data from posts table
which has foreign keys (
category_id references to categories.id
created_by references to users.id,
updated_by references to users.id
)
I can fetch created_by username but not both
$this->Post->Behaviors->load('Containable');
$this->paginate = array(
'conditions' => array('Post.category_id' => $id),
'order' => array('title'),
'contain' => array(
'User'=>array(
'fields'=>array('id','first_name','last_name','username'),
'conditions' => array('User.id = Post.created_by')
),
//posts table has 2 fields(created_by & updated_by) associated with users table
//'User'=>array(
// 'fields'=>array('id','first_name','last_name','username'),
// 'conditions' => array('User.id = Post.updated_by')
// ),
'Category'=>array(
'Type'=>array(
'fields'=>array('id','type_name')
)
),
)
);
//post model
public $belongsTo = array(
'User'=> array(
'className' => 'User',
'foreignKey' => 'created_by',
'foreignKey' => 'updated_by'
),
);
//user model
public $hasMany = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => array('created_by','updated_by'),
),
);
how to show both and alias both Users as (created_by & updated_by)
First you need to define two relationships in the Post model
public $belongsTo = array(
'CreatedUser'=> array(
'className' => 'User',
'foreignKey' => 'created_by'
),
'UpdatedUser'=> array(
'className' => 'User',
'foreignKey' => 'updated_by'
)
);
Now create the converse relationships in the User model.
public $hasMany = array(
'CreatedPosts' => array(
'className' => 'Post',
'foreignKey' =>'created_by'
),
'UpdatedPosts' => array(
'className' => 'Post',
'foreignKey' => 'updated_by'
),
);
Then the find()
$this->Post->Behaviors->load('Containable');
$this->paginate = array(
'conditions' => array('Post.category_id' => $id),
'order' => array('title'),
'contain' => array(
'CreatedUser'=>array(
'fields'=>array('id','first_name','last_name','username')
),
'UpdatedUser'=>array(
'fields'=>array('id','first_name','last_name','username')
),
'Category'=>array(
'Type'=>array(
'fields'=>array('id','type_name')
)
),
)
);

Cakephp Find conditions on related table with hasAndBelongsToMany

I have the following code that gives an error from the moment I do a find condition on the associated Model (HABTM):
class Users extends Model{
public $useTable = 'users';
public $hasAndBelongsToMany = array(
'UserCategories' => array(
'className' => 'UserCategories',
'joinTable' => 'user_categories_link',
'foreignKey' => 'user_id',
'associationForeignKey' => 'category_id',
'unique' => false,
)
);
public function getData($page = 0, $category = '', $subcategory = ''){
return $this->find('all', array(
'limit' => 6,
'page' => $page,
'conditions'=> array(
'active'=> 1,
'UserCategories.category_name' => $category, // THIS GIVES ERROR
'UserCategories.category_subcategory' => $subcategory, // THIS GIVES ERROR
)
));
}
In my Controller:
$this->Users->getData(0, 'somemaincategory', 'somesubcategory');
I can't seem to do conditions on the related HABTM-Model (UserCategories in this case). I also tried to use 'contain' (with $actsAs), but then he stills gives me all the User data even if there is no Category linked with it. The Category array is in that case just blank.
Hope someone can help me.
Thanks in advance,
AƤron
Do a manual join. You can use this to do an actual inner join (contain will act as a left join). http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
$this->find('all',
array(
'conditions' => array(
'active' => 1,
),
'joins' => array(
array(
'table' => 'user_categories_link',
'alias' => 'UserCategoriesLink',
'type' => 'inner',
'conditions' => array(
'UserCategoriesLink.user_id = User.id'
),
),
array(
'table' => 'user_categories',
'alias' => 'UserCategories',
'type' => 'inner',
'conditions' => array(
'UserCategories.id = UserCategoriesLink.category_id',
'UserCategories.category_name' => $category,
'UserCategories.category_subcategory' => $subcategory,
),
)
),
)
);

CakePHP saveAssociated not saving HasMany Through Model Data

I'm trying to get my associated models in CakePHP 2.3 to save properly, but I'm having issues. I'm storing posts, and I want to know what links are in those posts. For each of those links, I'd like to store anchor text if it is available. My database is set up as in the following diagram.
(source: derekperkins.com)
Anchor Model
class Anchor extends AppModel {
public $hasMany = array(
'PostsUrl' => array(
'className' => 'PostsUrl',
'foreignKey' => 'anchor_id',
'dependent' => false
)
);
public function save($data = NULL, $validate = true, $fieldList = array()) {
$id = Anchor::find('first', array(
'fields' => array('id'),
'recursive' => -1,
'conditions' => array('anchor' => $data['anchor'])
));
if( $id )
$data['id'] = $id['Anchor']['id'];
return parent::save($data, $validate, $fieldList);
}
}
URL Model
class Url extends AppModel {
public $hasMany = array(
'PostsUrl' => array(
'className' => 'PostsUrl',
'foreignKey' => 'url_id',
'dependent' => false
)
);
public function save($data = NULL, $validate = true, $fieldList = array()) {
$id = Url::find('first', array(
'fields' => array('id'),
'recursive' => -1,
'conditions' => array('url' => $data['url'])
));
if( $id )
$data['id'] = $id['Url']['id'];
return parent::save($data, $validate, $fieldList);
}
}
PostsUrl Model
class PostsUrl extends AppModel {
public $belongsTo = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => 'post_id'
),
'Url' => array(
'className' => 'Url',
'foreignKey' => 'url_id'
'Anchor' => array(
'className' => 'Url',
'foreignKey' => 'anchor_id'
)*/
);
}
Post Model
class Post extends AppModel {
public $hasMany = array(
'PostsUrl' => array(
'className' => 'PostsUrl',
'foreignKey' => 'post_id',
'dependent' => false
)
);
public function save($data = NULL, $validate = true, $fieldList = array()) {
$id = Post::find('first', array(
'fields' => array('id'),
'recursive' => -1,
'conditions' => array('external_post_id' => $data['external_post_id'])
));
if( $id )
$data['id'] = $id['Post']['id'];
return parent::save($data, $validate, $fieldList);
}
}
Submitting Data
I've created a form to test my model. This is the code I'm using to save the array created by the form. I am getting a message saying that things saved successfully, but only the post saves. Nothing is entered into the other three tables. I'm also using DebugKit and no SQL calls reference any of that data.
$this->Post->saveAssociated($this->request->data, array('deep' => true))
Array
(
[Post] => Array
(
[external_post_id] => 12345
[sentiment_score] => 3.3
)
[URL] => Array
(
[url] => http://test.com
)
[Anchor] => Array
(
[anchor] => Test Anchor
)
)
I've also tried formatting my arrays to have the URL and Anchor underneath PostsUrl as a subarray, but that didn't work either.
My Model::save functions are there to keep me from duplicating data, and they work properly in other models I have used in the past (though I'm open to suggestions on a better way to do this, as this uses a database call for each check). I've also tried commenting them out, and it doesn't affect my code. How should I structure this to save properly?
First of all about your Model::save functions, for example:
public function save($data = NULL, $validate = true, $fieldList = array()) {
$id = Post::find('first', array(
'fields' => array('id'),
'recursive' => -1,
'conditions' => array('external_post_id' => $data['external_post_id'])
));
if( $id )
$data['id'] = $id['Post']['id'];
pr($data);
return parent::save($data, $validate, $fieldList);
}
it prints $data in this way :
Array
(
[id] => 3 //for example 3
[Post] => Array
(
[external_post_id] => 12345
[sentiment_score] => 3.3
)
[URL] => Array
(
[url] => http://test.com
)
[Anchor] => Array
(
[anchor] => Test Anchor
)
)
this $data is incorrect, the correct data is:
Array
(
[Post] => Array
(
[id] => 3 //for example 3
[external_post_id] => 12345
[sentiment_score] => 3.3
)
[URL] => Array
(
[url] => http://test.com
)
[Anchor] => Array
(
[anchor] => Test Anchor
)
)
You must change your Model::save function this way:
public function save($data = NULL, $validate = true, $fieldList = array()) {
$id = Post::find('first', array(
'fields' => array('id'),
'recursive' => -1,
'conditions' => array('external_post_id' => $data['external_post_id'])
));
if( $id )
$data[$this->name]['id'] = $id['Post']['id'];
return parent::save($data, $validate, $fieldList);
}
second , you can't save this data with single save, you should save your data this way:
$postData = array
(
'Post' => array
(
'external_post_id' => 12345
'sentiment_score' => 3.3
)
);
$this->Post->save($data);
$postUrlId = $this->PostsUrl->find('first', array(
'conditions' => array(
'post_id' => $this->Post->id
),
'fields' => array('id')
));
$urlAnchorData = array(
'URL' => array
(
'url' => 'http://test.com'
),
'Anchor' => array
(
'anchor' => 'Test Anchor'
),
'PostsUrl' => array(
'id' => $postUrlId['PostsUrl']['id']
)
);
$this->PostsUrl->saveAll('$urlAnchorData');

How to get all Users with a "order by" latest Posts in a HABTM relation with CakePHP

I have a HABTM relation between Post and User model.
Now I want to receive all Users ordered by Post.published.
Something like this:
...
var $paginate = array(
'limit' => 8,
'recursive' => 1,
'fields' => array('id', 'username', 'image')
);
function index() {
$this->paginate['conditions'] = array('User.state'=>true);
$this->paginate['order'] = 'Post.published DESC';
$this->set('authors', $this->paginate());
}
...
How can I do this? Is it possible?
In MySQL:
SELECT users.id, users.username, users.image, posts.published FROM users INNER JOIN posts_users ON users.id = posts_users.user_id
INNER JOIN posts ON posts.id = posts_users.post_id
ORDER BY posts.published DESC;
The solution:
function index() {
$this->paginate['joins'] = array(
array('table' => 'posts_users', 'alias' => 'PostsUser', 'type' => 'inner', 'conditions'=>array('User.id = PostsUser.user_id')),
array('table' => 'posts', 'alias' => 'Post', 'type' => 'inner', 'conditions'=>array('Post.id = PostsUser.post_id'))
);
$this->paginate['fields'] = array('id', 'username', 'image');
$this->paginate['conditions'] = array('User.state'=>true);
$this->paginate['order'] = 'Post.published DESC';
$this->paginate['group'] = 'User.id';
$this->set('authors', $this->paginate());
}
You can specify The joins in your paginate options array, just like in the find options:
class PostsController extends AppController {
public function by_tag ( $tag ) {
/**
* This will fetch Posts tagged $tag (say, 'PHP')
*/
$this->paginate['Post'] = array(
'limit' => 10,
'contain' => '',
'conditions' => array(
'Post.published' => 1
),
'fields' => array('Post.*', 'Tag.*'),
'joins' => array(
array(
'table' => 'posts_tags',
'type' => 'INNER',
'alias' => 'PostTag',
'conditions' => array(
'Post.id = PostTag.post_id'
)
),
array(
'table' => 'tags',
'alias' => 'Tag',
'type' => 'INNER',
'conditions' => array(
"PostTag.tag_id = Tag.id AND Tag.name = '$tag'"
)
)
)
);
$data = $this->paginate('Post');
$this->set(compact('data'));
}
}
http://planetcakephp.org/aggregator/items/3544-using-mysql-inner-join-in-cakephp-pagination

Find conditions with hasMany model

I have 4 model:
Item------hasMany---->Detail
Item------hasMany---->Favourite
Item------hasMany---->Category
How can I find all Item that has Favourite.member_id = '8' and Category.item_category_id = '1'
Here is my Item model relation:
public $hasMany = array(
'Detail' => array(
'className' => 'Detail',
'foreignKey' => 'item_id',
'dependent' => true,
'conditions' => '',
'order' => 'created DESC',
),
'Category' => array(
'className' => 'Category',
'foreignKey' => 'item_id',
'dependent' => true,
'conditions' => '',
'order' => 'created DESC',
),
'Favorite' => array(
'className' => 'Favorite',
'foreignKey' => 'item_id',
'dependent' => true,
'conditions' => '',
'order' => 'created DESC',
)
);
I used this query() and it's ok:
$this->set('test',$this->Item->query("SELECT items.*
FROM items, categories, favourites
WHERE items.id = items_item_categories.item_id
AND items.id = favorites.item_id
AND categories.item_category_id = 1 AND favourites.member_id = 8"));
But I don't like using query(), and I change it into find(), and it seems not good:
$this->set('test',$this->Item->find('all', array(
'contain'=>array(
'ItemDetail',
'Category'=>array('conditions'=>array('Category.item_category_id'=>1)),
'Favorite'=>array('conditions'=>array('Favorite.member_id'=>8)));
You need call the containableBehaivor on your model
<?php
class Item extends AppModel {
public $actsAs = array('Containable');
}
in your controller you can make the query
$items = $this->Item->find('all', array(
'contain'=>array(
'ItemDetail',
'Category'=>array(
'conditions'=>array('Category.item_category_id'=>1)
),
'Favorite'=>array(
'conditions'=>array('Favorite.member_id'=>8)
)
)
);
$this->set('test', $items);
try using Joins
$items = $this->Item->find('all', array(
'joins' => array(
array(
'table' => 'categories',
'alias' => 'Category',
'type' => 'inner',
'conditions'=> array('Category.item_category_id' => 1)
),
array(
'table' => 'favorites',
'alias' => 'Favorite',
'type' => 'inner',
'conditions'=> array('Favorite.member_id' => 8, 'Item.id = Favorite.item_id')
)
),
'contain'=>array('ItemDetail','Category','Favorite')
);
$this->set('test', $items);
You could also try something like this:
$this->Item->hasMany['Favorite']['conditions']['member_id'] = 8;
Which has the same effect as rebinding the model with the condition.
Just a possible issue. The above will add the condition for the rest of the request, if you want to rollback to the previous behavior, you need to unset the condition:
unset($this->Item->hasMany['Favorite']['conditions']['member_id']);
Remember to set the $this->Item->recursive property to the desired value (recursive attribute). The default it's 1, which it's the minimum you need for this to work.

Resources