I am setting up a form that updates person and the associated person_to_role tables, person_to_role is a intermediate table that links person to role in a n..n relationship. role has a predefined list of roles, that shouldn't be modified from a person's scope.
I only need to update role_id and description in the person_to_role table and add/remove records.
SQL
--person
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| NICK_NAME | varchar(16) | YES | | NULL | |
| FIRST_NAME | varchar(24) | NO | | NULL | |
| MIDDLE_NAME | varchar(8) | YES | | NULL | |
| LAST_NAME | varchar(24) | NO | | NULL | |
| BIRTH_DATE | date | NO | | NULL | |
| GENDER | varchar(8) | NO | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
-- role
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| NAME | varchar(24) | NO | | NULL | |
| DESCRIPTION | varchar(100) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
--person_to_role
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| PERSON_ID | int(11) | NO | MUL | NULL | |
| ROLE_ID | int(11) | NO | MUL | NULL | |
| DESCRIPTION | varchar(100) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
PersonTable Model
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('person');
$this->setDisplayField('ID');
$this->setPrimaryKey('ID');
// define relations
$this->belongsToMany('Role', [
'joinTable'=> 'person_to_role',
'foreignKey' => 'PERSON_ID'
]);
}
Person controller -> edit()
public function edit($id = null)
{
$person = $this->Person->get($id, [
'contain' => ['role']
]);
$this->set('roles', $this->Person->Role->find('list'));
if ($this->request->is(['patch', 'post', 'put'])) {
$person = $this->Person->patchEntity($person, $this->request->getData());
if ($this->Person->save($person)) {
$this->Flash->success(__('The person has been saved.'));
return $this->redirect(['action' => 'index']);
}
$errors = print_r($person->errors(),1);
$this->Flash->error(__('The person could not be saved. Please, try again.<br><pre>'. $errors .'</pre>'),['escape'=> false]);
}
$this->set(compact('person'));
$this->set('_serialize', ['person']);
}
edit.ctp form fields
echo $this->Form->control('NICK_NAME');
echo $this->Form->control('FIRST_NAME');
echo $this->Form->control('MIDDLE_NAME');
echo $this->Form->control('LAST_NAME');
echo $this->Form->control('BIRTH_DATE');
echo $this->Form->control('GENDER',['type'=>'select','options'=>[''=> '-
Please Select -', 'Male'=>'Male','Female'=>'Female']]);
Assigned roles
...
<?php foreach ($person->role as $k=>$role) { ?>
<tr><td><?php
echo $this->Form->input("role.$k._joinData.ID",['type'=>'hidden','value'=>$person->role[$k]['_joinData']['ID']]);
echo $this->Form->input("role.$k._joinData.ROLE_ID",['value'=>$role-
>ID,'options'=>$roles,'templates'=>['formGroup' =>'{{input}}']])
?></td><td>
<?php echo $this->Form->input("role.$k._joinData.DESCRIPTION", ['value'=>$person->role[$k]['_joinData']['DESCRIPTION'],'templates'=>
['formGroup' =>'{{input}}']]); ?></td></tr>
<?php } ?>
...
This gives me the following POST data:
'NICK_NAME' => 'Johny',
'FIRST_NAME' => 'John',
'MIDDLE_NAME' => 'J.',
'LAST_NAME' => 'Smith',
'BIRTH_DATE' => '1961-01-01',
'GENDER' => 'Male',
'role' => [
(int) 0 => [
'_joinData' => [
'ID' => '1',
'ROLE_ID' => '5',
'DESCRIPTION' => 'person role description'
]
]
]
]
But the update fails with following errors:
The person could not be saved. Please, try again.
Array
(
[role] => Array
(
[0] => Array
(
[NAME] => Array
(
[_required] => This field is required
)
[_joinData] => Array
(
[PERSON_ID] => Array
(
[_required] => This field is required
)
)
)
)
)
It asks to provide person_to_role.person_id which is the foreignKey (it should know current person ID), and wants a value for role.name.
Did I set my association wrong? Any help is appreciated.
UPDATE 2017-08-20
Still no go, tried all possible variations from the docs and other Internet resources. Currently I am able to pass through validation to the save action, but an INSERT query is generated instead of UPDATE and errors out on unique constraint violation.
I have person.ID and person_to_role.ID accessible:
protected $_accessible = [
'*' => true,
'ID' => true
];
My POST data looks like this:
[
'NICK_NAME' => '',
'FIRST_NAME' => 'test',
'MIDDLE_NAME' => '',
'LAST_NAME' => 'user',
'BIRTH_DATE' => '1996-10-01',
'GENDER' => 'Male',
'role' => [
(int) 0 => [
'_joinData' => [
'ID' => '153',
'DESCRIPTION' => 'test edited text'
],
'ID' => '2'
]
]
]
I tried both, with and without person_to_role record ID in _joinData, same result:
INSERT INTO person_to_role (PERSON_ID, ROLE_ID, DESCRIPTION)
VALUES (129, 2, 'test edited text')
While trying different methods, including using 'through' association, I had the following lines added to my PersonToRoleTable.phpmodel:
$this->belongsTo('Person');
$this->belongsTo('Role');
After commenting these out, everything worked as expected, I am able to save updates as well as add new and delete existing records in the join table.
Related
I'm really new to PHP and Laravel and so far I managed to join query two tables... it looks something like this...
$data = DB::table('users')
->join('plans', 'plans.user_id', '=', 'users.id')
->get();
The query above returns something like this..
| id | user_id | name | plan_1 | plan_2 | plan_3 |
-------------------------------------------------------
| 1 | 1 | John | resul1 | result2 | result3 |
Note that user_id, plan_1, plan_2, and plan_3 columns are from the plans table
Now, what I want is to make the result look like this...
$data = [{
'id' => 1
'name' => 'John'
'plan_set' => [{
'user_id' => 1,
'plan_1' => 'result1',
'plan_2' => 'result2',
'plan_3' => 'result3',
}]
}]
As a newbie on PHP, especially on Laravel, I don't really have an idea on how to do this.
How to get result of below tables.
catTbl
catId, name
11 fruit
12 vegetable
prodTbl
pId | catTbl_catId | name
1 11 apple
2 11 orange
3 12 slag
I want to get result for
cat name total count
fruit 2
vegetable 1
order by with total count--
How to use order by total below cakephp 3 query..
$cats=$this->catTbl->find()
->where(['catTbl.status'=>'1','is_deleted'=>'0'])
->select(['name','catId','modified'])
->contain([
'prodTbl' => function($q) {
$q->select([
'prodTbl.catTbl_catId',
'total' => $q->func()->count('prodTbl.catTbl_catId')
])
->where(['prodTbl.status'=>'1','prodTbl.is_deleted'=>'0'])
->group(['prodTbl.catTbl_catId']);
return $q;
}
]);
I managed to get the results
+------------+---------+
| Cat | Total |
+------------+---------+
| fruit | 2 |
| vegetable | 1 |
+------------+---------+
using this query
$query = $this->Prod->find();
$cats = $query->select([
'Cat.name',
'total' => $query->func()->count('catId')
])
->contain([
'Cat'
])
->group([
'catId'
])
->order([
'total' => 'DESC'
])
->all();
I have 2 table in my database that second(orders) table has foreign_key of primary key of first(books) table like these
Books
----+---------+-------------
id | slug | name |
----+---------+--------------
1 | math | mathematics |
----+---------+--------------
2 | physics | holidays |
-----------------------------
Orders
----+---------+-------+--------
id | book_id | count | price |
----+---------+-------+--------
1 | 2 | 12 | 100000 |
--------------------------------
I want result like below
result
----+---------+----------+----------+----------+------------------
id | book_id | slug | name | order_id | count | price |
----+---------+----------+----------+-----------------------------
1 | 2 | physics | holidays | 1 | 12 | 100000 |
------------------------------------------------------------------
I believe each product has a price. To that start with relating PRODUCT table to PRICE.
In cake this is done very easily:
in your Model (Product.php)
class Product extends AppModel{
public $hasMany = array('Price');
}
in Price.php
class Price extends AppModel{
public $hasBelongTo = array('Product');
}
in your controller if you query any of these Models the returned array will contain data from both models.
make the relationships as follow
Product.php
....
public $hasMany = array(
'Price' => array(
'className' => 'Price',
'foreignKey' => 'product_id',
'dependent' => true,
'conditions' => '',
'group' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
....
Price.php
.....
public $belongsTo = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
....
then in your controller use this query
$this->Product->find('all',array('contain'=>array('Price')));
I have two tables resumes and links. resumes has hasmany relation with links.I want to save many links for single resume.
My $this->request->data array is like
Array
(
[alternate_email] =>
[mobile] => 23232
[level] => Student
[youtube] =>
[links] => Array
(
[0] => Array
(
['link'] => www.google.com
['user_id'] => 1
)
[1] => Array
(
['link'] => abc.com
['user_id'] => 1
)
)
)
$resume = $this->Resumes->newEntity($this->request->data);
if ($this->Resumes->save($resume)) {
// return true;
}
This is working and my data is saved in resumes table properly but in links table data saved like following:
id | resume_id | user_id | link
1 | 1 | |
I want like
id | resume_id | user_id | link
1 | 1 | | www.google.com
try do that:
$resume = $this->Resumes->newEntity($this->request->data, ['associated' => ['Links']]);
if ($this->Resumes->save($resume, ['associated' => ['Links']])) {
// return true;
}
Go to your Model/Entity/Link.php and add link to protected $_accessible array
I'm have quite a problem while trying to make a list (for the admin section) of HABTM relations. Here's the deal:
permissions: id, name;
users: id, username;
permissions_users: permission_id, user_id
Permission HasAndBelongsToMany User
I want to make a listing like such:
User.id | User.username | Permission.id | Permission.name
1 | Jack | 1 | posts
1 | Jack | 2 | comments
2 | Mark | 1 | posts
3 | Kate | 3 | tags
Stuff like: $this->Permission->User->find('all'); (or the other way around) doesn't really work, because it will fetch many permissions for Jack, also the other way around it will fetch many users for the posts permission, thus making it impossible to list in the view.
What I want is to get a array like:
[0] = > array(
[User] => array([id] => 1 [username] => Jack)
[Permission] => array([id] => 1 [name] => posts)
)
[1] = > array(
[User] => array([id] => 1 [username] => Jack)
[Permission] => array([id] => 2 [name] => comments)
)
...
Any ideas?
I think you would need to use the foreach and loop through your result to reconstruct a new array like that.
$user = array('id' => '1', 'name' => 'Jack');
$data = array();
foreach($permission as $per) {
$data[] = array($user, $per['Permission'])
}