I have a problem with HABTM in Cakephp.
There is two models: User (musicians) and Genre.
And there is three tables: users, genres, genres_users (id (primary), genre_id, user_id).
Wrote in User:
<?php
public $hasAndBelongsToMany = array(
'Genre' => array(
'className' => 'Genre',
'joinTable' => 'genres_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'genre_id',
),
);
But as result i'm getting "Missing Database Table".
What am I doing wrong?
Thanks.
upd
User model
class User extends AppModel {
public $primaryKey = 'id';
public $hasOne = array(
'PerformerProfile' => array(
'className' => 'PerformerProfile',
'dependent' => false,
),
'OrganizerProfile' => array(
'className' => 'OrganizerProfile',
'dependent' => false,
),
);
public $hasAndBelongsToMany = array(
'Genre' => array(
'className' => 'Genre',
'joinTable' => 'genres_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'genre_id',
'unique' => 'keepExisting',
),
);
}
Genre model:
class Genre extends AppModel {
public $primaryKey = 'id';
}
Answer is simple.
Error was in AppModel
It was:
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct();
Must be:
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table ,$ds);
Related
'books
id,name
categories
id,name
books_categories
id,book_id,category_id'
' App::uses('AppModel', 'Model');
class Book extends AppModel {
public $useTable = 'books';
public $belongsTo = array(
'Agerange' => array(
'className' => 'Agerange',
'foreignKey' => 'agerange_id'
),
'Publication' => array(
'className' => 'Publication',
'foreignKey' => 'publication_id'
),
);
public $hasMany = array(
'Category' => array(
'className' => 'Book_Category',
'foreignKey' => 'book_id',
'joinTable' => 'books_categories',
'fields' => array('Category_id',),
)
);
}
<?php
App::uses('AppModel', 'Model');
class Book_Category extends AppModel {
public $useTable = 'books_categories';
public $belongsTo = array(
'Book' => array(
'className' => 'Book',
'foreignKey' => 'book_id'
),
'Category' => array(
'className' => 'Category',
'foreignKey' => 'category_id'
)
);
}
in BooksController ......
$this->paginate = array(
'contains'=>array('Book','Publication','Agerange','Book_Category'),
'order' => 'Book.id ASC');
$books = $this->paginate('Book');
enter code here
{
Book: {id: "111", title: "ABC", subtitle: "English Today Primer", author: "Pruthviraj",…},…}
Agerange:{id: "31", from: "0", to: "2", status: true}
Book:{id: "111", title: "ABC", subtitle: "English Today Primer", author: "Pruthviraj",…}
Category:[{Category_id: "5", book_id: "111"}]
}'
Output Now I am getting only category_id:5 it's okay but I want name field also of category so How can I get name field of category using Book and Book_Category?
Modify your contain array by adding Categoy to Book_Category
$this->paginate = array(
'contains' => array(
'Book',
'Publication',
'Agerange',
'Book_Category' => 'Category'
),
'order' => 'Book.id ASC'
);
OR Use hasAndBelongsToMany association, it's much simpler
Start by deleting the Book_Category
Then change the book Model
class Book extends AppModel {
public $useTable = 'books';
public $belongsTo = array(
'Agerange' => array(
'className' => 'Agerange',
'foreignKey' => 'agerange_id'
),
'Publication' => array(
'className' => 'Publication',
'foreignKey' => 'publication_id'
),
);
public $hasAndBelongsToMany = array(
'Category' => array(
'className' => 'Category',
'joinTable' => 'books_categories',
'foreignKey' => 'book_id',
'associationForeignKey' => 'category_id'
)
);
}
Then, in your controller change the pagination setting like this
$this->paginate = array(
'contains' => array(
'Publication',
'Agerange',
'Category'
),
'order' => 'Book.id ASC'
);
#link Cakephp HABTM association
Here's my models
MODEL USERLIST
class UserList extends AppModel {
public $belongsTo = array(
'UserOwner' => array(
'className' => 'Usermgmt.User',
'foreignKey' => 'owner_id'
),
'UserMember' => array(
'className' => 'Usermgmt.User',
'foreignKey' => 'member_id'
)
);
public $recursive = -1;
public $actsAs = array('Containable');
MODEL USER
class User extends UserMgmtAppModel {
public $actsAs = array('Containable');
/**
* This model belongs to following models
*
* #var array
*/
var $belongsTo = array('Usermgmt.UserGroup');
/**
* This model has following models
*
* #var array
*/
var $hasMany = array(
'LoginToken' => array('className' => 'Usermgmt.LoginToken', 'limit' => 1),
'UserListOwner' => array('className' => 'UserList', 'foreignKey' => 'owner_id'),
'UserListMember' => array('className' => 'UserList', 'foreignKey' => 'member_id'),
);
var $hasOne = array(
'PhoneNumber' => array('className' => 'PhoneNumber', 'foreignKey' => 'user_id')
);
MODEL PHONENUMBER
class PhoneNumber extends AppModel {
public $belongsTo = array(
'User' => array(
'className' => 'Usermgmt.User'
)
);
I want to do a database request on multiple parameters who are on multiple levels. This is my request.
$this->UserList->find("all", array('conditions' => array(
"UserList.type" => 1,
'UserList.owner_id' => $this->UserAuth->getUserId(),
"UserMember.PhoneNumber.phoneNumber LIKE" => "%" . "514" . "%"
), 'fields'=>array('UserMember.first_name', 'UserMember.last_name', "PhoneNumber.phoneNumber")))
My problem is when I run this request, I always receive an SQL error message who says that the field UserMember.PhoneNumber.phoneNumber does not exists.
I can do that request using standard SQL but i'dd like to do it with CakePhp.
How can I do it?
thanks
Your column name is wrong, this line "UserMember.PhoneNumber.phoneNumber LIKE" => "%" . "514" . "%" should be "PhoneNumber.phoneNumber LIKE" => "%" . "514" . "%" from the looks of things like you have in your fields.
You might also need to specify which models you want to contain like this:-
$this->UserList->find(
'all',
array(
'contain' => array(
'UserMember' => array('PhoneNumber')
),
'conditions' => array(
'UserList.type' => 1,
'UserList.owner_id' => $this->UserAuth->getUserId(),
'PhoneNumber.phoneNumber LIKE' => '%' . '514' . '%'
),
'fields'=>array(
'UserMember.first_name',
'UserMember.last_name',
'PhoneNumber.phoneNumber'
)
)
);
I am having issues getting all the data from a relationship. Here are my tables:
**Regions**
id(pk)
regions_name
**Areas**
id(pk)
areas_name
regions_id (fk)
**carDealer**
id(pk)
dealer_name
areas_id(fk)
I would think that with this design, I should be able to query Regions like this:
$this->Region->recursive = 5;
$getRegions = $this->Region->find('all');
And get an array of all Regions, which would have a sub array of Areas, which would have a sub array of carDealers.
My code, only brings back the Regions and Areas array but not carDealers. Here is some relevant code to my models:
Regions Table
<?php
App::uses('AppModel', 'Model');
class Region extends AppModel {
public $validate = array(
);
public $belongsTo = array(
);
public $hasMany = array(
'Areas' => array(
'className' => 'Areas',
'foreignKey' => 'regions_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
}
Areas Table:
<?php
App::uses('AppModel', 'Model');
class Area extends AppModel {
public $validate = array(
);
public $belongsTo = array(
'Regions' => array(
'className' => 'Regions',
'foreignKey' => 'regions_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
public $hasMany = array(
'carDealer' => array(
'className' => 'carDealer',
'foreignKey' => 'areas_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
}
Car Dealer Table:
<?php
App::uses('AppModel', 'Model');
class carDealer extends AppModel {
public $validate = array(
);
public $belongsTo = array(
'Areas' => array(
'className' => 'Areas',
'foreignKey' => 'areas_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
public $hasMany = array(
);
}
Am I missing something in my models relationships?
thanks
jason
Foreign keys in hasMany, belongsTo or hasOne relationships are recognized by default as the (singular) name of the related table followed by _id.
Go through http://book.cakephp.org/2.0/en/getting-started/cakephp-conventions.html#model-and-database-conventions
So your foreign key shoud be area_id , region_id
Need to change recursive level
$this->Region->recursive = 1;
$getRegions = $this->Region->find('all');
Need to modify className of Model relationship
It should be 'Area', 'Region','CarDealer'.
Need to remove unnecessary variable or array options
Region Model
<?php
App::uses('AppModel', 'Model');
class Region extends AppModel {
public $hasMany = array(
'Area' => array(
'className' => 'Area',
'foreignKey' => 'region_id'
),
);
}
Area Model:
<?php
App::uses('AppModel', 'Model');
class Area extends AppModel {
public $belongsTo = array(
'Region' => array(
'className' => 'Region',
'foreignKey' => 'region_id'
),
);
public $hasMany = array(
'CarDealer' => array(
'className' => 'CarDealer',
'foreignKey' => 'area_id'
),
);
}
CarDealer Model:
<?php
App::uses('AppModel', 'Model');
class CarDealer extends AppModel {
public $belongsTo = array(
'Area' => array(
'className' => 'Area',
'foreignKey' => 'area_id'
),
);
}
Company class
public $hasMany = array(
'Person' => array(
'className' => 'Lasso.Person',
'foreignKey' => 'company_id',
)
Person class
public $belongsTo = array(
'Company' => array(
'className' => 'Lasso.Company',
'foreignKey' => 'id',
'conditions' => '',
'fields' => 'company',
'order' => ''
)
);
How do I get my company_id field within my People views to be the display name of Company rather than just the value of company_id?
public $displayField = 'companyName';
In your Person class you can write that:
public $belongTo = array(
'Company' => array(
'className' => 'Lesso.Company',
'foreignKey' => 'company_id', // Here use company_id instead of id
.....
)
);
and also you need to put company_id field in persons table.
I've been trying to figure out how to save multi-level models in CakePHP for some time now, but can't seem to find a solution.
I have three models. Survey, Question, and Choice.
Survey hasMany Question - so Question belongsTo Survey
Question hasMany Choice - so Choice belongsTo Question
The Question is linked to the Survey through its survey_id key.
The Choice, on the otherhand, is linked to the Question through its question_id key. (not directly linked to Survey though)
The form is created through $this->Form->create('Survey').
I want the application to save a survey with its corresponding questions, AND each question having their corresponding choice(s).
The problem is, only the Survey and Question models are saved. Choice gets discarded.
I'm using $this->saveAssociated($this->request->data, array( 'deep' => true) )
I will be updating my post to show the $_POST data.
Thanks,
XTN
Before saving data, you have to ensure that data should be in this format
in your controller:
$data = array('Survey' => array('id' => 1,'name' => 'test'),
'Question' => array(
array('id' => 1,'question' => 'test1','survey_id' => 1,
'Choice' => array(
array('id' => 1,'question_id' => 1,'choice' => 1),
array('id' => 2,'question_id' => 1,'choice' => 2)
)
),
array('id' => 2,'question' => 'question2','survey_id' => 1,
'Choice' => array(
array('id' => 3,'question_id' => 2,'choice' => 'sd'),
array('id' => 4,'question_id' => 2,'choice' => 'we')
)
)
)
);
$this->Survey->create();
$this->Survey->saveAssociated($data,array('deep'=>true));
Survey Model :
public $hasMany = array(
'Question' => array(
'className' => 'Question',
'foreignKey' => 'survey_id',
'dependent' => false,
)
);
Question Model :
public $belongsTo = array(
'Survey' => array(
'className' => 'Survey',
'foreignKey' => 'survey_id',
)
);
public $hasMany = array(
'Choice' => array(
'className' => 'Choice',
'foreignKey' => 'question_id',
'dependent' => false,
)
);
Choice Model :
public $belongsTo = array(
'Question' => array(
'className' => 'Question',
'foreignKey' => 'question_id',
)
);
I think it will work if found any problem please notify
Your models should looks like:
Survey Model: Survey.php
class Survey extends AppModel {
public $name = 'Survey';
public $hasMany = array('Questions' => array(
'className' => 'Question',
'foreignKey' => 'survey_id'
)
);
}
Question Model: Question.php
class Question extends AppModel{
public $name = 'Question';
public $belongsTo = array(
'Survey' => array('className' => 'Survey', 'foreignKey' => 'survey_id'),
'Answer' => array('className' => 'Choice', 'foreignKey' => 'answer_id'));
public $hasMany = array('Choices' => array('className' => 'Choice',
'foreignKey' => 'question_id'));
}
Choice Model: Choice.php
class Choice extends AppModel
{
public $name = 'Choice';
public $belongsTo = array('Question' => array('className' => 'Question',
'foreignKey' => 'question_id'));
}
Kindly ask if it not worked for you.