How to order relationships in laravel? - laravel-5

I need help with Laravel 5.4.
I have 2 tables: origins and coffees.
An origin can have many coffees.
In my controller I have this:
$origins = Origin::with('coffee')->get();
Is it possible to order the result by origin name and coffee name, both in ascending order with Eloquent or do I need to us query builder?
Something like:
select coffees.name, origins.name
from coffees
join origins
on coffees.origin_id = origins.id
order by origins.name asc, coffees.name asc

Can you try if this gives you the results you want:
$origins = Origin::with(['coffee' => function ($query) {
$query->orderBy('name', 'asc');
}])->orderBy('name', 'asc')->get();

Related

Laravel JOIN with JSON string

I have two tables in Laravel, one is the comment table, and the second is the users table. In the comment table, I have this type of data.
For this comment table, I want to match the tags column's userid in JSON, so how can we join that userid with the user's table? here is what I tried, but that is not working as expected.
$messages = TopicComment::where('user_id', $currentUserId)
->join("users", "users.id", "=", "users.id")
->(function ($query) {
$query->whereJsonContains('tags.userid', users.id);
})
->
->get()->toArray();
with this package you can create a relation via a json field
https://github.com/staudenmeir/eloquent-json-relations
First, there seem to be a number of errors in your code.
Judging from the DB schema, there is no user_id column in your comments table and so, ::where('user_id', $currentUserId) will not work.
A similar issue occurs in your join statement. You're joining on "users.id","=","users.id" which is the same column in the same table.
There's no method called in the line with function($query). Ideally, should be a where clause.
Correct usage of whereJsonContains would be:
$query->whereJsonContains('tags', ['userid' => $currentUserId]);
Rouge arrow after that line.
And so, your final result after correcting the changes should look like:
use Illuminate\Support\Facades\DB;
...
$messages = TopicComment::join('users', 'users.id', DB::Raw("CAST(comments.tags->'$.userid' AS UNSIGNED)"))
->where(function ($query) use ($currentUserId) {
$query->whereJsonContains('tags', ['userid' => $currentUserId]);
})
->get()
->toArray();
I think the only way to extract is to use json tables.
DB::select(DB::raw("
SELECT document_types.*, jst.name
FROM document_types,
JSON_TABLE(settings, '$[*]' COLUMNS (
`userid` int(11) PATH '$.userid',
`name` varchar(255) PATH '$.name'
)) jst
inner join users on jst.userid = users.id WHERE users.id = :id"
,['id' => $currentUserId]))->get()
credit: https://dba.stackexchange.com/questions/306938/extract-json-object-inside-of-an-json-array-then-search-base-on-id
Unfortunately I don't have json functions on my mysql so the code will probably fail, maybe at least it'll help get you on the right track.
You can try this way...
eg:
<?php
$comments = DB::table('topic_comments')
->join('users', 'users.id', '=', 'topic_comments.tags->userid')
->select('topic_comments.*', 'users.name')
->get();

Eloquent count occurrence with where clause

I'm trying to do a simple query using Eloquent. My test_registrants table looks like this
I want to add new column with value of all user_id with payment_status = 1
This is my query using whereColumn
TestRegistrant::select(['test_registrants.*'])
->where('payment_status', 1)
->addSelect([
'attempt' => TestRegistrant::select(DB::raw('count(*) as attempt'))
->whereColumn('test_registrants.user_id', 'user_id')
->where(function ($query) {
$query->where('payment_status', 1);
})
]);
but I get all user_id instead
What I'm trying to achieve is this one
So what do I do wrong here? thank you
The reason your query is returning 3, is because it is simply counting all the records that have payment_status = 1. The whereColumn() is not working properly, because it does not reflect the right columns.
When you define an alias for the user_id column on the test_registrants table, it should work. For example, you could name it: outer_user_id. I have updated your example accordingly:
TestRegistrant::select(['test_registrants.payment_status', 'test_registrants.user_id as outer_user_id'])
->where('payment_status', 1)
->addSelect([
'attempt' => TestRegistrant::selectRaw('count(*) as attempt')
->whereColumn('test_registrants.user_id', 'outer_user_id')
->where(function ($query) {
$query->where('payment_status', 1);
})
])
->get();
Alternatively, you could also look into grouping the results, so that you can count all the rows in a specific group.

Join on Eloquent breaks Relationships?

I have the following relation:
I have a many-to-many relation between Course and Users, and then again a has-many relation between Users and Certificates.
Now here is way how to get all users from one course, who have a certificate in the same course:
$user = $course->users()
->whereHas('certificates', function ($query) use($course){
$query->where('course_certificates.course_id', '=', $course->id);
})->first();
This will return a user with certificates $user->certificates.
This is the query.
SELECT *
FROM "course_users"
WHERE "course_users"."course_id" = ? AND
"course_users"."course_id" IS NOT NULL AND
EXISTS (
SELECT *
FROM "course_certificates"
WHERE "course_users"."id" = "course_certificates"."user_id" AND
"course_certificates"."course_id" = ?
)
If I use a join instead:
$user = $course->users()
->join('course_certificates', 'course_certificates.user_id', '=', 'course_users.id')
->where('course_certificates.course_id', '=', $course->id)
->first();
Then I get the same user, however the relationship $user->certificates is empty?
SELECT *
FROM "course_users"
INNER JOIN "course_certificates"
ON "course_certificates"."user_id" = "course_users"."id"
WHERE "course_users"."course_id" = ? AND
"course_users"."course_id" IS NOT NULL AND
"course_certificates"."course_id" = ?
Why is that?
I am not 100% sure, but if you use join I think laravel do not understand whatever table you are joining it with that it is a relation, it is just a join, it could mean anything, but the first query you are telling it what the relation means (whereHas some data for X relation).
Looking at the source code, I can confirm what I am saying: join and whereHas (and has).
getRelated() does the magic (adds the data to your relation). See that join does not do anything of this, it literally joins queries, nothing else related to relations. Also join comes from Query/Builder and any other method about relations comes from Eloquent/Builder.

how to union and groupby in laravel

i want to get contact id who was send chat or was i send chat to him
with native query i can get result but when i implement in laravel its going difficult
this my native query
select * from `users` where `users`.`id` in (
select `to` from messages where `from` = 2 group by `to`
union
select `from` from messages where `to` = 2 group by `from`
)
what i find difficult is how union after group by or group by after union with make same column number, i using merge but the result is wrong
this what i have try in laravel
$to = Message::select('to')->where('from',auth()->id())->groupBy('to')->get();
$from = Message::select('from')->where('to',auth()->id())->groupBy('from')->get();
$tofrom = $to->merge($from);
dd($tofrom);
please if any body can help
Unions are described in the documentation. To achieve your specific requirements you can do:
$final = User::whereIn('id', function ($query) {
$from = Message::select('from')->where('from',auth()->id())->groupBy('from');
$query->from('messages')->where('to',auth()->id())->groupBy('to')->union($from);
})->get();
Disclaimer: I have not actually tested this but I think it should work.
merge() is the method of collection. Not the Eloquent Builder or Query Builder.
However, It think you want to find user.id in the array.
You can convert the collection to array:
$to = Message::where('from',auth()->id())->groupBy('to')->pluck('to');
$from = Message::where('to',auth()->id())->groupBy('from')->pluck('from');
$tofrom = $to->merge($from)->toarray();
User::whereIn('id', $tofrom)->get();
oh finally i got the answer this is code
$contacts = User::select('users.id','users.name','users.email','users.profile_image')
->join('messages',function($join){
$join->on('users.id','messages.from');
$join->orOn('users.id','messages.to');
})
->where(function($query){
$query->where('messages.from',auth()->id())->orWhere('messages.to',auth()->id());
})
->groupBy('users.id','users.name','users.email','users.profile_image')
->get();

What is the equivalent query of laravel on this?

This is the native sql:
$sql = "Select count(name) from users Where email = 't#t.com' and user_id = 10";
I have this laravel code:
$checker = Customer::whereEmailAndUserId("t#t.com",10)->count("name");
Is this a correct way to do it in laravel?
You have to use where helper function and pass an array of checks. For example in your code it will be:
$checker = Customer::where([
['email', '=', 't#t.com'],
['user_id' '=', '10']
])->count();
Note: Please use the appropriate column name as it in table.
Assuming Customer model represents table users, you'll get query with eloquent like this:
Customer::where('email', 't#t.com')->where('user_id', 10)->select(\DB::raw('count(name)'))->get();
The option you are trying is incorrect
here is the right option
$users = \App\Customer::where('email','t#t.com')
->where('user_id',10)
->count()
Explanation of above code
App\Customer is the Model class and I am trying to read records where email = 't#t.com you can use various comparison operators like <,> and so on and you can also use the same function to for string pattern matching also
Eg.
$users = \App\Customer::where('email','%t.com')
->where('user_id',10)
->count()
You can use the same where function for Null Value test also
Eg.
$users = \App\Customer::where('email','=', null)
->where('user_id',10)
->count()
The above where clause will be converted to is null test of the SQL
You can read more here

Resources