I have to same multiple row in add form(controller) but it's not saving multiple record. Do i have to move save under the foreach? or what I can do to save multiple row?
$boldNumberRequest = $this->BoldNumberRequest->newEntity();
$boldNumberRequest = $this->BoldNumberRequest->patchEntity($boldNumberRequest, $this->request->data);
$this->BoldNumberRequest->saveMany($boldNumberRequest)
Here what i am getting in $this->request->data
(int) 0 => [
'bold_number_from' => '1',
'bold_number_to' => '1000',
'is_approved' => '1',
'unique_series' => '030318',
'owner_company_id' => '1'
],
(int) 1 => [
'bold_number_from' => '1',
'bold_number_to' => '1000',
'is_approved' => '1',
'unique_series' => '100318',
'owner_company_id' => '1'
],
Your problem is that you're creating a single entity using $this->BoldNumberRequest->newEntity() and then trying to patch it with the data of multiple entities.
What you want can be found in the CakePHP documentation about Saving Multiple Entities:
You need to create multiple entities from your data:
$entities = $this->BoldNumberRequest->newEntities($this->request->data);
$this->BoldNumberRequest->saveMany($entities);
Related
Hoping someone may be able to point me in the right direction.
I have a app that consists of (among other things) Recommendations and Assessments. They are joined with a join table that includes extra fields that I would like to update but am struggling to figure out how.
As you can see above, when I create a Reccommendation, I set the following fields:
default_user_impact
default_business_impact
default_deployment_complexity
default_criticality
Now when I create a new Assessment or edit one that has not got any Recommendations linked the Assessment saves fine because nothing is needing to be written to the join table.
When I try to edit an Assessment to include one or more Recommendations, the app tries to write the link to the join table and fails because the user_impact, business_impact, deployment_complexity and criticality fields aren't specified - perfectly normal because I have set the fields to required in MySQL right? The error I get in CakePHP is
SQLSTATE[HY000]: General error: 1364 Field 'user_impact' doesn't have a default value
What I want to be able to do is at the time of editing or creating an Assessment is to use the values in the Recommendations table to populate the corresponding join table entries. Any ideas how to go about this?
So as an example:
user_impact = default_user_impact
business_impact = default_business_impact
deployment_complexity = default_deployment_complexity
criticality = default_criticality
The reason I want to do this is so that I can have the Recommendations set with values for those fields, and then if a user wants to run an assessment and they want to adjust the values just for their own assessment then it won't impact others etc.
Here is my AssessmentsTable association.
$this->belongsToMany('Recommendations', [
'foreignKey' => 'assessment_id',
'targetForeignKey' => 'recommendation_id',
'joinTable' => 'assessments_recommendations',
'through' => 'assessments_recommendations',
]);
Here is my RecommendationsTable association.
$this->belongsToMany('Assessments', [
'foreignKey' => 'recommendation_id',
'targetForeignKey' => 'assessment_id',
'joinTable' => 'assessments_recommendations',
'through' => 'assessments_recommendations',
]);
Here is my AssessmentsRecommendations association:
$this->belongsTo('Assessments', [
'foreignKey' => 'assessment_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Recommendations', [
'foreignKey' => 'recommendation_id',
'joinType' => 'INNER',
]);
This is what my AssessmentsController edit function looks like:
public function edit($id = null)
{
$assessment = $this->Assessments->get($id, [
'contain' => ['Recommendations'],
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$assessment = $this->Assessments->patchEntity($assessment, $this->request->getData(), ['associated'=>['Recommendations._joinData']]);
if ($this->Assessments->save($assessment, ['associated' => ['Recommendations._joinData']])) {
$this->Flash->success(__('The assessment has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The assessment could not be saved. Please, try again.'));
}
$clients = $this->Assessments->Clients->find('list', ['limit' => 200]);
$recommendations = $this->Assessments->Recommendations->find('list', ['limit' => 200]);
$this->set(compact('assessment', 'clients', 'recommendations'));
}
Now when I've added the beforeSave function to the AssessmentsRecommendationsTable I see the following error:
Argument 2 passed to App\Model\Table\AssessmentsRecommendationsTable::beforeSave() must be an instance of App\Model\Table\EntityInterface, instance of Cake\ORM\Entity given, called in /var/www/html/csa-portal/vendor/cakephp/cakephp/src/Event/EventManager.php on line 310
Any help would be much appreciated.
First, the associations you are using are wrong. It should be like this
For AssessmentsTable
$this->hasMany('AssessmentsRecommendations', [
'foreignKey' => 'assessment_id'
]);
For RecommendationsTable
$this->hasMany('AssessmentsRecommendations', [
'foreignKey' => 'recommendation_id'
]);
For AssessmentsRecommendationsTable
$this->belongsTo('Assessments', [
'foreignKey' => 'assessment_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Recommendations', [
'foreignKey' => 'recommendation_id',
'joinType' => 'INNER',
]);
Now for the default values, you have to user beforeSave in you AssessmentsRecommendationsTable.php file.You can modify your data as per your need here before the save.
public function beforeSave(Event $event, EntityInterface $entity, \ArrayObject $options)
{
if ($entity->isNew()) { // Returns true when you add new record
$recommendation = TableRegistry::getTableLocator()->get('Recommendations')->get($entity->recommendation_id);
$entity->user_impact = $recommendation->default_user_impact;
$entity->business_impact = $recommendation->default_business_impact;
$entity->deployment_complexity = $recommendation->default_deployment_complexity;
$entity->criticality = $recommendation->default_criticality;
}
}
I have never used belongsToMany, if the associations works for you then ignore the association part.
Have you considered writing a Rule to handle this?
https://book.cakephp.org/3/en/orm/validation.html#applying-application-rules
Is it possible to loop through this array in mysql and execute a delete statement where the category_id column is equal to the current value been looped in that array below.
$row = [
'type' => '3',
'name' => 'Warez',
'category_id' => 'IAB26-2',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Spyware/Malware',
'category_id' => 'IAB26-3',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Copyright Infringement',
'category_id' => 'IAB26-4',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Uncategorized',
'category_id' => 'IAB24'
]
I have tried this
foreach($row as $value) {
$this->execute('DELETE from categories WHERE category_id = '.$value['category_id'].'');
}
doesn't seem to work as it should. Is there is better Sql command for this kind of operation?
Your code is insecure because it's possible to inject SQL. So an attacker might execute whatever he wants in your SQL query.
If this is really CakePHP code, why aren't you using the ORM? You cleary should read https://book.cakephp.org/3.0/en/orm.html the Table Objects and Deleting Data section. If not don't use wrong tags.
Assuming this is done in a table object, the most simple way to do this is:
$ids = Hash::extract($data, '{n}.category_id');
if (!empty($ids)) {
$this->deleteAll([
'category_id IN' => $ids
]);
}
You probably just need to wrap the value you concatenate with quotes (because it's not numeric).
Something like this:
$this->execute('DELETE from categories WHERE category_id = "'.$value['category_id'].'"');
However, doing DELETE ... WHERE as suggested in one of the comments would yield better performance.
Also, note that if the data comes from the user then it may be susceptible to SQL injection, so you should read about and use parameterized queries rather than concatenation.
Using an IN clause
$list = array(); foreach ($row as $item) {
$list[] = "'{$item['category_id']}'";
}
$sql = 'DELETE from categories WHERE category_id IN ('.implode(',',$list).')';
$this->execute( $sql );
I'm using the following code for promoting to front page but it's not working. It is inserting entry in node table only. I need to insert entry into another table to promote it.
Node table showing promote=1 value in the table but the issue is while checking it through drupal admin and editing article, it's not showing checked check box or not displaying to front page.
$insert = db_insert('node')
->fields(array(
'title' => $rtitle,
//'vid' => '',
'type' => 'article',
'language' => 'und',
'uid' => '1',
'created' => $pubdate,
//'comment' => '',
'promote' => '1',
//'sticky' => '',
//'tnid' => '',
'status' => '1',
))
->execute();
So the promote=1 is not display to front page. also all the variables are working fine and query is also working correctly.
enter image description here
Have you tried using the native Drupal method for creating a node in code?
global $user;
$node = new stdClass();
$node->title = "My Cool Article";
$node->type = "article";
node_object_prepare($node);
$node->language = LANGUAGE_NONE;
$node->uid = $user->uid;
$node->status = 1;
$node->promote = 1;
$node->comment = 0;
node_save($node);
I'm pulling data from several remote DataSources, restructuring to fit my models schema and finally passing the array to MyModel::saveAll();
I'd like to avoid importing duplicate records (ie, don't import if MyModel.external_id = 120 & MyModel.external_type = 'basecamp.comment' already exists in db).
What's the most efficient way of going about this?
Sample data:
$data['MyModel'] = [
[
'title' => 'foo',
'created' => '2013-12-18 11:29:06',
'external_id' => 120,
'external_type' => 'github.commit'
],
[
'title' => 'bar',
'created' => '2013-12-18 13:22:06',
'external_id' => 120,
'external_type' => 'basecamp.comment'
]
];
NB: Notice that MyModel.external_id isn't unique on it's own.
This is where validation comes into play. In your MyModel class, add the following:
public $validate = array(
'external_type' => array(
'rule' => 'idAndTypeUnique',
'message' => "Type and ID already exist"
)
);
public function idAndTypeUnique()
{
$existing = $this->find('first', array(
'conditions' => array(
'external_id' => $this->data[$this->name]['external_id'],
'external_type' => $this->data[$this->name]['external_type']
)
));
return (count($existing) == 0);
}
Your saveAll() call would look like:
$this->MyModel->saveAll($data, array('validate' => true));
The easiest way is to make a unique index on those two fields.
alter table my_model add unique index(external_id, external_type);
This forces the constraint in the database level.
If you want to force this constraint in the cake layer, then check this out:
cakephp isUnique for 2 fields?
I've been trying to find an answer to my problem for hours. I am currently working with cakePHP 2.4.
I have two models, Users and Groups. I have created the following associations for each:
(User.php)
public $hasAndBelongsToMany = array(
'Group' =>
array(
'className' => 'Group',
'joinTable' => 'groups_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'group_id',
'unique' => true,
)
);
and (Group.php):
public $hasAndBelongsToMany = array(
'GroupUser' =>
array(
'className' => 'User',
'joinTable' => 'groups_users',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => true,
)
);
The reason I use GroupUser and not "User" is I get an error because I have already used "User for some other relation.
My form looks like this:
echo $this->Form->create('Group', array('controller' => 'group','action' => 'add'));
echo $this->Form->input('User.id', array('type' => 'hidden', 'value' => $authUser['id']);
echo $this->Form->input('Group.address');
echo $this->Form->end(__('Save', true));
I also have a table called groups_users with "id", "user_id" and "group_id"
When I submit the form, it created the new Group and saves the data, but the association is not created.
I tried manually filling a groups_users record with an existing user_id and group_id but still, when I use find(All), it doesn't find the expected association like it should according to the books.
I debugged the array that is being saved and it looks like this:
Array
(
[User] => Array
(
[user_id] => 39
)
[Group] => Array
(
[address] => asdasd, San Antonio, Texas 78233, EE. UU.
)
)
This is the code in my GroupsController add function:
if ($this->Group->save($this->request->data)) {
// redirect or do something
}
I have tried changing the array to work with saveAll like in the books, still only created new record but no association. And as I said, I mannually created a record and tried finding it and it wouldn't find it anyway.
I solved it apparently, I think it was because I hadn't created the GroupsUser.php model file. Not rreally sure because I changed a bunch of stuff! But maybe it helps someone.