Struggle with how to get something from my database with Laravel - laravel

😄 Hi!
Sorry the title isn't that explicite, but I'm a beginner and I really don't have the vocabulary just yet 😶
I've been struggling for hours with something, so before I trow my computer by the window, I came to ask for help :3
In my database I have a table with exhibitors and an other one with labels for those exhibitors. It's a many to many relationship and on my Controller I get the exhibitors with they labels that way :
$exposants = Expo::where('this_year', 1)->with('labels')->get();
It's working great! But now I want more!
I need to get the Exhibitors with a specific label. Let's say I want the exhibitors who would come this year with they labels {that part I already have} but only those who have the column "name" on the "label" table equal to "food". How do I do that ? 😅
Please help my 🙏

You can try
$exposants = Expo::where('this_year', 1)
->whereHas('labels', fn($q) => $q->where('name', $request->input('labelName'))
->with('labels')
->get();
//OR using non-arrow closure for PHP 7.3 and lower
$exposants = Expo::where('this_year', 1)
->whereHas('labels', function($q) use($request){
$q->where('name', $request->input('labelName'));
})
->with('labels')
->get();
//replace labelName with whatever key you have on request
Laravel docs: https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence

Related

Could someone help me build the elequent query laravel

I am on laravel, I am developing a library. I would like to display a list of books with a publication date of less than 3 months. Could someone help me build the elequent query. I tried with the DB class but it doesn't work.
$today = date('Y-m-d');
$books = DB::select("SELECT * from books where(DATEDIFF($today, 'publication_date') <=90)");
You can benefit from laravel query builder and pass now()->subDays(90) as the point that the date must be greater than.
DB::table('books')
->whereDate('publication_date', '>', now()->subDays(90))
->get();
The carbon package that comes with Laravel is quite handy for these types of thing.
What you could do is the following:
$books = Book::where('published_date', '<=', now()->addMonths(3))->get();

How return all rows for groupBy

I use the query to get the models that the user has, but only 1 model is returned for each user. How to get all? If I set $count=3 I should receive 3 or more models in group, but only first row is returned
$items->where(/*.....*/)
->groupBy('user_id')
->havingRaw("COUNT(*) >= {$count}")->get()
UPDATE
I solved it. I created a separate function for preparing the query and used it 2 times.
I think this may be an incorrect solution, but it works
$items = Items::query();
$this->prepareQuery($request, $items)
$items->whereHas('user', function ($q) use ($count, $request){
$q->whereHas('items', function ($query) use ($request){
$this->prepareQuery($request, $query);
}, '>=', $count);
})
->paginate(4);
This may work.Sometimes take can help.
$items->where(/*.....*/)
->groupBy('user_id')
->take({{$count}});
If you have relationships set up you can quite simply call:
$model->models()
$model being the model you're wanting the list for.
models() being the name of the relationship between the two items.
For example, a post may have many comments. You can call $post->comments() to get a list of the posts comments.
You may also query this from the database directly with some eloquent magic.
Post::with('comments')->where(/*....*/)->get();
EDIT:
You can check to see if a model has X number of related models like so.
Post::has('comments', '>=', 3)->where(/*...*/)->get();

Laravel Eloquent - Get a specific row and others

In my users table i want to get admin user and the others who are activated.
in fact the result that I want is concatenation of this two query result :
User::where('user_name','admin')->first();
User::where('is_active',1)->get();
is there any way to get this result in one query?
$query = User::where('is_active',1)->where('user_name','admin')->first();
Above Query will give you only one Active User whos user_name is admin and active.
As per my understanding from your question you want all users who are "active" and whos user_name is "admin" then try this below query.
$query = User::where('is_active',1)->orWhere('user_name','admin')->get();
Hope this may solve your problem.
You need to use a Union to put the two result sets together.
$first = User::where('user_name','admin')->first();
$users = User::where('is_active',1)->union($first)->get();
That should get you the first Admin user AND all the active users.
In fact, as they are on the same table, a OR should also work like below:
$users = User::where('is_active',1)
->orWhere('user_name', 'admin')
->get();
I'll leave both parts in as both will work.
Try this,
User::where('is_active',1)
->orWhere('user_name', 'admin')
->get();
You should try this:
$rsltUser = User::where('is_active',1)
->orWhere('user_name', 'admin')
->get();
Sorry for the late reply everybody missed the laravel out of box method which accepts array
Eloquent Version
User::where(['user_name' => 'admin','is_active' => '1'])->first();
Another Method
DB Facade Version
DB::table('users')->where(['user_name' => 'admin','is_active' => '1'])->first();
Hope its helps

Laravel Order by in one to many relation with second table column

Hi i have tables with one to many relation
sectors
id
name
position
seat_plans
id
name
sector_id
I just want to select all seat plans order by sectors.position. I tried
$seat_plans = SeatPlan::with(['sector' => function($q){
$q->orderBy('position');
}
])->get();
but it is not working. when i check The SQL it is generating query like
select * from seat_plans
can anybody please tell me how to do this?
I don't think you need a custom function for your use case. Instead try this:
$users = DB::table('seat_plans')
->join('sectors', 'seat_plans.sector_id, '=', 'sectors.id')
->select('seat_plans.*')
->orderBy('sectors.position')
->get();

Working with Eloquent, How to select popular comments

I am designer trying to learn coding here and Laravel is so great in that it enables design like me to be able to create something myself smile
On to my question, I followed some of tutorial and now I learn to build simple blog system.
So I have Post model that has relationship $this->morphMany('Like','likeable','likeable_type'); with Like model.
Everything works great so far. Now I want to be able to create 'Popular Posts' page that basically shows the posts ordered by popularity, which is number of likes in my case.
The 'likes' table has these field id | likable_id | likeable_type
'likeable_type', in this case, is 'Post'
'likeable_id' is the post id linked to id in 'posts' table
So in my controller, I tried this.
$popular_ids = DB::table('likes')
->select('likeable_id')
->groupBy('likeable_id')
->orderBy(DB::raw('COUNT(likeable_id)'), 'DESC')
->get();
$popular_posts = Post::whereIn('id',array_pluck($popular_ids,'likeable_id'))->paginate(15);
This gives me all the popular posts but not in the order that I want.
I'm not sure if there is better way to achieve this or it seems that I only miss another 'orderBy' method?
Any suggestion on this?
ps. Sorry for my poor English
SQL IN does not maintain order. To achieve this have to user ORDER BY FIELD('id', , ,...) to achieve this.
$ids = array_pluck($popular_ids,'likeable_id');
$raw = DB::raw('FIELD(id,' + implode(',', $ids) + ')');
$popular_posts = Post::whereIn('id', $ids)->orderBy($raw)->paginate(15);
For more information refer to,
Maintaining order in MySQL "IN" query
I would do this with a join. It's kinda complex but if you want to understand the internals you should read into LEFT JOIN and INNER JOIN. This example is particularly ugly because of the polymorphic relationship.
Post::select('posts.*', DB::raw('COUNT(DISTINCT likes.id) AS popularity'))
->leftJoin('likes', function ($join)
{
$join->on('likes.likeable_id', '=', 'posts.id')
->on('likes.likeable_type', '=', DB::raw("'Post'"));
})
->orderBy('popularity', 'DESC')
->paginate(15);
There is a bonus in that the popularity value is now available on the posts.
$post->popularity;
Thank you Collin for your time! Your answer leads me to the light!!! I modified your answer a bit and finally get what I need. I'm still trying to fully understand it though. This is what I ended up with.
Post::select('posts.*', DB::raw('COUNT(likes.likeable_id) AS popularity'))
->join('likes', function($join)
{
$join->on('likes.likeable_id', '=', 'posts.id')
->on('likes.likeable_type', '=', DB::raw("'Post'"));
})
->groupBy('likes.likeable_id')
->orderBy('popularity', 'DESC')
->paginate(15);
Ps. Even though this code gives me what I want, I'm not sure if I did my db design right.

Resources