How to insert multiple record without loop in laravel - laravel

I have I need to insert multiple record in database . Currently I am inserting with loop which is causing timeout when record is big. Is there any way that we dont use loop?
$consignments = Consignment::select('id')->where('customer_id',$invoice->customer_id)->doesntHave('invoice_charges')->get();
foreach($consignments as $consignment){
InvoiceCharge::create(['invoice_id'=>$invoice->id,'object_id'=>$consignment->id,'model'=>'Consignment']);
}
consignment has hasOne relation in model
public function invoice_charges()
{
return $this->hasOne('App\Models\Admin\InvoiceCharge', 'object_id')->where('model', 'Consignment');
}

How about this:
$consignments = Consignment::select('id')->where('customer_id',$invoice->customer_id)->doesntHave('invoice_charges')->get();
foreach($consignments as $consignment){
$consignment_data[] = ['invoice_id'=>$invoice->id,'object_id'=>$consignment->id,'model'=>'Consignment'];
}
InvoiceCharge::insert($consignment_data);
In this way you enter with one query rather than loop. Just check if consignment_data array is ok.

If you want to save time, but can give more memory, you can use Cursor,
Cursor: You will use PHP Generators to search your query items one by one. 1)It takes less time 2) Uses more memory
$consignments = Consignment::select('id')->where('customer_id',$invoice->customer_id)->doesntHave('invoice_charges')->cursor();
foreach($consignments as $consignment){
InvoiceCharge::create(['invoice_id'=>$invoice->id,'object_id'=>$consignment->id,'model'=>'Consignment']);
}
You can refer from here

Related

Using Laravel Eloquent to count how many times something exists in an efficient manner

I have a table called rentals, within each row are columns state,city,zipcode which all house ids to another table with that info. There are about 3400 rentals. I am pulling each column to display the states,city and zipcode distinctly. I need to show how many rentals are in each one. I am doing this now via ajax, the person starts typing in what they want to see and it auto completes it with the count, but its slow because of the way im doing it.
$rentals_count = Rentals::where('published',1)->get();
foreach($states as $state) {
echo $state.”-“.$rentals_count->where(‘state’,$state->id)->count();
}
Above is roughly what im doing with pieces removed because they are not related to this question. Is there a better way to do this? It lags a bit so the auto complete seems broken to a new user.
Have you considered Eager loading your eloquent query? Eager loading is used to reduce query operations. When querying, you may specify which relationships should be eager loaded using the with method:
$rental_counts = Rentals::where('published',1)->with('your_relation')->get();
You can read more about that in Laravel Documentation
$rentals = Rentals::wherePublished(true)->withCount('state')->get();
When you loop through $rentals, the result will be in $rental->state_count
Setup a relation 'state' on rentals then call it like this
$rentals_count = Rentals::where('published',1)->with('state')->get()->groupBy('state');
$rentals_count->map(function($v, $k){
echo $v[0]->state->name .' - '. $v->count();
});
Meanwhile in Rentals Model
public function state(){
return $this->hasOne(State::class, 'state'); //state being your foreign key on rentals table. The primary key has to be id on your states table
}

changing a query result value according to wherehas condition in laravel

I am using laravel
I want to change the value of a column according to a specific condition.
if a condition is satisfied in wherehas then change the value of specific column to 1 let's say.How could i do it.
if i can call a function in the model inside the wherehas function to change the value how could I do it ??
i can iterate the result set using a 2 for loops and change it, however I want to decrease the complexity by changing the value while retrieving the data
Course::with('stages','stages.levels')->whereHas('stages.levels', function($query)use ($levelsarray){
$query->wherenotIn('id', $levelsarray);
here I want to change a column value in table levels
})->first();
Here is a general way,
Assuming you have Three models, Course, Stage, Level
When you are retrieving data from Level model, add an accessor,
For more info click here.
Eg:
On Level.php model,
public function getColumnNameAttribute($value) // replace ColumnName with column name
{
//write application logic here.
return $value;
}

Deleting multiple same id from mysql database

Below is my code for deleting all rows with ids one.It seems that only first index was deleted
and an error will trigger right away.How can i loop through the array and delete all rows with id one.
The array I've created here is only a representation from my database with multiple columns.
Any idea in resolving this problem is much appreciated.
public function deleteRow(){
$ids = ['1','1','1','3','3','1','1'];
foreach($ids as $id ){
$id = Scholarshipcount::find($id);
$id->delete();
}
}
my error
Call to a member function delete() on a non-object
Find() can fail to find the record, especially of you have multiple times the same PK as in your example (and you have already deleted the object the first time). You might want to consider using findOrFail instead.
You should use a different kind of approach instead. Assuming that your table name is scholarshipcounts then:
DB::table('scholarhipcounts')->whereIn('id', $ids)->delete();

Anonymous types alternative in Eloquent

Is there a way I can construct a query that will return not just existing entities on the model/table, but also create new variables populated according to a function/query. All done in a single query.
So something like this pseudocode.
Job::whereDate('created_at', '>=', $pdate)
->with('address')
->with('Employees'->count() as newprop);
Basically I want to get the job, address and also create a new property on the returned objects in the collection that will hold the employee count for each job.
What is the best way of going about this ? Maybe I should just create a new function/property on the Job model that returns Employees count ? Would that mean the application will make more db queries or will such property be populated anytime I use eloquent to get any Job object ?
If you want to add it to all Job model instances:
public function getNewpropAttribute($value) {
return count($employees);
}
That way you can call Job::find($id)->newprop; and it will execute that function. it is described here https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators

How do I define relation between users and points in Eloquent ORM

I have 3 tables:
Users - for storing users
User_point - for associacion between users and points(has only user_id and point_id)
Points for description of points(id, amount, description)
How do I define a relation between these? I tried
public function points(){
return $this->belongsToMany('\App\Point', 'user_point');
}
but when I do
return $user->points()->sum('amount');
it returns just one
Edit:
At first I tried making it like this as it makes more sense:
public function points(){
return $this->hasMany('\App\Point');
}
But it wouldn't work
SUM is an aggregate function and so it should only return one row.
$user->points will be a collection of points attached to that user.
$user->points() is a query that you can do additional work against (i.e. $user->points()->whereSomething(true)->get()).
As user ceejayoz pointed out, using user->points() is going to return a builder which you can do additional work on. I believe using sum() on that will look at the first row returned which is what you indicated is actually happening.
Likely, what you really want to do is $user->points->sum('amount');
That will get the sum of that column for the entire collection.

Resources