Update many in Laravel for one-to-many relationship - laravel

I have a one-to-many relationship in laravel. Author to Books. How would I update all records in specific book and remove those that are not in my array. For example, $book is array with author, page, publication and I want to update those records and at the same time detach those that are not there?
I used $book->update($array) but that failed. I also used sync and that failed because it can only be used with many-to-many

Here is some example of how to update many records in the model using where conditions.
Book::where('author', $author_name)
->update([
'price' => 10000, // Add as many as you need
]);
Book::where('author',$author)
->where('publication', $publication)
->update([
'price' => 10000,
]);
// Or More Dynamic
Book::whereAuhorAndPublication( $author_name, $publication )
->update([
'price' => 10000,
]);
it would be nice if you share an example of data and request data.

Related

Laravel increment column in updateOrCreate and get the model

I am trying to increment a column and updateorcreate a record in one query by doing so:
$model = Model::updateOrCreate([
'email' => $email
], ['received_at' => $received_at])->incremet('received_count');
This does the job as I wanted it too. It updates or create a record and increments the received_count column.
But after the query, I wanted to get the updated/created row, but when I log $model, it only logs 0 or 1. I can confirm that this is because of the ->increment().
But to be honest, I don't know any way how to increment the received_count column other than how I currently did it.
How do I achieve so that it updates or create a record, at the same time increments the received_count column, and after all of this, returns the updated/created object?
As much as posssible, I want this all in one query. Getting the model should be a memory.
$model = Model::updateOrCreate(['email' => $email], ['received_at' => $received_at]);
$model->increment('received_count');
$model->refresh(); // this will refresh all information for your model.
or you can simply:
$model = Model::updateOrCreate(['email' => $email], ['received_at' => $received_at]);
tap($model)->increment('id'); // this will return refreshed model.
just fresh model after incremet:
$model = Model::updateOrCreate([
'email' => $email
], ['received_at' => $received_at]);
$model->incremet('received_count');
$model->fresh();

Update collection with WhereIn statment with their relation

I have code updating a collection as follows
Transaction::whereIn('id', $inProcessIds)
->update([
'transfer_status' => SaleTransaction::TRANSFER_STATUS_TRANSFERRED
]);
In Transaction I have relation to another model
public function sale_offer() {
return $this->hasOne('App\SaleOffer', 'sale_offer_id', 'id');
}
What I want to do is update related model at once when I updating Transaction
Here's what I tried to do is
Transaction::whereIn('id', $inProcessIds)->with('sale_offer')
->update([
'transfer_status' => SaleTransaction::TRANSFER_STATUS_TRANSFERRED
'transaction.sale_offer => 1'
]);
or
Transaction::whereIn('id', $inProcessIds)->sale_offer()
->update([
'transfer_status' => SaleTransaction::TRANSFER_STATUS_TRANSFERRED
'transaction.sale_offer => 1'
]);
]);
You can update related model by extract sale_offers ids from Transaction table then update sale_offer :
$sale_offer_ids=Transaction::whereIn('id', $inProcessIds)->with('sale_offer')->pluck('sale_offer_id')->toArray();
then update sale offer :
SaleOffer::whereIn('id',$sale_offer_ids)->update(['amount_sent'=>$amount_sent]) ;

Two fields overwriting each others values on saving in Backpack for Laravel CRUD (spatie/laravel-tags implementation issues)?

I am trying to use spatie/laravel-tags together with Backpack for Laravel. I have 2 types of tags defined. Currently I have extended the Tag model from spatie/laravel-tags as MyCategory and MyTag and added global scopes to separate the two tag types. This works to the extent that it will display the current categories and tags correctly in Backpack, but when I try to save any changes it will only save the entries in the last field, and delete everything in the first field.
Here is my current field configuration for my CRUD:
$this->crud->addField([
'name' => 'categories',
'label' => 'Categories',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyCategory',
'pivot' => true,
]);
$this->crud->addField([
'name' => 'tags',
'label' => 'Tags',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyTag',
'pivot' => true,
]);
When I check Laravel Telescope I see that the same thing happens for both fields. First all current tags (regardless of type) for the item I am saving are deleted, and the new tags from the field are added. This is then repeated for the second field, which of course deletes the tags from the first field that should also be kept.
It seems that GlobalScope on my extended Tag models does not stick around for this part. Is there any way to reintroduce the scopes into the queries run by backpack to get these tags to save correctly?
In my CrudController I created custom update and store functions. See the update example below. This seems to work fine. There are still 2 queries being run, with the second one undoing the first one, but for my purposes this is a good enough workaround to be able to have 2 fields with different tag types in the same form in Backpack, using spatie/laravel-tags.
public function update(UpdateRequest $request)
{
$request = request();
// Merge the values from the two tag fields together into the second field
$request->merge(['tags' => array_merge((array)$request->input('categories'), (array)$request->input('tags'))]);
$redirect_location = $this->traitUpdate($request);
return $redirect_location;
}

Elasticsearch searching in different results

Im using Elasticsearch with laravel and Elasticquent https://github.com/elasticquent/Elasticquent over the Eloquent model.
Each user of my project can search in a different result of objects.
I have for example
$user_books->addToIndex();
Books::search($search);
And the problem is that everytime when someone go to the current step the elasticsearch is filled with his results.And at the end I have a combined result for each user with their books together.. which is a problem.
I need one user to search only into his results.
How can I achieve that? I think that I probably must delete the indexes after search because I dont need them anymore.
And then
There is no need to delete your indexes,
instead you should index the books added by users by building a custom index
of their user_id like this :-
$data = [
'body' => [
'book' => '$book->name',
'user_id' => Auth::user()->id,
],
'index' => 'your application name',
'type' => 'books',
'id' => $book->id,
];
and then you can use custom queries to search for book belonging to that user only like this
$books = Book::searchByQuery(array('match' => array('user_id' => Auth::user()->id)));
Refer to Query based search and Indexing and Mapping section here

Laravel Eloquent - Inserting multiple records

How do we insert multiple records using eloquent in Laravel?
Basically this:
Teacher::create([
'user_id' => $user->id,
'college_id' => $collegeId,
'first_name' => $this->faker->firstName(),
'last_name' => $this->faker->lastName()
],[...],[...]);
Okay, I just came across the github request where Taylor replied that it is not possible with Eloquent and to use Query builder instead.
Here is the link to the issue:
https://github.com/laravel/framework/issues/1295

Resources