Searching for a Laravel equivalent - php

I am beginner webdeveloper.
I have small problem my model.
I have this migration and model:
Schema::create('stopwatches', function (Blueprint $table) {
$table->increments('id');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
Schema::create('timecycles', function (Blueprint $table) {
$table->increments('id');
$table->integer('timecycleable_id');
$table->string('timecycleable_type');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->boolean('status')->default(0);
$table->integer('worked_time')->default(0);
$table->timestamps();
});
class Stopwatch extends Model
{
protected $fillable = [
'case_id',
'user_id'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
'user_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function timeCycle()
{
return $this->morphMany(Timecycle::class, 'timecycleable');
}
public function caseInstance()
{
return $this->belongsTo(CaseInstance::class, 'case_id');
}
class Timecycle extends Model
{
protected $fillable = [
'case_id',
'timecycleable_id',
'timecycleable_type',
'status',
'worked_time'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function stopwatch()
{
return $this->morphTo();
}
}
In timecycles I have 2 record with status = 0 and status = 1: https://ibb.co/5vyh316
I need my stopwatches with only one timecycles with status = 1.
I make this code:
return $this->stopwatch::with(['timeCycle', 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', \Carbon\Carbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
In result I have booth items: https://ibb.co/WnJ58Kc
What's wrong in my code?
How can I repair it?
Please help me.

You're actually quite close, but whereHas() doesn't affect the loaded records. Use the same clause on your with() statement:
return $this->stopwatch::with(['timeCycle' => function ($q) {
$q->where('status', 1); // If you only want 1, you can do `->limit(1)` as well
}, 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', \Carbon\Carbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
Now, when looping over your data, each $record->timeCycle will only include whatever is specified in the with() clause.

It's likely the problem is generated by the with('timeCycle') clause. If you want to constraint your query by a relation, you need to specified it in both the whereHas and the with(), otherwise the eager loading will fetch all the elements making the whereHas irrelevant. Try this:
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => function ($query) {
$query->where('status', 1);
}
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($query) {
$query->where('status', 1);
})
->get();
Of course, given both constraints are equal, you could store it in a variable and pass it to both methods:
$timeCycleContraint = function ($query) {
$query->where('status', 1);
};
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => $timeCycleContraint
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', $timeCycleContraint)
->get();

Related

Laravel collection query: get count only for model with specific property

I have a page where I display a list of projects, including a count of a relationship(rmgs). This is the query:
Project::select('id', 'number', 'name', 'status')
->withCount(['rmgs as project_rmg_submitted' => static function ($query): void {
$query->where('submitted', true);
}])
->withCount(['rmgs as project_rmg_unsubmitted' => static function ($query): void {
$query->where('submitted', false);
}])
->get()
But I need the count only for projects that have the status='Approved'.
I just found the when method, but this check an external flag. I need to check the condition on the model.
Project::select('id', 'number', 'name', 'status')
--- this should be conditional for project.status='Approved' ----
->withCount(['rmgs as project_rmg_submitted' => static function ($query): void {
$query->where('submitted', true);
}])
->withCount(['rmgs as project_rmg_unsubmitted' => static function ($query): void {
$query->where('submitted', false);
}])
----------------------------------------------------------
->get()
Have you tried?
Project::select('id', 'number', 'name', 'status')
->withCount(['rmgs as project_rmg_submitted' => static function ($query): void {
$query->where('submitted', true);
}])
->withCount(['rmgs as project_rmg_unsubmitted' => static function ($query): void {
$query->where('submitted', false);
}])
->where('status','=','Approved')
->get();

Laravel boolean value return wrong data

I have table name payments in this table each row has column named paid which is boolean. When I try to get separate list of paid and unpaid rows based on this paid column it just return all rows regardless.
Code
Get unpaid rows
$purchases = Payment::wherePaid(false)
->where('employee_id', $user->id)
->orWhere('employer_id', $user->id)->with([
'employer',
'employee' => function($q) {
$q->select(['id', 'first_name', 'last_name']);
},
'template',
'training',
'contract',
])->get();
Get paid rows
$purchases = Payment::wherePaid(true)
->where('employee_id', $user->id)
->orWhere('employer_id', $user->id)->with([
'employer',
'employee' => function($q) {
$q->select(['id', 'first_name', 'last_name']);
},
'template',
'training',
'contract',
])->get();
Model
protected $casts = [
'paid' => 'boolean',
];
In both queries I am getting array of 4 which is include 3 unpaid and 1 paid row.
Update
Schema
public function up()
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('employer_id')->nullable();
$table->unsignedBigInteger('employee_id')->nullable();
$table->unsignedBigInteger('template_id')->nullable();
$table->unsignedBigInteger('contract_id')->nullable();
$table->unsignedBigInteger('training_id')->nullable();
$table->string('duration')->nullable();
$table->string('amount');
$table->boolean('paid')->default(false);
$table->string('booking_id')->nullable();
$table->string('invoice_no');
$table->timestamps();
});
Schema::table('payments', function (Blueprint $table) {
$table->foreign('employer_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('employee_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('template_id')->references('id')->on('contract_templates')->onDelete('cascade');
$table->foreign('contract_id')->references('id')->on('contracts')->onDelete('cascade');
$table->foreign('training_id')->references('id')->on('trainings')->onDelete('cascade');
});
}
I may be wrong, but I think your issue is that you are asking for paid = false AND employee_id = ID OR employer_id = ID. I think MySQL is thinking:
(paid = false AND employee_id = ID) OR (employer_id = ID)
So, try this query instead:
$purchases = Payment::wherePaid((false or true))
->where(function ($query) use ($user) {
return $query->where('employee_id', $user->id)
->orWhere('employer_id', $user->id)
})
->with([
'employer',
'employee' => function($query) {
return $query->select(['id', 'first_name', 'last_name']);
},
'template',
'training',
'contract',
])
->get();
That will change the query to:
(paid = false or true) AND (employee_id = ID OR employer_id = ID)

Store parent_id in laravel

I'm new to Laravel so I struggle. I have a comment system that worked perfectly fine but now I want to also add a reply system to it. So the way I decided to do it, is by adding a parent_id column to the comments table and then check if a comment has a parent. But I don't know how exactly the store method, in this case, should work. Here's my database set up for comments:
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->text('body');
$table->timestamps();
});
}
And now a set up for the reply column:
public function up()
{
Schema::table('comments', function (Blueprint $table) {
$table->unsignedBigInteger('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('comments');
});
}
Model:
class Comment extends Model{
use HasFactory;
protected $guarded = [];
public function post()
{
return $this->belongsTo(Post::class);
}
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
public function replies() {
return $this->hasMany('App\Comment', 'parent_id');
}
}
Controller:
public function store(Post $post){
request()->validate([
'body' => 'required'
]);
$post->comments()->create([
'user_id' => request()->user()->id,
'parent_id' => request()->get('id'),
'body' => request('body')
]);
return back();
}
I just don't know how exactly I can get parent_id in the store function so I would appreciate some suggetstions
it should be the comment id that got the reply
something like this
$post->comments()->create([
'user_id' => request()->user()->id,
'parent_id' => request()->get('comment_id'),
'body' => request('body')
]);
I hope it's helpful
use code :
public function store(Post $post) {
request()->validate([
'body' => 'required'
]);
$post->comments()->create([
'user_id' => request()->user()->id,
'parent_id' => request()->get('comment_id'),
'body' => request('body')
]);
return back();
}

How to search within an BelongsToMany Relationship

How do I search within a BelongsToMany Relationship within laravel?
Looks like I seem to be understanding something wrong
Below is my code:
public function search(Request $request, Project $post)
{
$this->validate($request, [
'query' => 'required'
]);
$query = $request->input('query');
$post = Post::where('title', 'like', "%$query%")
->orWhere($post->tags()->role, 'like', "%$query$%")
->paginate(6);
return view('post.search', [
'post' => $post,
]);
}
If you want to search into a relationship you may use whereHas or orWhereHas methods.
Your search function may be ok like this.
public function search(Request $request, Project $post)
{
$this->validate($request,[
'query' => 'required'
]);
$query = $request->input('query');
$post = Post::where('title', 'like', "%$query%")
->orWhereHas('tags', function($q) use ($query) {
$q->where('role', 'like', "%{$query}%");
})->paginate(6);
return view('post.search',[
'post' => $post,
]);
}

create index for following LARAVEL eloquent query

Hi I have more than 500k records in items table Its takes more than 9 seconds to execute this query ineed to make it milliseconds to execute this query using mysql index
$products = \App\items::with([
'item_store' => function($query) {
$query->select('size', 'item_id', 'item_store_id');
},
'pics' => function($query) {
$query->select('img_url', 'item_id');
},
'brand' => function($query) {
$query->select('item_id', 'brand_id');
},
'brand.brand' => function($query) {
$query->select('brand_id', 'brand_name');
}
])
->select('item_id', 'short_name', 'price', 'price_above')
->orderBy('Price', 'Asc')->whereIn('category_id', $arr)
->groupBy('Sku')
->paginate(20);
my database structure is [st] https://screenshots.firefox.com/JAmaKENMYRhQkEjx/ourweds.com
this is item table migration
Schema::create('item', function (Blueprint $table) {
$table->bigIncrements('item_id');
$table->string('item_name');
$table->integer('Sku');
$table->text('Description');
$table->text('short_description');
$table->text('category_id');
$table->string('color');
$table->double('price');
$table->double('indian_price');
$table->string('old_price');
$table->string('indian_old_price');
$table->timestamps();
});
item eloquent model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class items extends Model
{
//
protected $table = 'items';
protected $primaryKey = 'item_id';
protected $fillable = [
'category_id',
'item_name',
'Sku',
'Description',
'short_description',
'color',
'kik_cash_percentage',
'status',
'price',
'price_old',
'indian_price',
'short_name',
'price_above',
'short_name_alter',
'availability'
];
public function pics(){
return $this->hasOne( 'App\item_pics', 'item_id' );
}
public function item_store()
{
return $this->hasMany('App\item_store','item_id');
}
public function category()
{
return $this->belongsTo('App\categories','category_id');
}
public function brand()
{
return $this->hasOne('App\item_has_brand','item_id');
}
}

Categories