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,
]);
}
Related
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();
I have a laravel 7.14 app.
I'm trying to get the search result based on brand name = query.
The problem is with building link to display individual product. It takes brand slug instead of product slug. When I search with brand name I get the desired result but to view a individual product link fetches the brand slug instead of product slug. If I remove the slug from brands table I get an error in displaying results.
My products table has brand_id which tags the brand in product. In brands table I have 'name' and 'slug'.
Products fields:
'image',
'title',
'slug',
'description',
'brand_id',
'category_id',
Brands fields:
'name',
'slug',
Here's my search in ProductsController:
public function search(Request $request)
{
$validator = Validator::make($request->all(), [
'query' => 'required|min:3',
]);
if ($validator->fails()) {
return back()->with('toast_error', 'Please enter at least 6 character');
}
$query = $request->input('query');
$products = Product::where('title', 'like', "%$query%")
->orWhere('molecules', 'like', "%$query%")
->orWhere('text', 'like', "%$query%")
->join('brands', 'brands.id', '=', 'brand_id')
->orWhere('name', 'like', "%$query%")->paginate(10);
// Search with paginate
// $products = Product::search("%$query%")
// ->paginate(20);
$categories = Category::all();
$brands = Brand::all();
return view('products.search')->with([
'products' => $products,
'categories'=> $categories,
'brands' => $brands,
]);
}
Just give alias to one of the slug columns in your query. For example
$products = Product::select('products.*', 'brands.name', 'brands.slug as brand_slug')
->where('title', 'like', "%$query%")
->orWhere('molecules', 'like', "%$query%")
->orWhere('text', 'like', "%$query%")
->join('brands', 'brands.id', '=', 'brand_id')
->orWhere('name', 'like', "%$query%")->paginate(10);
I am working on laravel/php in which I am checking how the method that is being used in the controller to return the view.
public function client($uuid) {
$client = clients::with([
'client_details' => function($q){
$q->with([
'client_ratings' => function($q){
$q->with(['rating_review',
'rating_user' => function($q){
$q->select('user_id','first_name','last_name');
},
'rating_user_media' => function($q) {
$q->select('client_id','owner_id','url')->where('media_type','image')->where('context','user');
}]);
$q->orderBy('created_at', 'desc');
$q->take(2);
}]);
},'owner_details','media','cancellation_policy'])->where('uuid',$uuid)->first();
$groups = groups::getgroups(NULL);
$data = [
'groups' => $groups,
'client' => $client
];
//echo '<pre>';var_dump(json_decode(json_encode($data)));exit;
return View::make('client',['data'=>$data]);
}
Problem Statement:
The above php code is creating the JSON but I am not sure how is this JSON getting created.
I would like to create an orderBy ('created_at', 'desc') and paginate, for my articles posted in my account, here is my code.
MyaccountController
public function viewProfile($username) {
if($username) {
$user = User::where('username', $username)->firstOrFail();
} else {
$user = User::find(Auth::user()->id);
}
return view('site.user.account', [
'user' => $user,
'events' => $user->events,
'articles' => $user->articles,
]);
}
Assuming the relationship is correct on the User model:
'articles' => $user->articles()->orderByDesc('created_at')->paginate()
Hi there I have two routes that look identical except that one has an extra paramter called genre how do make them call their on routines and not have them mixed up.
Route::get('browse/{product_slug}', array(
'as' => 'products.view_by_producttype',
function($slug)
{
}
))->where('product_slug', '[A-Za-z\-]+');
Route::get('browse/{producttype_slug}/{genre_slug}', array(
'as' => 'products.view_by_producttype_genre',
function($productype_slug, $genre_slug)
{
}
))->where('producttype_slug', '[A-Za-z\-]+')->where('genre_slug', '[A-Za-z\-]+');
Upated Code and order:
Route::get('browse/{producttype_slug}', array(
'as' => 'products.view_by_producttype',
function($producttype_slug)
{
$producttype = ProductTypes::where('slug', '=', $producttype_slug)->firstOrFail();
$items = DB::table('products')->join('productvariations', function($join) {
$join->on('productvariations.product_id', '=', 'products.id');
})->where('producttype_id', '=', $producttype->id)->paginate(1);
return View::make('products.view_by_producttype')->with(compact('items', 'producttype'));
}
))->where('producttype_slug', '[A-Za-z\-]+');
Route::get('browse/{producttype_slug}/{genre_slug}', array(
'as' => 'products.view_by_producttype_genre',
function($producttype_slug, $genre_slug)
{
$producttype = ProductTypes::where('slug', '=', $producttype_slug)->firstOrFail();
$genre = GenreTypes::where('slug', '=', $genre_slug)->firstOrFail();
$items = DB::table('products')->join('product_genretypes', function($join) {
$join->on('product_genretypes.product_id', '=', 'products.id');
})->join('productvariations', function($join) {
$join->on('productvariations.product_id', '=', 'products.id');
})
->where('genretype_id', '=', $genre->id)
->where('producttype_id', '=', $producttype->id)
->paginate(1);
return View::make('products.view_by_type_genre')->with(compact('items', 'producttype', 'genre'));
}
))->where('producttype_slug', '[A-Za-z\-]+')->where('genre_slug', '[A-Za-z\-]+');
Just swap the order - have the Genre route defined first - like this:
Route::get('browse/{producttype_slug}/{genre_slug}', array(
'as' => 'products.view_by_producttype_genre',
function($productype_slug, $genre_slug)
{
}
))->where('producttype_slug', '[A-Za-z\-]+')->where('genre_slug', '[A-Za-z\-]+');
Route::get('browse/{product_slug}', array(
'as' => 'products.view_by_producttype',
function($product_slug)
{
}
))->where('product_slug', '[A-Za-z\-]+');
That way - if a route matches with a Genre route - it will be used first.
Otherwise it will default back to the normal Product route.