I am using one table:UserMasters and associate with PersonMasters using:
$this->hasOne('person_masters', [
'className' => 'person_masters',
'foreign_key'=>'user_master_id',
'dependent' => true
]);
But when i am saving data it only save data in user_masters table.i am also using 'associated' method in patchEntity. but it not worked..Here is my code for save data:
$user = $this->UserMasters->newEntity();
$user = $this->UserMasters->patchEntity($user, $this->request->data, ['associated' => ['person_masters']]);
It only save data to user_masters ..so how can i also save data in person_masters in cakephp3??
thanks in advance...
If person_masters isn't accessible, it won't be assigned like this.
The _accessible property allows you to provide a map of properties and whether or not they can be mass-assigned. The values true and false indicate whether a field can or cannot be mass-assigned.
http://book.cakephp.org/3.0/en/orm/entities.html#mass-assignment
also use table alias for defining associations.
$this->hasOne('PersonMasters', [
'className' => 'PersonMasters',
'foreign_key'=>'user_master_id',
'dependent' => true
]);
Related
everyone
I am tring to save the Multiple values from select option, but i don't have knowledge about how to save in laravel Backpack .I have been trying to solve the error from 2 days, but still it's not working from my side.
Please have a look, help would be appreciated.
Here is Screen shot of multiple select option ---
But it does not saving in db, but if i am going to edit the record , it gives this error ---
Here is my controller code
CRUD::addField([ // select2_from_ajax: 1-n relationship
'label' => "City Name", // Table column heading
'type' => 'select2_from_ajax_multiple',
'name' => 'location_id', // the column that contains the ID of that connected entity;
'entity' => 'location', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'tab' => 'Texts',
'data_source' => url('api/location'), // url to controller search function (with /{id} should return model)
'placeholder' => 'Select location', // placeholder for the select
'include_all_form_fields' => true, //sends the other form fields along with the request so it can be filtered.
'minimum_input_length' => 0, // minimum characters to type before querying results
'dependencies' => ['state'], // when a dependency changes, this select2 is reset to null
// 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
"allows_multiple" => true,
'pivot' => true,
]);
Problem description
I'm trying to configure a CakePHP 3.7 API to save associated data in a child-first manner. The entities - for the sake of example, lets call them Users and Persons - and their relationships are as follows:
UsersTable.php
...
$this->belongsTo('Persons', [
'foreignKey' => 'person_id',
'joinType' => 'LEFT',
'className' => 'MyPlugin.Persons',
]);
...
PersonsTable.php
$this->hasOne('Users', [
'foreignKey' => 'person_id',
'className' => 'MyPlugin.Users'
]);
In their respective entities, they each have one another's property visibility set to true. What I'm trying to do is POST to the /users/ route (UsersController.php) and have it also save the Persons object included. The payload is as such:
{
"username": "foo",
"password": "bar",
"persons": {
"dob": "1982-07-03",
}
}
The relevant part of the saving method is below, from UsersController.php:
if ($this->request->is('post') && !empty($this->request->getData())) {
$data = $this->request->getData();
$newEntity = $this->Users->newEntity($data, ['associated' => 'Persons']);
$savedEntity = $this->Users->save($newEntity);
...
The error
This produces the following SQL error.
PDOException: SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column 'person_id' violates not-null constraint
DETAIL: Failing row contains (1, null, foo, bar)
I understand this is because Cake is attempting to save to Users without having a person_id to satisfy the foreign key constraint. It's not possible to reverse this FK relationship in my application domain as we desire leftward one-to-many relationship (User -> 1 Person).
I suspect sending an id in the persons object of the JSON payload will allow this to save correctly. However, for various reasons, this isn't possible at runtime. For example, this is how it's shown in the "Saving Data" CakePHP Book page...
$data = [
'title' => 'First Post',
'user' => [
'id' => 1,
'username' => 'mark'
]
];
...
$article = $articles->newEntity($data, [
'associated' => ['Users']
]);
$articles->save($article);
I know the following would also likely work as suggested by xPfqHZ for a similar issue, as Persons can save to Users, but it feels less suitable as compared to what I'm trying to do and feels as if there is a way via the associations on Users.
if ($this->request->is('post') && !empty($this->request->getData())) {
$data = $this->request->getData();
$newEntity = $this->Users->Persons->newEntity($data, ['associated' => 'Persons']);
$savedEntity = $this->Users->Persons->save($newEntity);
...
Workings
Now I believe this used to be possible in CakePHP 2.X, as stated in this answer by ndm on a similar question where a person is attempting to save the belongsTo associated entity and it's parent hasOne entity in one request via the belongsTo entity.
That's the expected behavior, saveAssociated() is not meant to save only the associated records, it will save the main record as well, so you should use saveAssociated() only, no need to manually set the foreign key, etc, CakePHP will do that automatically.
Controller
public function create() {
if ($this->request->is('post') && !empty($this->request->data)):
$this->CandidatesProblemReport->create();
if ($this->CandidatesProblemReport->saveAssociated($this->request->data)):
// ...
endif;
endif;
}
However, I'm not able to find or use the saveAssociated() method upon the Cake\ORM\Table object which the Users entity inherits from, in the documentation. Calling it produces a method not found error. This method only appears to exist on the Cake\ORM\Association object as detailed in the documentation. Unless I'm missing the obvious, is there a way to use this or is it used internally by BelongsTo() and its sibling methods?
Logging / Dumping entity
Using Cake\Log\Log::error($newEntity); or die(var_dump($newEntity)); shows the Users data of the payload hydrated into an object, but I don't see the Persons object attached (see below).
object(MyPlugin\Model\Entity\User)[299]
public 'username' => string 'foo' (length=3)
public 'password' => string 'bar' (length=3)
public '[new]' => boolean true
public '[accessible]' =>
array (size=5)
'*' => boolean false
'person_id' => boolean true
'username' => boolean true
'password' => boolean true
'person' => boolean true
public '[dirty]' =>
array (size=2)
'username' => boolean true
'password' => boolean true
public '[original]' =>
array (size=0)
empty
public '[virtual]' =>
array (size=0)
empty
public '[hasErrors]' => boolean false
public '[errors]' =>
array (size=0)
empty
public '[invalid]' =>
array (size=0)
empty
public '[repository]' => string 'MyPlugin.Users' (length=17)
Attempting to \Cake\Log\Log::error($savedEntity); shows nothing in the log file.
save() associations arguments
Another solution I considered was using the $options['associated] of save() as shown in the documentation (extract below). With this set to true as below, the error still occurred.
save( Cake\Datasource\EntityInterface $entity , array $options [] )
... associated: If true it will save 1st level associated entities as they are found in the passed $entity whenever the property defined for the association is marked as dirty. If an array, it will be interpreted as the list of associations to be saved. It is possible to provide different options for saving on associated table objects using this key by making the custom options the array value. If false no associated records will be saved. (default: true) ...
UsersController.php:
if ($this->request->is('post') && !empty($this->request->getData())) {
$data = $this->request->getData();
$newEntity = $this->Users->newEntity($data, ['associated' => 'Persons']);
$savedEntity = $this->Users->save($newEntity, ['associated' => true]);
...
Summary
Without going through the PersonsController.php and utilising its hasOne relationship, I'm not having much luck getting my Users and Persons data to save through the UsersController.php.
If I've missed any important information, or you have questions/need more, please ask! I might have missed something obvious, but I'd appreciate any suggestions/solutions possible.
As #ndm identified, the error lay in the posted data. As per the "Saving Data: Saving BelongsTo Associations" page of the documentation:
When saving belongsTo associations, the ORM expects a single nested entity named with the singular, underscored version of the association name.
The posted key persons should have been person. Equally, if the entity were named PersonSnapshots, the relevant key in the payload hydrated into the entities would need to have been person_snapshot.
$permission = new Permission();
$permPost = $permission->create([
'name' => 'post',
'slug' => [ // pass an array of permissions.
'create' => true,
'view' => true,
'update' => true,
'delete' => true
],
'description' => 'manage post permissions'
]);
throwing error on passing array within array on create method laravel 5.4 :
Array to string conversion (SQL: insert into permissions (name, slug, description, updated_at, created_at) values (post, 1, manage post permissions, 2017-04-27 05:32:41, 2017-04-27 05:32:41))
Laravel allows Array & JSON Casting mutator:
Just update your Permission model to have:
protected $casts = [
'slug' => 'array',
];
From the docs:
Once the cast is defined, you may access the options attribute and it will automatically be deserialized from JSON into a PHP array. When you set the value of the options attribute, the given array will automatically be serialized back into JSON for storage
So, now you no need to encode manually, Laravel does everything for you automatically! Just pass array as an array.
Try json_encode on slug field, then pass it to the Eloquent to persist in DB:
'slug' => json_encode([
'create' => true,
'view' => true,
'update' => true,
'delete' => true
)]
Slug is a string in the database. You passing an array to it.
You could store it as JSON or Serialise it, but this is a database design smell. You should think about what other tables you need to store this data properly, depending on how it will be used elsewhere in you application.
I am using CakePHP 2.9.1, have 2 tables in a HABTM relationship, I want to save the header record and save many associations in one go, but the child record is already existing, I seem to be able to save the data using a hardcoded list but not using a variable, I'm sure it's something silly I'm doing, I'm running inside a plugin, the model I want to link too is in the main code.
The child record must not be altered because it's handled by the main system, I'm just extending it's functionality by linking to it in our plugin.
// Header Record
class templatedoc extends TemplateModuleAppModel
{
public $useTable = 'templatedocs';
public $hasAndBelongsToMany = [
'Servicetemplate' => [
'className' => 'Servicetemplate',
'joinTable' => 'templatedocs_to_servicetemplates',
'foreignKey' => 'templatedoc_id',
'associationForeignKey' => 'servicetemplate_id',
'unique' => true,
'dependent' => false, // We don't want to delete the Service Template by mistake!
]
];
}
Here is my save, this works:
$this->templatedoc->create ();
$data = [
'templatedoc' => [
'warning_adjust' => $prioritywarn,
'summary' => $summary,
],
'Servicetemplate' => [
1,2,3,10 // Dynamic data needed here!
]
];
$result = $this->templatedoc->SaveAll ($data);
But I can't have the "Servicetemplate" hardcoded, I've tried passing an array inside that array and removing it, imploding an array to make a comma separated list all I end up with is the header 'templatedoc' record being created but nothing in my link table
Only thing I can think is a difference is that the hardcoded list are int values, by data is coming from the database so will be an int inside a string, but I can't see that being an issue.
Any ideas what I'm doing wrong? Sorry if it's something completely stupid.
What I had to do in the end was store the items forcing an int, when associating in my foreach loop.
$items[] = (int) $id
Then this worked:
$this->templatedoc->create ();
$data = [
'templatedoc' => [
'warning_adjust' => $prioritywarn,
'summary' => $summary,
],
'Servicetemplate' => [
$items // Dynamic data needed here!
]
];
$result = $this->templatedoc->SaveAll ($data);
Seems very fussy it has to be type int, adding here in case someone else gets caught out, would love to know if there is a better solution.
i was looking for a previous answer, but the ones i've found are related to older cakephp versions
i have two tables, 'magazines' and 'issues' where there is a relation 'issues' BelongsTo 'magazines', this is what IssuesTable looks like:
public function initialize(array $config){
$this->belongsTo('Magazines', [
'foreignKey' => 'id'
]);
}
table magazines has two fields, magazines.id and magazines.name
table issues has two fields, issues.id, issues.magazine_id where issues.magazine_id is the foreign key
to populate a select input in the issues view with the magazine.name values and save the issues.magazine_id, i've set the controller like this
$this->set('magazines', $this->Issue->Magazine->find('list'));
then i've added the following code to the issue view add.cpt
<?php
echo $this->Form->input('name', [
'type' => 'select',
'multiple' => false,
'options' => $magazines,
'empty' => true]);
?>
but i get the input select with the issues.magazine_id as values instead of magazines.name
thanks for your help and comments
You want to use find('list') as this will return the primary key and display field:-
$this->set(
'magazines',
$this->Issues->Magazines->find('list')
);
Then in your form you need the input name to be magazine_id if you're wanting to set the foreign key for the association:-
echo $this->Form->input(
'magazine_id',
[
'type' => 'select',
'multiple' => false,
'options' => $magazines,
'empty' => true
]
);
See the docs for more info.
Update
If you're experiencing issues with find('list') it is perhaps because your model's displayField is not getting set correctly. Cake normally determines the displayField for the model on initialisation. If this isn't working, or you want a different field you can set this manually in the model's initialize() method. E.g.:-
class MagazinesTable extends Table
{
public function initialize(array $config)
{
$this->displayField('name');
}
}
Changing 'name' to the appropriate field.
Alternatively, you can choose which field Cake will use for the values returned by find('list') (this is particularly useful when you want to override the default displayField). E.g.:-
$this->Issues->Magazines->find('list', [
'keyField' => 'id',
'valueField' => 'name'
]);
Display selected option in month helper
$this->Form->month('students.month', [
'label' => false,
'value'=>date('m'),
'required'=>true
]);
This actually helped me.
$this->Issues->Magazines->find('list', [
'keyField' => 'id',
'valueField' => 'name'
]);