I have a form with one add button. Next row will append whenever i click on add button and all entered data should store into database. I can do for single record but unable to do with multiple records. Please provide any help for my issue. Thanks in advance.
$this->db->insert_batch() is used for bulk insert.
Example of how it works (assuming I have a series of 20 records to insert) :
array_push($newRecords, array(
"property1" => 1
"property2" => "two"
));
//...
array_push($newRecords, array(
"property1" => 20
"property2" => "twenty"
));
$this->db->insert_batch("tableName", $newRecords);
There are two different ways to do this:
you can put insert code in foreach
foreach($variable as $key=>$value){
$this->db->insert('table name',array('fieldname'=>'values'));
}
this above method called every time for every loop
or used the batch methods
$this->db->insert_batch('table name',$dataArray);
this above method will called one time only.
Related
In my database there is a content table and when fetching data from this table I would like to append field url to the results, which is based on slug field which is contained in the table. Anyway, I have seen a way to do this in the previous versions of cakephp using behavior for the model of this table and then modifying results in afterFind callback in the behavior class. But in version 3 there is no afterFind callback, and they recommend using mapReduce() method instead in the manual, but this method is poorly explained in the manual and I cant figure out how to achieve this using mapReduce().
After little bit of research I realized that the best way to append the url field field to find results is using formatResults method, So this is what I did in my finders:
$query->formatResults(function (\Cake\Datasource\ResultSetInterface $results) {
return $results->map(function ($row) {
$row['url'] = array(
'controller' => 'content',
'action' => 'view',
$row['slug'],
$row['content_type']['alias']
);
return $row;
});
});
I have an array of objects fetched from database:
$masterListContacts = MasterListContacts::find()
->select('master_list_contacts.*')
->innerJoin('master_contacts', '`master_contacts`.`id` = `master_list_contacts`.`master_contact_id`')
->with('masterContact')
->where(['user_id' => \Yii::$app->user->identity->id, 'slug' => $slug])
->all();
Under certain circumstances, I need to delete all rows from the database represented in this array. But with both delete() and deleteAll() methods I got an error Call to a member function ... on array. Could someone tell me please which one is the best way to accomplish this?
UPDATE:
Here is my database structure.
Found better solution:
\Yii::$app
->db
->createCommand()
->delete('master_contacts', ['id' => $deletableMasterContacts])
->execute();
Where $deletableMasterContacts is array of master_contacts ids, which should be deleted
You can painlessly remove ->select('master_list_contacts.*').
->innerJoin('master_contacts', '`master_contacts`.`id` = `master_list_contacts`.`master_contact_id`')
performs the same work that ->joinWith('masterContact').
For delete entites try use this code:
MasterListContacts::deleteAll(['user_id' => \Yii::$app->user->identity->id, 'slug' => $slug]);
I'm working on a page which lists staff members for a large company and trying to minimise the number of times I'm forced to query the database as it gets quite complex and slow.
'person' is a custom post type (there are about 300 people)
'date_accredited' is a date field added via Advanced Custom Fields plugin.
Only accredited staff will have a 'date_accredited'.
I need to list every 'person' BUT, with ALL accredited staff listed first (so about 20 accredited staff come at the top).
At the moment, I am doing a call to WP_Query like:
$args = array(
'posts_per_page' => -1,
'post_type' => 'people',
'no_found_rows' => true,
'meta_key' => 'date_accredited'
);
$people = new WP_Query($args);
After that I'm doing:
while($people->have_posts()): $people->the_post();
$my_post_meta = get_post_meta($post->ID, 'date_accredited', true);
if (!empty($my_post_meta)) {
array_push($accredited, $post);
} else {
array_push($notAccredited, $post);
}
endwhile;
Leaving us with two arrays of 'person' objects. My thinking here was that I would be able to do something like the following to get the list I want:
foreach($accredited as $person):
personTile($person);
endforeach;
foreach($notAccredited as $person):
personTile($person);
endforeach;
I'm trying to avoid re-querying the database.
The personTile(); function was supposed to output various info and HTML (the_post_thumbnail() and various Advanced Custom Fields fields), but what I'm realising now is that none of this is included in the post objects I get from WP_Query(), so I'm forced to use things like:
get_the_post_thumbnail($person->ID)
get_permalink($person->ID)
get_field('date_accredited', $person->ID)
All of these cost another DB Query (each!), and worse still since they are in a loop each one happens around 300 times.
Is there any way to get the permalink, thumbnail and ACF fields to be included in the original DB Query? Would I need to resort to a custom MySQL Query???
Any other suggestions welcome!
I execute a simple insert query, however this insert is done multiple times sometimes unexpectedly. The code for insert is :
$query=$this->db->query("INSERT INTO clientaccesshistory (jobid, clientid,firstname,lastname,clientname,menu,submenu,starttime) VALUES ('$time','$userID','$firstname','$lastname','$clientname','Monitor/Verify', '$this->job_name',current_timestamp() )");
When i look in the database though this information is sometimes there 3 times, sometimes its just once like it is supposed to be. I think this is some issue with connecting to mysql, and then retries till it inserts three times?
I tested the front end to see if the function is actually be called more than once by putting an alert there, but no problem there whatsoever.
Your code almost certainly has to be in a variable loop of some kind. This code, like wonk says, will not add more than one record, ever.
This won't be of much help, but you can try using this-
$arr = array(
jobid => $time,
clientid => $userID,
firstname => $firstname,
lastname => $lastname,
clientname => $clientname,
menu => 'Monitor/Verify',
submenu => $this->job_name,
starttime => current_timestamp()
);
$this->db->insert('clientaccesshistory', $arr);
I have a large data set (over a billion rows). The data is partitioned in the database by date. As such, my query tool MUST specify an SQL between clause on every query, or it will have to scan every partition.. and well, it'll timeout before it ever comes back.
So.. my question is, the field in the database thats partitioned is a date..
Using CakePHP, how can I specify "between" dates in my form?
I was thinking about doing "start_date" and "end_date" in the form itself, but this may bring me two a second question.. how do I validate that in a model which is linked to a table?
If I am following you correctly:
The user must specify start/end dates for find queries generated from a form
You need to validate these dates so that, for example:
end date after start date
end date not centuries away from start date
You want validation errors appearing inline within the form (even though this isn't a save)
Since you want to validate these dates they will be harder to grab when they are tucked away inside your conditions array. I suggest trying to pass these in separately and then dealing with them later:
$this->Model->find('all', array(
'conditions' => array(/* normal conditions here */),
'dateRange' => array(
'start' => /* start_date value */,
'end' => /* end_date value */,
),
));
You should hopefully be able to handle everything else in the beforeFind filter:
public function beforeFind() {
// perform query validation
if ($queryData['dateRange']['end'] < $queryData['dateRange']['start']) {
$this->invalidate(
/* end_date field name */,
"End date must be after start date"
);
return false;
}
/* repeat for other validation */
// add between condition to query
$queryData['conditions'][] = array(
'Model.dateField BETWEEN ? AND ?' => array(
$queryData['dateRange']['start'],
$queryData['dateRange']['end'],
),
);
unset($queryData['dateRange']);
// proceed with find
return true;
}
I have not tried using Model::invalidate() during a find operation, so this might not even work. The idea is that if the form is created using FormHelper these messages should make it back next to the form fields.
Failing that, you might need to perform this validation in the controller and use Session::setFlash(). if so, you can also get rid of the beforeFind and put the BETWEEN condition array in with your other conditions.
if you want to find last 20 days data .
$this->loadModel('User');
//$this->User->recursive=-1;
$data=$this->User->find('all', array('recursive' => 0,
'fields' => array('Profile.last_name','Profile.first_name'),'limit' => 20,'order' => array('User.created DESC')));
other wise between two dates
$start = date('Y-m-d') ;
$end = date('Y-m-d', strtotime('-20 day'));
$conditions = array('User.created' =>array('Between',$start,$end));
$this->User->find("all",$conditions)
You could write a custom method in your model to search between the dates:
function findByDateRange($start,$end){
return $this->find('all',array('date >= '.$start,'data >= .'$end));
}
As far as validating, you could use the model's beforeValidate() callback to validate the two dates. More info on this here.
function beforeValidate(){
if(Validation::date($this->data['Model']['start_date'])){
return false;
}
if(Validation::date($this->data['Model']['end_date'])){
return false;
}
return parent::beforeValidate();
}
Does that answer your question?