Mass update in Laravel Eloquent or DB - mysql

Is there anyone who knows how to do this without the technique of doing it in a one query string. I mean the popular ways I see on the net is by looping in data(the updates) and generating a single update statement and then fire a query. Is it possible for an Eloquent Approach or DB without looping?

This is posible with Eloquent, it might be necessary to enable mass-assignment, but you will get an error if so.
$post_data = Input::all();
$model = Model::find($id);
$model ->fill($post_data);
$model ->save();
or
$post_data = Input::all();
Model::find($id)->update($post_data);

Yes, you can do that but in that case, you have to make the array of data that is a loop is needed to store the data in the array with respective field_name => value of the table.
The following is the example:
$Array = array(); //This is needed to hold data while looping over $YourData
$YourData - is the array of data you want to store in the respective table.
foreach ($YourData as $YourDatakey => $YourDatavalue ){
$Array = [
'table_column_name' => $YourDatavalue['value_from_array'],
'table_column_name' => $YourDatavalue['value_from_array'],
'table_column_name' => $YourDatavalue['value_from_array'],
...... and so on
];
}
$InsertQuery= YourModelName::create($Array);
PS:
YourModelName model file should have the columns in protected
$fillable = ['column1','column2'....];
You should use App\Models\ModelName; at the top of the file.

Related

Keep sort order of json columns in Laravel after inserting new Key Value pair

I have a key value pair that I am inserting into a model with the following:
public function addContactDetail(Request $request){
$data = $request->all();
$contact_id = $data['contact_id'];
$contact = Contact::find($contact_id);
$details = $contact->details;
$details[$data['label']] = $data['value'];
$contact->details = $details;
$contact->save();
return response()->json($contact);
}
After insert it sometimes puts it randomly in the middle of the object. How do I keep it at the end?
If you are using Laravel 5 or greater version,
Try casting your json column into array in eloquent using mutators. like this.
inside your Contact Model
protected $casts = [
'details' => 'array',
];
By doing so, I guess you will get what you want. Try it and let me know

Yii2 insert partial data into table

I'm inserting into a table data coming from another table which is basically a subset of the first table.
$partialProduct = partialProducts::find()
->where(['company_id' => $company_id])
->andWhere(['productName' => $productName])->one();
$partialProductData = ($partialProductData['attributes']);
$product = Yii::$app->db->createCommand()
->insert('products', [
'field1' => $field1value,
...
...
'fieldN' => $fieldN,
])->execute();
Something like that could work, but considering that partialProductData has a lot of fields, I was searching for a cleaner way of doing it.
I've tried with a foreach(partialProductData as $key => $value) approach, considering that the keys are named as the products table column names, but I struggled in obtain something viable.
As suggested, creating an array of key/values pairs should work if the keys match the table fields in both models. Something like:
$data = [];
foreach($partialProduct->attributes as $key => $value):
$data[$key] = $value;
endforeach;
$product = Yii::$app->db->createCommand()
->insert('products', $data)
->execute();
Alternatively, you could use massive assignment. Again, for this to work the fields on both models would need to match:
$product = new Product;
$product->attributes = $partialProduct->attributes;
$product->save();
If you only want to save certain fields from your partialProducts to your Product, you can use scenarios to select the specific fields you want to be to set with massive assignment:
In Product.php
const SCENARIO_TEST = 'test';
...
public function scenarios()
{
return [
self::SCENARIO_TEST => ['field_1', 'field_2'], // Any field not listed here will not be set
];
}
And wherever you're doing the save:
$product = new Product;
$product->scenario = Product::SCENARIO_TEST;
$product->attributes = $partialProduct->attributes;
$product->save();

Delete multiple rows in YII2

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]);

Retrieve every model and return three values

I am looking for a way to retrieve all models in a database. Then loop through all of the models and read out the values for name, firstname and phonenumber.
So far I've gotten this and failed to go past it:
$searchModel = new EmployeeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
I am then looking to implement those three values in a simple HTML table:
<tr><td>$firstname</td><td>$name</td><td>$phone</td></tr>
The table should be part of a PDF output, so ideally I would save it to a variable:
$html_table = '<tr><td>$firstname</td><td>$name</td><td>$phone</td></tr>';
I would need to get this for every model that fulfills the criteria of status = 'active' in the database.
So far I've only been able to get tables via gridView and not in a HTML template either.
You don't really need a data provider to achieve this, you could simply try :
$models = Employee::find()->where(['status'=>'active'])->orderBy('name ASC')->all();
foreach ($models as $model) {
echo "<tr><td>{$model->firstname}</td><td>{$model->name}</td><td>{$model->phone}</td></tr>";
}
Read more : http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#querying-data
You can get all models like this:
$employees = Employee::find()
->select('firstname, name, phone')
->asArray()
->where(['status'=>'active'])
->all();
This way you will get an array of arrays containing the 3 selected fields, so now you only need to use a foreach to loop through them and create the table:
$html = '<table>';
foreach($employees as $employee) {
$html .= '<tr><td>'.$employee['firstname'].'</td><td>'.$employee['name'].'</td><td>'.$employee['phone'].'</td></tr>';
}
$html .= '</table>'

YII SQL Query Optimization

I have a huge list of IDs that i need to query through a table to find if those IDs are available in the table, if yes fetch its model.
Since there are few thousands of IDs this process is really slow as I'm using CActiveRecord::find() mothod
ex. $book = Book::model()->find('book_id=:book_id', array(':book_id'=>$product->book_id));
I even indexed all possible keys, still no improvement.
Any suggestions to improve the execution speed?
thanks in advance :)
1)
Make a list of book ids
foreach $product in Product-List
$book_ids[$product->book_id] = $product->book_id;
Now query all Book models ( indexed by book_id )
$books = Book::model()->findAll(array(
'index' => 'book_id',
'condition' => 'book_id IN (' . implode(',', $book_ids). ')',
));
Integrate $books in your code, I believe you are looping through all products.
foreach $product in Product-List
if( isset($books[$product->book_id]) )
$model = $books[$product->book_id]
2) Another way (I am just assuming you have Product model)
in Product model add a relation to Book
public function relations() {
.......
'book'=>array(self::HAS_ONE, 'Book', 'book_id'),
.......
}
While retrieving your product list, add 'with' => array('book') condition, with any of CActiveDataProvider or CActiveRecord ...
//Example
$productList = Product::model()->findAll(array(
'with' => array('book'),
));
foreach( $productList as $product ) {
.......
if( $product->book != null )
$model = $product->book;
......
}
with either way you can reduce SQL queries.
Better if you use schema caching because Yii fetches schema each time we execute a query. It will improve your query performance.
You can enable schema caching by doing some configuration in config/main.php file.
return array(
......
'components'=>array(
......
'cache'=>array(
'class'=>'system.caching.CApcCache', // caching type APC cache
),
'db'=>array(
...........
'schemaCachingDuration'=>3600, // life time of schema caching
),
),
);
One more thing you can fetch specific column of the table that will improve performance also.
You can do it by using CDbCriteria with find method of CActiveRecord.
$criteria = new CDbCriteria;
$criteria->select = 'book_id';
$criteria->condition = 'book_id=:book_id';
$criteria->params = array(':book_id'=>$product->book_id);
$book = Book::model()->find($criteria);
I would suggest you to use any nosql database if you are processing thousands of records if that is suitable.