List all users and their recipes - php

I'm writing a custom database query in Laravel for my cocktail app. The goal is to retrieve the following structure:
User 1
Recipe 1
Recipe 4
User 2
Recipe 2
Recipe 3
etc...
My code (see below) currently returns 3 objects, all containing a single recipe but all from 2 users. Is it even possible to build the desired structure (see above), retrieving a user and having his/her recipes stored in a array/object called recipes?
$recipes = DB::table('users')
->join('recipes', 'users.id', '=', 'recipes.user_id')
->select(
'recipes.id as recipe_id',
'recipes.name as recipe_name',
'recipes.short as short',
'users.name as user_name'
)
->get();

While in Laravel, use Eloquent.
In your User model add relationship to recipes:
public function recipes()
{
return $this->hasMany('App\Recipe');
}
To call it:
$recepies = App\User::find(1)->recipes;
https://laravel.com/docs/5.6/eloquent-relationships

You cannot get this format using query.
First fetch users then fetch recipes.
Then format them using loop.
OR
Use eloquent :)
$recepies = App\User::with('recipes')->get();

I think this would work
$recipes = DB::table('users')
->select(
'recipes.id as recipe_id',
'recipes.name as recipe_name',
'recipes.short as short',
'users.name as user_name'
)
->where('recipes.user_id', '=', 'users.id')
->get();

Related

Add join filter in Laravel Eloquent

I am a novice in Laravel.
I want to add a filter join through Laravel Eloquent model.
I have below relationship
user belongs to city
user has one restaurant
restaurant has many jobs
Now I want to fetch all jobs with a filter of city.
I tried couple of ways, but ended up in error, like:
$jobs = Job::where("date_time", ">=", $currentDate)->where("city.id", 50)->whereIn('job_status', ['upcoming', 'active'])->orderBy('start_date_time', 'desc')->get();
and the below one
$jobs = Job::with(['restaurant'])->where("date_time", ">=", $currentDate)->where("city.id", 50)->whereIn('job_status', ['upcoming', 'active'])->orderBy('start_date_time', 'desc')->get();
So, here how can I add join from job -> restaurant -> user -> city?
Thanks
Assuming you have city_id in your table
$jobs = DB::table('jobs')->with('restaurant')
->join('users', 'users.id', '=', 'restaurant.user_id')
->join('cities', 'users.id', '=', 'cities.user_id')
->where("table_name.date_time", ">=", $currentDate)
->where("cities.id", 50)
->whereIn('job_status', ['upcoming', 'active'])
->orderBy('table_name.start_date_time', 'desc')->get();
I have edited my answer hope it helps. If not please post your errors and table structure.
You can read about joins here: https://laravel.com/docs/6.x/queries#joins

Laravel append data count to database object

Hello i have this function
public function readData(){
$TableB1 = \DB::table('users')
->join('group_user', 'users.id', '=', 'group_user.user_id')
->join('groups', 'groups.id', '=', 'group_user.group_id')
->join('meetings', 'users.id', '=', 'meetings.owned_by_id')
->select(
'users.name as name',
'group_user.user_id as id',
'groups.name as groupname',
)
->get();
foreach ($TableB1 as &$data){
$meetings = \DB::table('meetings')
->where('company_id', 1)->where('owned_by_id', $data->id)
->where(\DB::raw('MONTH(created_at)'), Carbon::today()->month);
echo $meetings->count();
}
return $TableB1;
}
i retrieve some data from database and return them and use AJAX Call to use them later
The problem is i have a table called users and table called meetings
i want to know how many meetings every user done everyday
so to do this i made a for each to take the user_id and use it to get the count
of meetings done by each user
for example in meetings table i have a owned_by_id field which have the user_id
so what the code does if it found for example if owned_by_id(6) repeated in
meetings table 4 times it will return 4
but this is what i get in the browser
instead what i want to get is something like this
im using Laravel 5.7 and sorry i know my question is unclear this is the 1st time i have ever asked question on stackoverflow
Image
If you want count of meetings then you may use laravel eloquent method with is: withCount();
Like this:
$users = User::with('meetings')->withCount('meetings')->get();
If you will do this then you will get meetings_count with your user object.
And if you have still any doubt you may refer following link:
https://laravel.com/docs/5.8/eloquent-relationships
Thnak you!
You could add a new column in the select() using the COUNT SQL statement:
->select(
'users.name as name',
'group_user.user_id as id',
'groups.name as groupname',
\DB::raw('(
SELECT COUNT(meetings.id) FROM meetings GROUP BY meetings.owned_by_id
) as meetings')
)

Laravel mysql Inner join and also select a specific field from another table

I have the following query:
Ratings::join('users', 'movieratings.rated_by', '=', 'users.usr_id')
->where('rated_on', $movieId)
->orderBy('rated_at', 'desc')
->select('comment', 'rating', 'rated_as', 'rated_at', 'username')
->paginate(20);
This will get all the feedback ratings for a specific movie.
But I have another table which contains the total good and bad ratings for a specific movie movie, the only problem is that I cant get it to work to query that table as well at the same time.
If I do another query I would simply write: Movie::where('movie_id', $movieId)->select('total_good_ratings', 'total_bad_ratings')->get(); this would output eg "22, 15" but is it possible to only fetch two columns from a specific row then do a inner join between two tables and paginate the result?
thanks
You can do a leftJoin with the table that contains the good and bad ratings, where the join condition will be the id of the movie.
Ratings::join('users', 'movieratings.rated_by', '=', 'users.usr_id')
->leftJoin('movie', 'movie.id', '=', 'movieratings.rated_on')
->where('rated_on', $movieId)
->orderBy('rated_at', 'desc')
->select('comment', 'rating', 'rated_as', 'rated_at', 'username', 'total_good_ratings', 'total_bad_ratings')
->paginate(20);
I think you can try this:
Ratings::leftJoin('users', 'users.usr_id', '=', 'movieratings.rated_by')
->leftJoin('movie', 'movie.id', '=', 'movieratings.rated_on')
->where('movieratings.rated_on', $movieId)
->orderBy('movie.rated_at', 'desc')
->select('movieratings.comment', 'movieratings.rating', 'movieratings.rated_as', 'movie.rated_at', 'users.username', 'movieratings.total_good_ratings', 'movieratings.total_bad_ratings')
->paginate(20);
Hope this help for you !!!
In case this may be of help:
Assuming:
class Rating extends Model {
public users() {
$this->belongsTo(User::class, 'usr_id');
}
public movie() {
$this->belongsTo(Movie::class, 'rated_on'); //Name looks odd, it should be movie_id if you are following standard conventions
}
}
Then you can lazy/eaher load them:
$ratings = Ratings::with([ "movie" => function ($query) {
$q->select('total_good_ratings', 'total_bad_ratings');
}])->where('rated_on', $movieId)
->orderBy('rated_at', 'desc')
->select('comment', 'rating', 'rated_as', 'rated_at', 'username',"rated_on")
->paginate(20);
You can get the movie info via $ratings[X]->movie->total_good_ratings (in a loop that would be $rating->movie->total_good_ratings
A bit of critique though:
total_good_ratings looks like it's a derived attribute so it should not have been stored in the first place. It's appears to be a count of the good ratings.
You should use the standard conventions when naming columns and tables e.g. a foreign key is usually called <foreign table name in singular>_<foreign field name> example user_id or movie_id .

Laravel 5.1: handle joins with same column names

I'm trying to fetch following things from the database:
user name
user avatar_name
user avatar_filetype
complete conversation_messages
with the following query:
static public function getConversation($id)
{
$conversation = DB::table('conversation_messages')
->where('belongsTo', $id)
->join('users', 'conversation_messages.sender', '=', 'users.id')
->join('user_avatars', 'conversation_messages.sender', '=', 'user_avatars.id')
->select('users.name', 'conversation_messages.*', 'user_avatars.name', 'user_avatars.filetype')
->get();
return $conversation;
}
It works fine so far, but the avatar's column name is 'name' like the column name from the 'users' table.
So if I'm using this query the to get the output via $conversation->name, the avatar.name overwrites the users.name
Is there a way to rename the query output like the mysql "as" feature at laravel 5.1?
For example:
$conversation->avatarName
$conversation->userName
Meh okay.. i've found a simple solution here
->select('users.name as userName', 'conversation_messages.*', 'user_avatars.name as avatarName', 'user_avatars.filetype')
As you can mention I've added the requested "as-Feature" next to the table.columnName
Take a look at this example of trying to join three tables staffs, customers and bookings(pivot table).
$bookings = \DB::table('bookings')
->join('staffs', 'staffs.id' , '=', 'bookings.staff_id')
->join('customers', 'customers.id' , '=', 'bookings.customer_id')
->select('bookings.id', 'bookings.start_time', 'bookings.end_time', 'bookings.service', 'staffs.name as Staff-Name', 'customers.name as Customer-Name')
->orderBy('customers.name', 'desc')
->get();
return view('booking.index')
->with('bookings', $bookings);
I had the following problem, simplified example:
$result = Donation::join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
$result is a collection of Donation models. BUT CAREFUL:
both tables, have a 'created_at' column. Now which created_at is displayed when doing $result->created_at ? i don't know. It seems that eloquent is doing an implicit select * when doing a join, returning models Donation but with additional attributes. created_at seems random. So what I really wanted, is a return of all Donation models of the user with email hello#papabello.com
solution is this:
$result = Donation::select('donation.*')->join('user', 'user.id', '=', 'donation.user_id')->where('user.email', 'hello#papabello.com')->first();
Yeah, simply rename the column on either table and it should work.
Also what you can do is, rename the user.name column to anything, also rename sender column of conversation_messages to id and perform a natural join.

How to get a collection of models using where and relationships?

I have an Order table with some relationships (Status, User) using their IDs to create it (status_id, user_id)
I need to get a collection of Order models using and Eloquent ORM but I need to filter by their status name (which is in Status table only) and user name (which is in User table only)
When I use 'join' in my query builder. The relationships aren't hydrating, like in this case:
$emprestimo = DB::table('emprestimos')
->join('status', 'status_id', '=', 'status.id')
->where('status.nome', 'Solicitado')
->where('emprestimos.dono_id', Auth::user()->id)
->get();
How can I filter using joins and also hydrate my collection of models?
you can try something like this
see if that works
$emprestimo = DB::table('emprestimos')
->join('status', function ($join) {
$join->on('emprestimos.status_id', '=', 'status.id')
->where('status.nome', 'Solicitado')
})
->where('emprestimos.dono_id', Auth::user()->id)
->get();

Categories