Laravel get one to many with limit by DB query builder - php

I have a products table that is connected through model_has_attachments with attachments table. I need to connect first attachment to each product record thought the query builder, but for some reason it just give me few records with model_has_attachments ids and rest is the null
my query builder look as:
$products = DB::table('products')->
leftJoin(DB::raw('(select `model_id`, `attachment_id` from model_has_attachments where model_has_attachments.model_id = id) as model_has_attachments'), 'model_has_attachments.model_id', 'products.id')->
leftJoin('attachments', 'model_has_attachments.attachment_id', '=', 'attachments.id')->
select('products.id', 'products.square', 'products.height', 'products.address', 'products.rooms', 'products.title', 'products.description', 'model_has_attachments.model_id as id_model', 'model_has_attachments.attachment_id')->
where([
['products.deleted_at', '=', null],
]);
I've tried to add limit = 1 in the DB::raw but it just give me the first record of the products table, not a joined table. Can you tell me why?
I also tried different approach, but it takes all the record of attachments which result duplicate products records if product has more than one attachment. I also have tried to add ->limit(1) at the end but it just ignores the method.
leftJoin('model_has_attachments', function ($join) {
$join->on('products.id', '=', 'model_has_attachments.model_id')->where('model_has_attachments.model_type', '=', Product::class);
})->
``

//try this
$products = Product::leftJoin('model_has_attachments', 'products.id', '=', 'model_has_attachments.model_id')
->leftJoin('attachments', 'attachments.id', '=', 'model_has_attachments.attachment_id')
->addSelect('products.*', 'attachments.id as attachment_id')
->where('attachments.is_active',1)
->get();

Related

Laravel WithSum / WithCount Relationships not bringing results

I am trying to make a query using Laravel eloquent but at the moment I have not had good results.
My query is about the scope of relationships in Laravel. We have two tables:
table 1 : orders
table 2 : products in orders (depends on table 1)
We have a relationship in the model.
public function products()
{
return $this->hasMany(OrderProduct::class);
}
OrderProduct (detail of products in orders) has the following fields:
id
order_id
product_id
qty
line_total
What we are trying to achieve is a query that returns the sum of line_total when the product_id is 139.
We tried the following options without success in the controller:
$orderspaid = Order::with('products')
->where('customer_id', '=', Auth::id())
->where('status', '=', 'completed')
->withSum ('products','line_total')
->where('product_id', '=', '139')
->get();
Error: Column not found: 1054 Unknown column 'product_id'
$orderspaid = Order::withCount(['products as orderproducts' => function($query) {
$query->where('orderproducts.product_id', '=', 139)
->select(DB::raw('sum(line_total)'));
}])->get();
But with no success.
My main question is, it is possible to use sum(line_total) or withSum('products','line_total') to directly sum the amount of money that a particular product_id have?.
Additional Info: Tinker information displaying the relationship between orders and orderproducts.
You can try this one. I don't have those tables ready to test so I could be wrong
So basicly, the method being tried is that products with wanted id will be preloaded, in this case, it's 139. When withSum is called on products table, it will use eagerly products that have been specified beforehand.
$product_id = 139;
$orderspaid = Order::with(['products' => function ($query) use ($product_id) {
$query->where(`products.id`, $product_id);
}])
->where('customer_id', '=', Auth::id())
->where('status', '=', 'completed')
->withSum('products', 'line_total')
->get();
dd($orderspaid);
Tell me if that works for you.

Laravel query builder duplicates row

I'm printing some data in mi index.blade.php file but it returns duplicated values. This is my query:
$hist = DB::table('codigo_sisnova')
->join('llamada', 'codigo_sisnova.idPaciente', '=', 'llamada.id_paciente')
->join('medico', 'llamada.id_medico', '=', 'medico.id_medico')
->where('llamada.status_llamada', 'Finalizada')
->where(function($query){
$query->where('llamada.status_pago', '=', 'Sisnova')
->orWhere('llamada.status_pago', '=', 'RedireccionadaSisnova');
})
->distinct()
->get();
I already tried with unique() but it doesn't work too.
EDIT
The relations between tables are one to may from "codigo_sisnova" to "llamada", if I take out the join with the table "medico" the rows keep duplicating
Every row gets a duplicate
You will have multiple codigo_sisnova rows if you are joining tables that have multiple matches on that table. DISTINCT would not eliminate those since the joined data will make it non-distinct in those results. I would recommend trying to use groupBy() to eliminate the redundant rows.
You are missing the group_by statement. Assuming that you have an ID column in codigo_sisnova, besides adding it in a SELECT clause, you need to add it before your get() method :
$hist = DB::table('codigo_sisnova')
->select('codigo_sisnova.id')
->join('llamada', 'codigo_sisnova.idPaciente', '=', 'llamada.id_paciente')
->join('medico', 'llamada.id_medico', '=', 'medico.id_medico')
->where('llamada.status_llamada', 'Finalizada')
->where(function($query){
$query->where('llamada.status_pago', '=', 'Sisnova')
->orWhere('llamada.status_pago', '=', 'RedireccionadaSisnova');
})
->group_by('codigo_sisnova.id')
->get();

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.

Laravel Query Builder - sum() method issue

I'm new to laravel and I have some issues with the query builder.
The query I would like to build is this one:
SELECT SUM(transactions.amount)
FROM transactions
JOIN categories
ON transactions.category_id == categories.id
WHERE categories.kind == "1"
I tried building this but it isn't working and I can't figure out where I am wrong.
$purchases = DB::table('transactions')->sum('transactions.amount')
->join('categories', 'transactions.category_id', '=', 'categories.id')
->where('categories.kind', '=', 1)
->select('transactions.amount')
->get();
I would like to get all the transactions that have the attribute "kind" equal to 1 and save it in a variable.
Here's the db structure:
transactions(id, name, amount, category_id)
categories(id, name, kind)
You don't need to use select() or get() when using the aggregate method as sum:
$purchases = DB::table('transactions')
->join('categories', 'transactions.category_id', '=', 'categories.id')
->where('categories.kind', '=', 1)
->sum('transactions.amount');
Read more: http://laravel.com/docs/5.0/queries#aggregates
If one needs to select SUM of a column along with a normal selection of other columns, you can sum select that column using DB::raw method:
DB::table('table_name')
->select('column_str_1', 'column_str_2', DB::raw('SUM(column_int_1) AS sum_of_1'))
->get();
You can get some of any column in Laravel query builder/Eloquent as below.
$data=Model::where('user_id','=',$id)->sum('movement');
return $data;
You may add any condition to your record.
Thanks
MyModel::where('user_id', $_some_id)->sum('amount')

How to determine columns that will be returned in the result when using `paginate()` method in Laravel?

I have 2 tables: users and articles. To fetch all columns from the articles table and only user_name column from the users table, I use this code:
$articles = Article::join('users', 'articles.user_id', '=', 'users.user_id')
->get(array('articles.*', 'users.user_name'));
and it works fine, but when I use paginate() method like this:
$articles = Article::join('users', 'articles.user_id', '=', 'users.user_id')
->paginate(10);
it fetches all columns from both tables, which I don't want. My question is: How can I select columns that will be returned in the result if I use paginate() method in Laravel framework?
The select function does this.
$articles = Article::join('users', 'articles.user_id', '=', users.user_id')
->select('articles.*', 'users.user_name')
->paginate(10);

Categories