CakePHP not binding model automatically - php

CakePHP 2.8.3 is not binding the model automatically.
Model :
<?php
class Item extends AppModel
{
public $name = 'Item';
public $belongsTo = array(
'Cat' => array(
'className' => 'Cat',
'foreignKey' => 'cat_id',
),
);
}
The above Model is not working.
However when I Bind Model in controller. It works fine.
$this->Item->bindModel(array(
'belongsTo' => array(
'Cat' => array(
'foreignKey' => 'cat_id',
))));
What could be the cause ?

Related

Cakephp 2.x multiple relationship

i have some troubles with cakephp 2.x and the relationship of the models, i have 3 models, Post, User and Comment.
I would like bind the Post with his User and Comment with his User.
In Post Model:
$belongsTo = array('Comment','User'),
$hasMany = array('CommentOfPost'=>array('className'=>'Comment'));
I have Post bind with User, and all comment from the post but i don't have users of the comments.
Edit :
Sql output
1 SELECT `Post`.`id`, `Post`.`title`, `Post`.`content`, `Post`.`tags`, `Post`.`created`, `Post`.`modified`, `Post`.`user_id`, `User`.`id`, `User`.`username`, `User`.`password`, `User`.`role`, `User`.`name`, `User`.`lastname`, `User`.`birthdate`, `User`.`email`, `User`.`created`, `User`.`modified` FROM `blog`.`posts` AS `Post` LEFT JOIN `blog`.`users` AS `User` ON (`Post`.`user_id` = `User`.`id`) WHERE `Post`.`id` = 16 LIMIT 1 1 1 0
2 SELECT `CommentOfPost`.`id`, `CommentOfPost`.`post_id`, `CommentOfPost`.`user_id`, `CommentOfPost`.`content`, `CommentOfPost`.`created` FROM `blog`.`comments` AS `CommentOfPost` WHERE `CommentOfPost`.`post_id` = (16)
Edit :
Comment Model
public $belongsTo = array('User' => array('className' => 'User'));
Post Model
public $belongsTo = array('Comment' => array('className' => 'Comment'));
Edit :
Thank for reply, i have the same result like before i have Post and his User and Post and his comments but not users of comments
Now my model Post
$hasMany = array(
'Comment' => array(
'className' => 'Comment',
)
),
$belongsTo = array(
'User' => array(
'className' => 'User',
)
);
User model
$hasMany = array('Comment' => array('className' => 'Comment'));
Comment Model
$belongsTo = array('Users' => array('className' => 'User'), 'Posts' => array('clasName' => 'Post'));
I use paginate querying in my PostsController
$this->Paginator->settings = $this->paginate;
$data = $this->Paginator->paginate('Post');
$this->set('posts', $data);
Edit :
My paginate params
$paginate = array(
'limit' => 10,
'recursive' => 2,
'order' => array(
'Post.id' => 'desc'
)
);
I try with and without recursive option
Ok it's done !
For resume i have :
class User extends AppModel {
public $hasMany = array('Comment' => array('className' => 'Comment'));
}
class Post extends AppModel
{
$hasMany = array(
'Comment' => array(
'className' => 'Comment',
)
),
$belongsTo = array(
'User' => array(
'className' => 'User',
)
);
}
class Comment extends AppModel {
public $belongsTo = array('User' => array('className' => 'User'), 'Post' => array('clasName' => 'Post'));
}
PostsController extends AppController
{
....
$this->Post->recursive = 2;
$post = $this->Post->findById($id);
...
}
Thank for your help guys, you're awesome !
Post does not belongs to Comment. It has many comments.
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
Example from the cookbook:
class User extends AppModel {
public $hasMany = array(
'MyRecipe' => array(
'className' => 'Recipe',
)
);
}
For your application:
class Post extends AppModel {
public $hasMany = array(
'Comment' => array(
'className' => 'Comment',
)
);
public $belongsTo = array(
'User' => array(
'className' => 'User',
)
);
}

How do I traverse CakePHP relations?

I'm trying to traverse the relations on CakePHP models.
This is the database:
I can access product attributes (product->attributes) on a product model but I cannot access the product attributes on Ad model (ad->product->attributes).
Here is my code:
//Product Model
class Product extends AppModel {
public $useTable = 'products';
public $displayField = 'name';
public $hasAndBelongsToMany = array(
'Attributes' =>
array(
'className' => 'Attribute',
'joinTable' => 'product_has_attributes',
'foreignKey' => 'products_id',
'associationForeignKey' => 'attributes_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => 'product_has_attributes'
)
);
public $hasMany = array(
'Ads' => array(
'className' => 'Ad',
'foreignKey' => 'Products_id',
'conditions' => '',
'order' => '',
'limit' => '',
'dependent' => true
)
);
//Ad Model
class Ad extends AppModel {
public $displayField = 'Name';
public $belongsTo = array(
'Product' => array(
'className' => 'Products',
'foreignKey' => 'products_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
//Attribute Model
class Attribute extends AppModel {
public $displayField = 'name';
public $hasAndBelongsToMany = array(
'Products' =>
array(
'className' => 'Product',
'joinTable' => 'product_has_attributes',
'foreignKey' => 'attributes_id',
'associationForeignKey' => 'products_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => 'product_has_attributes'
)
);
// Products controller -> Action View
class ProductsController extends AppController {
public function view($id = null) {
if (!$this->Product->exists($id)) {
throw new NotFoundException(__('Invalid product'));
}
$options = array('conditions' => array('Product.' . $this->Product->primaryKey => $id));
$this->set('product', $this->Product->find('first', $options));
}
}
// Ads controller -> Action View
class AdsController extends AppController {
public function view($id = null) {
if (!$this->Ad->exists($id)) {
throw new NotFoundException(__('Invalid ad'));
}
$options = array('conditions' => array('Ad.' . $this->Ad->primaryKey => $id));
$this->set('ad', $this->Ad->find('first', $options));
}
And here is what I do in the views:
//Products Views: snipet of view.ctp
print_r ($product);
// this prints rhe product and all associated attributes
//Ads Views: snipet of view.ctp
print_r ($ad['Product']);
//this will print only the product fields, but not the attributes associated to the product
What is wrong? How do I access the relation Ad->product->attribute from my Ad model?
I can think of a couple of simple ways to accomplish this.
First:
class AdsController extends AppController {
if (!$this->Ad->exists($id)) {
throw new NotFoundException(__('Invalid ad'));
}
$options = array(
'conditions' => array('Ad.' . $this->Ad->primaryKey => $id),
'recursive' => 1, // or more
);
$this->set('ad', $this->Ad->find('first', $options));
}
That would be the simplest code change to make sure you get attributes that are related to the product that is returned.
Otherwise, you alluded to this in your question. You can access related Models through the model, so:
$this->Ad->Product->find(...);
I have had issues with Cake not liking my find conditions when using related models in conditions, and I'm not sure of the proper syntax, but if you wanted to pursue that, I'm sure you can track it down through the docs or by experimentation.
Finally, I would advise you to check into the ContainableBehavior, which will allow you to fine tune which fields are actually returned in the results. I hope this answers your question!
Perhaps the problem could be that you're not using CakePHP's conventions.
From the docs:
"new join table’s name needs to include the names of both models involved, in alphabetical order, and separated with an underscore ( _ )."
So, your join table should be named attributes_products.
Also, check your foreign keys. They should be in singular form.
attributes_products.id
attributes_products.product_id
attributes_products.attribute_id
Hopefully that solves the problem.
References:
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm
http://book.cakephp.org/2.0/en/getting-started/cakephp-conventions.html#model-and-database-conventions

Cannot save associated data with hasMany through (Join Model)

Hi, I am new to cakephp and doing a project on cakephp 2.3.4.
I have to associate product metal class through has many through association . But it doesn't seem to be working.
Model code
class Metal extends AppModel {
public $hasMany = array(
'MetalProduct'
);
}
class Product extends AppModel {
public $hasMany = array(
'MetalProduct'
);
}
App::uses('AppModel', 'Model');
class MetalProduct extends AppModel {
public $belongsTo = array(
'Metal' => array(
'className' => 'Metal',
'foreignKey' => 'metal_id'
),
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id'
)
);}
My database table names are metal, products and metal_products
I have multiple select option for selecting more than one metal type.
This is how I get the the list of metals
$metals=$this->Metal->find('list');
$this->set(compact('metals'));
FormHelper code for listbox is
<?php echo $this->Form->input('Metal',array('type' => 'select',
'multiple' => true)); ?>
The product is getting saved successfully but the associations are not.
The debug array give me this
$message = array(
'Product' => array(
'category_id' => '517a514b-0eb0-4ec9-b018-0b948620d4f0',
'name' => 'mangalsutra Diamond',
'slug' => 'mangalsutra_diamond',
'description' => '1212',
'Metal' => array(
(int) 0 => '5183cb65-bf90-459c-b22e-0b748620d4f0',
(int) 1 => '5183ce25-c744-433e-b035-0b748620d4f0'
),
'image' => '121212',
'price' => '12121',
'weight' => '12',
'active' => '1',
'category' => 'Mangalsutra'
)
)
I had put my head through walls but no clue why the associations are not getting saved.
The way they say in tutorials it seems easy, but why its not working?
I have doubts that its not saving because the metal array is passed like this
'Metal' => array(
(int) 0 => '5183cb65-bf90-459c-b22e-0b748620d4f0',
(int) 1 => '5183ce25-c744-433e-b035-0b748620d4f0'
),
It should mention 'id''rather than (int) 0 or something.
Also, my database table for metal_products which I have created manually has
id(primary key)
metal_id(foreign key to Metal.id)
product_id(foreign key to Product.id)
Am I doing something wrong with naming conventions or the way database is created?
Please give me correct ans cause anything I tried from others answer is not working
I am saving it via
$this->Product->saveAll($this->request->data, array('deep' => true))
In your model, is all of that in your MetalProduct Model? If so you need to move
class Metal extends AppModel {
public $hasMany = array(
'MetalProduct'
);
}
to the Metal model and
class Product extends AppModel {
public $hasMany = array(
'MetalProduct'
);
}
to the Product Model
Also add your belongsTo to each Model
I see you have a join table. Join tables are usually for HABTM associations. This is a HasMany. You need to use the other options available to define the foreign key relationships in each model as outlined above.
Please see the examples on the Cake Documentation.
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
Also, if you are unsure of how to set up the models correctly, you can always use the Bake feature of Cakephp to generate the models and code for you in that regard.
book.cakephp.org/2.0/en/console-and-shells/code-generation-with-bake.html
If you are more of a visual learner this video tut should help you through the basics
http://www.youtube.com/watch?v=kJAMifqF5s8
The Relation i generated using Bake looks something like this
class Product extends AppModel {
/**
* hasAndBelongsToMany associations
*/
public $hasAndBelongsToMany = array(
'Metal' => array(
'className' => 'Metal',
'joinTable' => 'metals_products',
'foreignKey' => 'product_id',
'associationForeignKey' => 'metal_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
));
}
class Metal extends AppModel {
/** hasAndBelongsToMany associations */
public $hasAndBelongsToMany = array(
'Product' => array(
'className' => 'Product',
'joinTable' => 'metals_products',
'foreignKey' => 'metal_id',
'associationForeignKey' => 'product_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
));
}
/**
* MetalsProduct Model
* #property Product $Product
* #property Metal $Metal
*/
class MetalsProduct extends AppModel {
/* belongsTo associations */
public $belongsTo = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Metal' => array(
'className' => 'Metal',
'foreignKey' => 'metal_id',
'conditions' => '',
'fields' => '',
'order' => ''
));
}
This worked for me flawlessly.
Hope it works for all.

Using Cakephp, how can I get a multi-select element or checkboxes for a hasMany relationship in my scaffolded add, edit views?

I've run through the Cakephp documentation on linking models together (creating associations), and I can get a single select dropdown in the scaffolded add and edit views by defining a $hasOne member one model and a corresponding $belongsTo in the other. Now, for a $hasMany relationship, I'm trying to get some kind of form input (either a multi-select dropdown, or checkboxes ... preferably checkboxes) in my scaffolded add and edit views that lets the user choose the associated advertisements for a given rental. But with the below code I get no mention of Advertisements in the Rental add and edit views :'( Am I missing something? Is this even possible? I've seen this done in RoR and Grails but can't get it working with CakePHP. Thanks for any help!
Rental model (app/Model/Rental.php)
<?php
class Rental extends AppModel {
var $name = 'Rental';
var $belongsTo = array(
'Agent' => array(
'className' => 'User',
'foreignKey' => 'agent_id'
),
'Bedroom',
'Landlord' => array(
'className' => 'Landlord',
'foreignKey' => 'landlord_id'
)
);
var $hasMany = array(
'Advertisement' => array(
'className' => 'Advertisement',
'foreignKey' => 'rental_id',
//'conditions' => array('Comment.status' => '1'),
'order' => 'Advertisement.created DESC',
'limit' => '5',
'dependent'=> false
)
);
public $validate = array(
'title' => array(
'rule' => 'notEmpty'
),
'description' => array(
'rule' => 'notEmpty'
)
);
public function isOwnedBy($rental, $user) {
return $this->field('id', array('id' => $rental, 'user_id' => $user)) === $rental;
}
}
Rentals Controller (app/Controller/RentalsController.php)
<?php
class RentalsController extends AppController {
public $scaffold;
}
Advertisement model (app/Model/Advertisement.php)
<?php
class Advertisement extends AppModel {
var $name = 'Advertisement';
var $belongsTo = array(
'Rental' => array(
'className' => 'Rental',
'foreignKey' => 'rental_id'
),
'Author' => array(
'className' => 'User',
'foreignKey' => 'author_id'
)
);
}
Advertisements Controller (app/Controller/AdvertiesementsController.php)
<?php
class AdvertisementsController extends AppController {
public $scaffold;
}
Cake's scaffold views don't show anything from the hasMany side of the relationship. They assume you want to pick it from the model that has the belongsTo.
Frankly, doing it as a multi-select is a little odd for this relationship, IMHO. Multi-selects are normally used for hasAndBelongsToMany relationships. If you want to do it, you'll need to do the work yourself, and not use Cake's scaffolding.

CakePHP alias breaks HABTM Model

Consider the following HABTM relation in CakePHP 2.2.3:
class User extends AppModel
{
public $hasAndBelongsToMany = array(
'Role' => array(
'className' => 'Role',
'joinTable' => 'roles_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'role_id',
)
);
}
This works fine, but when using an alias like VeryUniqueAlias instead of Role and changing the UsersController accordingly, the m:n relation is not persisted in the database (the data passed to save() in the controller are equivalent).
This does not work:
class User extends AppModel
{
public $hasAndBelongsToMany = array(
'VeryUniqueAlias' => array(
'className' => 'Role',
'joinTable' => 'roles_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'role_id',
)
);
}
This is awkward, since the the CakePHP docs state that it should work.
Any idea why it's not working for me? Did I miss something?
Use the 'with' key to define the name of the model for the join table. In your case:
public $hasAndBelongsToMany = array(
'VeryUniqueAlias' => array(
'className' => 'Role',
'joinTable' => 'roles_users',
'with' => 'RolesUser', // first model pluralized
'foreignKey' => 'user_id',
'associationForeignKey' => 'role_id',
)
);

Categories