Objective: Person can follow any other Person or Organization.
/**
* PersonFollow schema:
CREATE TABLE `person_follows` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person_id` int(11) DEFAULT NULL,
`table_id` int(11) DEFAULT NULL,
`table_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_person_id` (`person_id`),
KEY `i_table_id` (`table_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
*/
class PersonFollow extends AppModel {
public $belongsTo = array(
'Person' => array(
'foreignKey' => 'person_id',
),
'FollowPerson' => array(
'className' => 'Person',
'foreignKey' => 'table_id',
//'conditions' => array('PersonFollow.table_name' => 'persons'), // tried this
),
'FollowOrganization' => array(
'className' => 'Organization',
'foreignKey' => 'table_id',
//'conditions' => array('PersonFollow.table_name' => 'organizations'), // tried this
),
);
}
class Person extends AppModel {
public $hasMany = array(
'Following' => array(
'className' => 'PersonFollow',
'dependent' => true,
),
'Follower' => array(
'className' =>'PersonFollow',
'foreignKey' => 'table_id',
'conditions' => array('Follower.table_name' => 'persons'),
'dependent' => true
),
);
}
class Organization extends AppModel {
public $hasMany = array(
'Follower' => array(
'className' =>'PersonFollow',
'foreignKey' => 'table_id',
'conditions' => array('Follower.table_name' => 'organizations'),
'dependent' => true
/* Tried this
'foreignKey' => false,
'finderQuery' => 'SELECT `PersonFollow`.*
FROM `person_follows` as `PersonFollow`
WHERE `PersonFollow`.`table_id` = {$__cakeForeignKey__$}
AND `PersonFollow`.`table_name` = "organizations"',
*/
)
);
}
$following = $this->Person->find('all', array(
'contain' => array('Following' => array('FollowPerson','FollowOrganization')),
'conditions' => array('Person.id' => 1234),
));
Results for $following return all Following that match on table_id, and does not use table_name condition. I'm trying to get FollowOrganization where PersonFollow.table_name = 'organizations' and same for FollowPerson where PersonFollow.table_name = 'persons'. It appears $hasMany is only using the 'foreignKey' and not the 'conditions'. What am I missing?
Related
I'm trying to do this with last 2.x CakePHP version
http://i.stack.imgur.com/IylLu.png
Without education_id in projects_students table works perfectly. But doesn't work with education_id.
this is my implementation with education_id:
ProjectsStudent.php
class ProjectsStudent extends AppModel {
public $belongsTo = array(
'Project' => array(
'className' => 'Project',
'foreignKey' => 'project_id'
),
'Student' => array(
'className' => 'Student',
'foreignKey' => 'student_id'
)
);
Student.php
public $hasMany = array('ProjectsStudent');
public $hasAndBelongsToMany = array(
'Education' => array(
'className' => 'Student',
'joinTable' => 'projects_students',
'foreignKey' => 'student_id',
'associationForeignKey' => 'project_id',
),
);
Project.php
public $belongsTo = 'Status';
public $hasMany = array(
'Doc' => array(
'className' => 'Doc',
'joinTable' => 'docs',
'foreignKey' => 'project_id',
),
'History' => array(
'className' => 'History',
'joinTable' => 'history',
'foreignKey' => 'project_id',
),
'ProjectsStudent'
);
public $hasAndBelongsToMany = array(
'Student' => array(
'className' => 'Student',
'joinTable' => 'projects_students',
'foreignKey' => 'project_id',
'associationForeignKey' => 'student_id',
),
'Professor' => array(
'className' => 'Professor',
'joinTable' => 'projects_professors',
'foreignKey' => 'project_id',
'associationForeignKey' => 'professor_id',
),
'Education' => array(
'className' => 'Education',
'joinTable' => 'projects_educations',
'foreignKey' => 'project_id',
'associationForeignKey' => 'education_id',
),
);
ProjectsController.php
$data = array(
'Project' => array(
'id' => $id,
'status_id' => 5,
'Student' => array($this->Auth->user('id'))),
'History' => array(
array(
'action' => 'update -> status 5',
'student_id' => $this->Auth->user('id'),
)
),
'ProjectsStudent' => array(array(
'education_id' => "5"))
);
$this->Project->saveAll($data, array('deep' => true))
Output error:
Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '109' for key 'PRIMARY'
SQL Query: INSERT INTO tfg.projects_students (project_id, education_id) VALUES (109, 5)
I think CakePHP is trying 2 inserts, with (project_id, student_id) and with (project_id, education_id)
I want just one input like INSERT INTO tfg.projects_students (project_id,student_id,education_id) VALUES (109, 1, 5)
Thanks in advance, sorry for my english.
---SOLUTION---
$data = array(
'Project' => array(
'id' => $id,
'status_id' => 5,
'Student' => array($this->Auth->user('id'))),
'History' => array(
array(
'action' => 'update -> status 5',
'student_id' => $this->Auth->user('id'),
)
),
);
$this->Project->saveAll($data, array('deep' => true));
$this->Project->ProjectsStudent->updateAll(
array('education_id' => $this->Auth->user('education')),
array('project_id' => $this->Project->id));
You appear to have setup the projects_students table to use project_id as the primary key. The primary key needs to be unique whereas the project_id foreign key is likely to be duplicated (as appears to be happening for you). The join table should be at least:-
id (int)
project_id (int)
student_id (int)
Where id is the primary key (with auto increment enabled).
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')
)
),
)
);
I am trying to save data with multiple HABTM & hasMany relation. Even if I use
$this->Project->save();
$this->Project->saveMany();
$this->Project->saveAssociated();
$this->Project->saveAlll();
It does not save associated model, I can't figure out what I am doing wrong.
Models Reations
Project hasAndBelongsToMany Skill
Project hasMany Milestone
Project hasAndBelongsToMany Attachment (because Milestone's will also have attachement so can not bind project & attachment in hasMany Relation)
Project Model
class Project extends AppModel{
public $belongsTo = array('Profile');
public $hasMany = array('Milestone');
public $hasAndBelongsToMany = array(
'Skill' =>
array(
'className' => 'Skill',
'joinTable' => 'projects_skills',
'foreignKey' => 'project_id',
'associationForeignKey' => 'skill_id',
'dependent' => true,
//'conditions' => array('Advertisement.advertisement_is_active' => '1')
),
'Attachment' =>
array(
'className' => 'Attachment',
'joinTable' => 'attachments_projects',
'foreignKey' => 'project_id',
'associationForeignKey' => 'attachment_id',
)
);
public function beforeSave($options = array()) {
parent::beforeSave($options = array());
foreach (array_keys($this->hasAndBelongsToMany) as $model):
if(isset($this->data[$this->alias][$model])):
$this->data[$model][$model] = $this->data[$this->alias][$model];
unset($this->data[$this->alias][$model]);
endif;
endforeach;
return true;
}
}
Skill Model
class Skill extends AppModel {
public $name = 'Skill';
public $hasOne = array('Exam');
public $hasAndBelongsToMany = array(
'Category' =>
array(
'className' => 'Category',
'joinTable' => 'categories_skills',
'foreignKey' => 'skill_id',
'associationForeignKey' => 'category_id',
'dependent' => true
),
'Profile' =>
array(
'className' => 'Profile',
'joinTable' => 'profiles_skills',
'foreignKey' => 'skill_id',
'associationForeignKey' => 'profile_id',
'dependent' => true
),
'Project' =>
array(
'className' => 'Project',
'joinTable' => 'projects_skills',
'foreignKey' => 'skill_id',
'associationForeignKey' => 'project_id',
//'dependent' => true
)
);
}
Attachment Model
class Attachment extends AppModel{
public $name = 'Attachment';
public $hasAndBelongsToMany = array(
'Project' =>
array(
'className' => 'Project',
'joinTable' => 'attachments_projects',
'foreignKey' => 'attachment_id',
'associationForeignKey' => 'project_id',
'dependent' => true,
)
);
}
Data
Array
(
[Project] => Array
(
[project_name] => Name Of Project
[project_detail] => Dummy short description
[project_category_id] => 3
[project_budget] => 45
[Skill] => Array
(
[0] => Array
(
[skill_id] => 14
)
[1] => Array
(
[skill_id] => 16
)
)
[project_status] => 1
[project_created] => 2014-08-04 15:31:00
[creator_id] => 1
)
[Milestone] => Array
(
[milestone_name] => Milestone 1
[milestone_budget] => 45
[milestone_created_on] => 2014-08-04 15:31:00
[project_id] => 8
)
[Attachment] => Array
(
[attachment_path] => 11615297103.zip
[attachment_term] => Project Attachment
[attachment_type] => zip
[project_id] => 8
)
)
Pass Skill id not the field name of relation model
[Skill] => Array
(
[0] => Array
(
[id] => 14
)
[1] => Array
(
[id] => 16
)
)
I have this two classes:
class Client extends AppModel{
public $belongsTo = array(
'User',
'plans' => array(
'className' => 'Plan',
'foreignKey' => 'plans_id'
)
);
public $hasMany = array(
'Order'
);
}
}
class User extends AppModel{
public $belongsTo = array(
'Rol' => array(
'fields' => array('id', 'nombre')
)
);
public $hasOne = array(
'Client'
);
}
However cake retrieves this:
'User' => array(
'password' => '*****',
'id' => '32',
'username' => 'test_admin',
'correo_electronico' => 'a#d.com',
'created' => '2013-06-09 19:58:18',
'modified' => '2013-06-09 19:58:18',
'esta_habilitado' => '1',
'rol_id' => '1'
),
'Rol' => array(
'id' => '1',
'nombre' => 'Administrador'
),
'Client' => array(
'id' => null,
'primer_nombre' => null,
'segundo_nombre' => null,
'primer_apellido' => null,
'segundo_apellido' => null,
'direccion' => null,
'diudad' => null,
'telefono' => null,
'rating' => null,
'created' => null,
'modified' => null,
'esta_habilitado' => null,
'plans_id' => null,
'user_id' => null
)
Any ideas what's happening, I have check the foreign keys in the database and the id from the user corresponds to the user_id in the Client record
My DB Structure:
CREATE TABLE IF NOT EXISTS `pos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`alias` varchar(255) NOT NULL,
`model` varchar(255) NOT NULL,
`foreign_key` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `alias` (`alias`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `psos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`po_id` int(11) NOT NULL,
`lft` int(11) NOT NULL DEFAULT '0',
`rght` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
My Models Structure:
class Po extends Model {
public $name = 'Po';
public $useTable = 'pos';
public $cacheQueries = false;
public $hasMany = array(
'Pso' => array(
'className' => 'Pso',
'foreignKey' => 'po_id',
'dependent' => true,
),
'Puso' => array(
'className' => 'Puso',
'foreignKey' => 'po_id',
'dependent' => true,
),
);
}
class Pso extends Model {
public $name = 'Pso';
public $useTable = 'psos';
public $cacheQueries = false;
public $actsAs = array(
'Tree',
);
public $belongsTo = array(
'Parent' => array(
'className' => 'Pso',
'foreignKey' => 'parent_id',
),
'Po' => array(
'className' => 'Po',
'foreignKey' => 'po_id',
),
);
public $hasMany = array(
'Children' => array(
'className' => 'Pso',
'foreignKey' => 'parent_id',
),
);
}
My Saving Associated test code:
$Po->saveAssociated(array(
'Po' => array(
'alias' => 'teste'.uniqid(),
),
'Pso' => array(
'parent_id' => 2,
),
));
Resulting PSO saved Row:
array('id'=>4,'parent_id'=>0,'po_id'=>4,'lft'=>7,'rght'=>8)
Expected PSO saved Row:
array('id'=>4,'parent_id'=>2,'po_id'=>4,'lft'=>7,'rght'=>8)
Resolved like this:
$Po->saveAssociated(array(
'Po' => array(
'alias' => 'teste'.uniqid(),
),
'Pso' => array(
'parent_id' => array(
'parent_id' => 2,
),
),
));