Here is my method available in the controller
public function getProductListAll(){
$products = Product::with('property')
->whereStatus(1)
->where('show', 1)
->where('code', '!=', 1)
->where('is_roketable',true)
->with(['prices_roket' => function ($q) {
return $q->whereNull('user_id');
}]);
$products = $products->whereIn('product_type', ['education', 'consultancy', 'startup']);
$data['products'] = $products->select([
'id', 'name', 'image', 'commission', 'price',
'buy_now', 'type', 'short_desc', 'pricing_desc',
'offer_status', 'period_status', 'period', 'period_frequency',
'endpoint', 'product_type', 'unique_id', 'discount_show_status',
'annual_payment', 'pre_register', 'privacy_status', 'privacy',
'sg_project', 'last_pre_register_date', 'product_desc',
'product_consulting', 'product_status',
])->get();
return response()->json($data);
}
and here is the relationship in my model.
return $this->hasMany(ProductPrice::class)->select('price','created_at','user_id','offer_id')
->orderBy('price')
->where(function ($q) {
$q
->where(function ($q2) {
$q2->whereNull('offer_id');
})
->orWhere(function ($q2) {
$q2->whereNotNull('offer_id');
$q2->where('user_id', auth()->user() ? auth()->user()->id : 0);
});
});
I tried to change my relationship and rewrite it, but when I write select, I cannot access any data. When I remove select, they all come. I can't select at prices relationship.
You can not use ->select() inside your model relationship.
Instead what you can do to limit the selection is by adding it into ->with()
For example
$products = Product::query()
->with(['property' => function ($q) {
$q->select(['price','property.created_at','user_id','offer_id']);
}])
->where( ... )
// no need to add property 'price' inside this select
->select(['id', 'name', 'image', 'commission' ... ])
->get();
Related
coming from this relationship from the docs:
https://laravel.com/docs/9.x/eloquent-relationships#advanced-has-one-of-many-relationships
/**
* Get the current pricing for the product.
*/
public function currentPricing()
{
return $this->hasOne(Price::class)->ofMany([
'published_at' => 'max',
'id' => 'max',
], function ($query) {
$query->where('published_at', '<', now());
});
}
how can I make such an relation with a specific date?
The relation down below will work
/**
* Get pricing for the product of one specific date.
*/
public function priceOfDay(Carbon $date)
{
return $this->hasOne(Price::class)->ofMany([
'published_at' => 'max',
'id' => 'max',
], function ($query) {
$query->where('published_at', '<', $date());
});
}
but how can I use it with Eloquent? How can I pass the date to this:
Product::with('priceOfDay')->get();
update
I now use the one to many relation with a closure
->with(['prices' => function ($query) use ($month) {
$query->where('published_at', '<', $month)
->orderByDesc('published_at')
->orderByDesc('id')
->first();
}])
it works with the little drawback of having a collection instead of an object as relation, but it fills my needs for the moment.
It would be nice if there was something like
->with(['relation', $param])
update 2
since there seems to bo no direct solution here the workarround i came up with:
->first() does not work in the query, you will end up getting all prices, so I finished with an each()
->with(['prices' => function ($query) use ($month) {
$query->where('published_at', '<', $month)
->orderByDesc('published_at')
->orderByDesc('id');
}])
->get()
->each(function ($product) {
$product->price = $product->prices->first()->price;
})
**
How can I make this code easy . i use this query() function for many section
i want to get event by filter. my filter based on tags and category(both are in pivot table)
**
public function index(Request $request)
{
$customQuery = Event::where('status', '1');
if ($request->vehical_type) { //vehical filter
$customQuery->where('vehical_type', '=', $request->vehical_type);
}
if ($request->tag) { //tag filter
$id = $request->tag;
$customQuery->whereHas('tags', function (Builder $query) use ($id) {
$query->where('tag_id', $id);
});
}
if ($request->category) { //category filter
$id = $request->category;
$customQuery->whereHas('categories', function (Builder $query) use ($id) {
$query->where('category_id', $id);
});
}
$events = $customQuery->get(); //get event according to filters
$tags = Tag::whereHas('events', function (Builder $query) { //get all tags of events
$query->where('event_id', '>', 0);
})->get();
$categories = Category::whereHas('events', function (Builder $query) { //get all categories of events
$query->where('event_id', '>', 0);
})->get();
return view('frontend.event.index', compact('events', 'tags', 'categories'));
}
You could use when for conditionals in the query and short hand closures with fn to put them in a single line.
whereRelation instead of whereHas could make those queries a bit shorter too.
public function index(Request $request)
{
$events = Event::query()
->where('status', '1')
->when(
$request->vehical_type,
fn($query) => $query->where('vehical_type', $request->vehical_type)
)
->when(
$request->tag,
fn($query) => $query->whereRelation('tags', 'tag_id', $request->tag)
// or fn($query) => $query->whereHas('tags', fn($tags) => $tags->where('tag_id', $request->tag))
)
->when(
$request->category,
fn($query) => $query->whereRelation('categories', 'category_id', $request->category)
// or fn($query) => $query->whereHas('categories', fn($category) => $category->where('category_id', $request->category))
)
->get();
$tags = Tag::query()
->whereRelation('events', 'event_id', '>', 0)
// or ->whereHas('events', fn($events) => $events->where('event_id', '>', 0))
->get();
$categories = Category::query()
->whereRelation('events', 'event_id', '>', 0)
// or ->whereHas('events', fn($events) => $events->where('event_id', '>', 0))
->get();
return view('frontend.event.index', compact('events', 'tags', 'categories'));
}
You could also maybe use a query scope to put the search in the Event model.
# Event.php
public function scopeSearch(Builder $query, array $filter = [])
{
return $query
->when(
array_key_exists('vehicle_type', $filter),
fn($query) => $query->where('vehical_type', $filter['vehicle_type'])
)
->when(
array_key_exists('tag', $filter),
fn($query) => $query->whereRelation('tags', 'tag_id', $filter['tag'])
// or fn($query) => $query->whereHas('tags', fn($tags) => $tags->where('tag_id', $filter['tag']))
)
->when(
array_key_exists('category', $filter),
fn($query) => $query->whereRelation('categories', 'category_id', $filter['category'])
// or fn($query) => $query->whereHas('categories', fn($category) => $category->where('category_id', $filter['category']))
);
}
public function index(Request $request)
{
$filter = [
'vehicle_type' => $request->vehicle_type,
'tag' => $request->tag,
'category' => $request->category,
];
$events = Event::query()
->where('status', '1')
->search($filter)
->get();
$tags = Tag::query()
->whereHas('events', fn($events) => $events->where('event_id', '>', 0))
->get();
$categories = Category::query()
->whereHas('events', fn($events) => $events->where('event_id', '>', 0))
->get();
return view('frontend.event.index', compact('events', 'tags', 'categories'));
}
You can use whereRelation for getting instead of using whereHas.
$customQuery->whereRelation('tags', 'tag_id', $id)
Using this structure you can shortan your code and optimize.
there is other relationship query method introduced in newer version check here
// Get event according to filters
$events = Event::where('status', '1')
->when($request->get('vehicle_type'), function ($query, $vehicleType) {
$query->where('vehical_type', '=', $vehicleType);
})
->when($request->get('tag'), function ($query, $tagId) {
$query->whereHas('tags', function ($query) use ($tagId) {
$query->where('tag_id', $tagId);
});
})
->when($request->get('category'), function ($query, $categoryId) {
$query->whereHas('categories', function ($query) use ($categoryId) {
$query->where('category_id', $categoryId);
});
})
->get();
You can use the when method for these types of conditions. You can view the documentation here.
How to filter by relation column
tried this
->whereHas('customer',function ($query) use ($order){
$query->orderBy('first_name', $order);
})
and this
->with(['customer' => function ($query) use ($order) {
$query->orderBy('first_name', $order);
}])
Both did not work
with() are using eager loading, which turns this into two queries.
You need to use join() instead of with()
$orders = Order
::join('customers', 'order.customer_id', '=', 'customers.id')
->orderBy('customers.first_name')
->get();
OR
You may use sortBy() or sortByDesc() methods of Collection.
For example:
$orders = Order
::with('customer')
->get()
->sortBy('customer.first_name');
request {{host}}/admin/showcases?filterBy=companies:name it order by relation column companies
if simple {{host}}/admin/showcases?filterBy=name
it will be only orderBy("name")
->when(str_contains($filterBy, ':'),
function (Builder $query) use ($filterBy, $order, $columns) {
$table = explode(':', $filterBy)[0];
$key = Str::singular($table) . "_id";
$column = explode(':', $filterBy)[1];
$selfTable = $this->getTable();
$query->leftJoin($table, "$selfTable.$key", "$table.id")
->when($columns !== ['*'],
function ($query) use ($columns, $selfTable) {
$columns = array_map(function ($column) use ($selfTable) {
return "$selfTable.$column";
}, $columns);
$query->select($columns);
},
fn($query) => $query->select(["$selfTable.*"]))
->orderBy("$table.$column", $order);
},
function ($query) use ($filterBy, $order) {
$query->orderBy($filterBy, $order);
})
I have this query:
$orders = Order::with(['company', 'products', 'user', 'status', 'seller'])->orderBy('id', 'DESC')->select('orders.*');
And it returns the relevant results as expected in a yajra datatable instance.
Now I would like to narrow down this result even more. I use it this way:
$orders = $orders->whereHas('user', function ($q) use ($request){
$q->searchFullName($request->seller);
});
I have created a scope in the model and it works for another function on my website. However it returns no results when calling it like that.
Even if I call the whereHas using a where statement, still the result is empty:
$orders = $orders->whereHas('user', function ($q) use ($request){
$q->where('first_name', 'like', '%'.$request->seller.'%');
});
The seller parameter is not empty. Even if I use a hardcoded string, the results are always empty.
The searchFullName method:
public function scopesearchFullName($query, $value){
return $query->where('first_name', 'LIKE', "%$value%")
->orWhere('middle_name', 'LIKE', "%$value%")
->orWhere('last_name', 'LIKE', "%$value%");
}
Full controller:
public function listOrdersData(Request $request)
{
if(!$request->ajax())
return Redirect::route('/');
$loggedUser = Auth::user();
if($loggedUser->hasRole('Super Administratör'))
$orders = Order::with(['company', 'products', 'user', 'status', 'seller'])->orderBy('orders.id', 'DESC')->select('orders.*');
else
$orders = Order::with(['company', 'products', 'user', 'status', 'seller'])->where('company_id', $loggedUser->company_id)->orderBy('id', 'DESC')->select('orders.*');
if (!empty($request->seller) && $request->seller != 'all') {
$orders = $orders->whereHas('user', function ($q) use ($request){
$q->searchFullName($request->seller);
});
}
return DataTables::of($orders)
->addColumn('products', function($orders) {
$products = "";
foreach($orders->products as $product)
$products = $products . $product->name . "<br>";
return $products;
})
->editColumn('company', function($orders){ return $orders->company->name; })
->editColumn('price', '{{$price}} kr')
->editColumn('user', function($orders){
return $orders->user->full_name;
})
->addColumn('seller', function($orders){
return $orders->seller->full_name;
})
->addColumn('status', function($orders){
return '<span class="chip lighten-4 purple purple-text">'. $orders->status->localized . '</span>';
})
->addColumn('contract', '<i class="material-icons">file_download</i>')
->addColumn('edit', '<i class="material-icons">edit</i>')
->rawColumns(['products', 'status', 'edit', 'contract'])
->make(true);
}
The issue is with scope method
public function scopesearchFullName($query, $value){
return $query->where('first_name', 'LIKE', "%".$value."%")
->orWhere('middle_name', 'LIKE', "%".$value."%")
->orWhere('last_name', 'LIKE', "%".$value."%");
}
Also make sure that only those user record returns who has orders.
Also for searching sellers order
$orders = $orders->whereHas('seller', function ($q) use ($request){
$q->searchFullName($request->seller);
});
so in Order model
public function seller()
{
return $this->belongsTo(User::class, 'seller_id', 'id');
}
I have a table in laravel which tracks recent views of posts by users. Here is its controller
$contents = RecentView::where('user_id', $loggedUser)
->with('posts.user')
->with(['posts.note' => function($query) use($loggedUser){
$query->where('user_id', $loggedUser);
}])
->with(['posts.tags' => function($query) use($loggedUser){
$query->where('user_id', $loggedUser);
}])
->with(['posts.savedpost' => function($query) use($loggedUser){
$query->where('user_id', $loggedUser);
}])
->with(['following' => function($query) use($loggedUser){
$query->where('user_id', $loggedUser)
->where('follower_id', 'id');
}])
->paginate(12)->toArray();
I always gel blank values in 'following'. i want to join 'follow' table using 'user_id' field from 'posts' table.
my model is as follows:
public function posts()
{
return $this->hasOne('App\FeedPost', 'id', 'post_id');
}
public function following()
{
return $this->hasOne('App\Follow');
}
can someone tell me how i can do this?