Pagination eloquent - php

I want to paginate ordering by linkscount em ASC...
The table pages:
----------------------
id | name
----------------------
1 | Globo
----------------------
2 | Google
----------------------
3 | MC Donalds
----------------------
4 | Habibs
The query to FIRST PAGE RESULTS (order/query is OK):
$pages = Mypages::where('pages.author_id', auth()->user()->id)
->orderBy('linkscount', 'desc')
->leftJoin('links', 'links.page_id', '=', 'pages.id')
->selectRaw('pages.*, count(links.id) as linkscount')
->groupBy('pages.id')
->take(2)
->get();
The query TO PAGINATE (order/query is not ok):
$pages = Mypages::where('pages.author_id', auth()->user()->id)
->orderBy('linkscount', 'asc')
->leftJoin('links', 'links.page_id', '=', 'pages.id')
->selectRaw('pages.*, count(links.id) as linkscount')
->groupBy('pages.id')
->where('pages.id', '>', $id)
->take(2)
->get();
This query, don't return nothing, it was to return "MC Donalds"...
$id = LAST ID DISPLAYED.

Like Jacob H said in the comment, this isn't a real SQL, because the group by function need to have all the columns of the query that you have in the select except the functions like counts, sums, etc.
For this example you need to put the pages.name and pages.id in the group by
$pages = Mypages::where('pages.author_id', auth()->user()->id)
->orderBy('linkscount', 'asc')
->leftJoin('links', 'links.page_id', '=', 'pages.id')
->selectRaw('pages.id, pages.name, count(links.id) as linkscount')
->groupBy('pages.id', 'pages.name')
->where('pages.id', '>', $id)
->take(2)
->get();
And if you are sending the correct $id, everything seems ok.

Related

Laravel relation between 5 tables

please what is the correct way of getting data from the MN table where one product has assigned multiple combinations of Mark / Model / Year.
E.g. product with ID 1 has following in mmis table:
id | product_id | mark_id | model_id | year_id
178 1 1 1 2
177 1 2 1 3
176 1 3 1 1
other tables are: marks, models, years.
It's completely fine getting all requested data with just:
$items = ProductMmi::where('product_id', $id)
->with(['mark', 'model', 'year'])
->get();
The problem is, that in this way I am not able to sort result based on mark.name ASC, model.name ASC, year.name ASC.
Thank you for any advice.
update:
forgot to add my second try - ordering still in troubles...
$items = ProductMmi::select([
'product_mmis.*',
'marks.*',
'mark_models.*',
'mark_model_years.*'
])
->join('marks', 'product_mmis.mark_id', '=', 'marks.id')
->join('mark_models', 'product_mmis.model_id', '=', 'mark_models.id')
->join('mark_model_years', 'product_mmis.year_id', '=', 'mark_model_years.id')
->where('product_mmis.product_id', $id)
->orderBy('mark', 'asc')
->orderBy('model', 'asc')
->orderBy('year', 'asc')
->get();
you can use this way
$items = ProductMmi::where('product_id', $id)->with(['mark'=>function($query){
$query->orderBy('your_column_name','ASC');
}])->with(['model', 'year'])
->get();
or one thing if you dont want to edit your query then in the model you can do also like this
public function mark()
{
return $this->hasMany(Mark::class)->orderBy('mark','asc');
}
I think the solution was to add orderBy methods between specific joins. E.g. the following case is working completely properly:
$items = ProductMmi::select([
'product_mmis.*',
'marks.*',
'mark_models.*',
'mark_model_years.*'
])
->join('marks', 'product_mmis.mark_id', '=', 'marks.id')
->orderBy('mark', 'asc')
->join('mark_models', 'product_mmis.model_id', '=', 'mark_models.id')
->orderBy('model', 'asc')
->join('mark_model_years', 'product_mmis.year_id', '=', 'mark_model_years.id')
->where('product_mmis.product_id', $id)
->orderBy('year', 'desc')
->get();
Is there a better way to have it done in a more efficient way? Thanks.

Laravel query join 1 table in 2 tables at single query

I have a complex query and it works, now i need to join users table and get 2 different value of it based on 2 different tables here is where things messed up.
Code
I have commented issue part as well as data that should be returned
$datas = DB::table('projects')
->orderBy('projects.id', 'desc')
->join('customers', 'projects.customer_id', '=', 'customers.id')
->leftjoin('project_schedules', 'projects.id', '=', 'project_schedules.project_id')
->leftjoin('project_schedule_details', 'project_schedules.id', '=', 'project_schedule_details.schedule_id')
->leftjoin('project_schedule_visits', 'projects.id', '=', 'project_schedule_visits.project_id')
// issue tables (project_admins) and (project_shoppers)
->leftjoin('project_admins', 'projects.id', '=', 'project_admins.project_id')
->leftjoin('project_shoppers', 'projects.id', '=', 'project_shoppers.project_id')
->groupBy('projects.id')
->select(
'projects.name as project',
'customers.companyName as customer',
'project_schedule_details.date as schedule_date',
'project_schedule_details.description as schedule_description',
'project_schedule_details.actual_cost as schedule_actual_cost',
'project_schedule_visits.from_date as visit_from_date',
'project_schedule_visits.to_date as visit_to_date',
'project_schedule_visits.description as visit_description'
// 'project_admins.user.username as admin' //i.e. user 1
// 'project_shoppers.user.username as shopper' // i.e user 2
)
->get();
Explanation:
I need to join users table to project_admins table as well as project_shoppers table and return related users to those tables.
Then I would have user 1 returned based on project_admins table
And user 2 based on project_shoppers table.
Any idea how to achieve that goal?
Under the leftJoins you can add the extra joins for getting the users:
->leftJoin('users','users2.id','=','project_admins.user_id')
->leftJoin('users AS users2','users2.id','=','project_shoppers.user_id')
In your select you can get the details like this:
->select(
...,
'users.username AS admin',
'users2.username AS shopper'
)

get() + sum() in one line laravel

My data
invoice|amount|
0001 | 10000|
0001 | 10000|
Now my code on Controller;
$invoices = Invoice::where('user_id', 1)
->where('status', 'Paid')
->orderBy('datePaid', 'desc')
->groupBy('no_invoice')
->get()
->sum('amount'); return view('invoice', ['invoices' => $invoices]);
I want show all data with get() and sum only field amount like this on my foreach.
invoice|total amount|
0001 | 20000|
You can use selectRaw in your select in query and then use sum(amount) like this
$invoices = Invoice::selectRaw('*, sum(amount) as total')
->where('user_id', 1)
->where('status', 'Paid')
->orderBy('datePaid', 'desc')
->groupBy('no_invoice')
->get();
Now you can print
foreach($invoices as $invoice){
echo $invoice->total
}

Eloquent join table with two conditions

I have two tables:
A: id | user_id | phonenumber | status | ...
B: id | user_id | phonenumber | name | ...
I would like to list all elements in table A but I have to left join the elements to table B.
I can do it with DB:
DB::table('A')
->leftJoin('B', function ($join) {
$join->on('A.phonenumber', '=', 'B.phonenumber')
->on('A.user_id', '=', 'B.user_id');
})
->select(...)
->where('A.user_id', '=', $userId)
->get();
Is it possible to solve it with eloquent somehow?
You can use eloquent, one way is to change it to
A::leftJoin('B', function ($join) {
$join->on('A.phonenumber', '=', 'B.phonenumber')
->on('A.user_id', '=', 'B.user_id');
})
->select(...)
->where('A.user_id', '=', $userId)
->get();
And with using pure eloquent
You would have to do adjustment to your A model. We would define two model functions.
public function phoneNumber()
{
return $this->hasMany(B::class, "phonenumber", "phonenumber");
}
public function userId()
{
return $this->hasMany(B::class, "user_id", "user_id");
}
Now we will change our query to
A::with("phonenumber")->has("phonenumber")
->with("userId")->has("userId")
->where("user_id","=",$userId)
->get();
This should work for you.
** Updated ***
if you want all the record in A then simply do
A::with("phonenumber","userId")
->where("user_id","=",$userId)
->get();
modelname::where(condition)->leftjoin(tablename,fieldname,othertable.fieldname)->get()
This is format how we write join in laravel
$postdata = post::select('categories.id', 'posts.id', 'categories.categoryname', 'posts.title', 'posts.body', 'posts.image', 'posts.created_at', 'users.name')
->where('post_type', 'publish')
->where('status', 'active')
->where('categories.id', $id)
->leftJoin('users', 'users.id', '=', 'posts.user_id')
->leftJoin('categories', 'categories.id', '=', 'posts.category')
->orderBy('created_at', 'desc')
->paginate(5);
This query display blog with username and with category using join it's my proect convenient query you can also create for you in this manner

Laravel query builder SUM returns multiplied values

I have the following query and been fighting with from yesterday after solving previous issue with the help of great stack-overflowers yesterday's question.
$sales = DB::table('sales')
->leftJoin('store_configs', 'store_configs.id', '=', 'sales.store_config_id')
->leftJoin('category_sales', 'category_sales.sale_id', '=', 'sales.id')
->leftJoin('categories', 'categories.id', '=', 'category_sales.category_id')
->leftJoin('departments', 'departments.category_id', '=', 'categories.id')
->leftJoin('department_sales', 'department_sales.sale_id', '=', 'sales.id')
->select('sales.date',
DB::raw('sales.id as sales_id'),
DB::raw('(IFNULL(sum(department_sales.amount), 0)) as department_sales'),
DB::raw('(IFNULL(sum(category_sales.amount), 0)) as cat_total')
)
->groupBy('date', 'sales.id')->orderBy('date', 'desc')->get();
The following is the result output from above query and it is wrong:
I have a table structure with following data: categories_sales has following data:
department_sales
As per the table : I expected result should have been :
department_sales: 10 for sale_id = 1
department_sales: 5 for sale_id = 2
category_sales: 200 for sale_id 1
category_sales: 30 for sale_id 2
Can someone please give me some idea ? I will be really really thankful.

Categories