I'm struggling with Laravel since I'm still a beginner.
In my web.php I have the following route
Route::get('/customize/{id}', function ($id) {
if (User::where('id','=','4')->has('profile'->with('id',$id))->exists() && Profile::where('user_id', $id)->exists()) {
return true;
}
return false;
});
I know something isn't right.
Basically what I want to do is, return true ONLY IF The user with id 4 has a profile with the same id as the one in the url.
In my user modal I have the following relationship :
public function profile()
{
return $this->hasMany(Profile::class);
}
Example of the profiles table:
You've got a typo.
if (User::where('id','=','4')->has('profile'->with('id',$id))->exists() && Profile::where('user_id', $id)->exists()) {
Should be
if (User::where('id','=','4')->has('profile')->with('id',$id)->exists() && Profile::where('user_id', $id)->exists()) {
By doing 'profile'->with(...) you were calling a member function (with(...)) on a string ('profile').
To return true only if the User with id 4 has a profile with id = $id, you want to use whereHas.
if (
User::where('id', 4)->whereHas('profile', function ($query) use ($id) {
return $query->where('id', $id);
})
->exists()
) { ... }
Using PHP ^7.4, this can be written a bit more compactly with shorthand Closures.
if ( User::where('id', 4)->whereHas('profile', fn($query) => $query->where('id', $id))->exists() ) { ... }
By the way, when using where()/orWhere(), if you don't use an operator, it's implied to be '=' so where('id', '=', 4) can be written as just where('id', 4).
Related
I am retrieving a bunch of records from the database to display:
$students = $bursary_administrator->students()/*->whereIn('status',[1,4,6,7])*/
->whereHas('bursaries.statuses', function($query) use ($request) {
$query->whereIn('status',[1,4,6,7])
->whereYear('status_start','<=',$request->year)
->where(function ($query) use ($request){
$query->whereYear('status_end','>=',$request->year)
->orWhereNull('status_end');
})
->where(function ($query) use ($request){
$query->whereYear('registration_date','<=',$request->year)
->orWhereNull('registration_date');
});
})
->with('bursaries','bursaries.statuses','bursaries.enrolments','bursaries.enrolments.courses')
->orderBy('student_name')->orderBy('student_middle_names')->orderBy('student_surname')->get();
Im displaying all these records in a table so need to fetch all of them.
I also however, need to get some count()'s based on this data. Now, I know I can perform individual queries for each count, but since I've already fetched all the data, I think it will be more optimised to just count the filtered data?
However, I am not winning. Both attempts listed below yield 0 as the output:
eg: using "where":
$summary['students_transfer'] = $students->where('status', '7')->count();
or, using "filter":
$summary['students_postgraduate'] = $students->filter(function ($student) {
return $student->qualification == 'Postgraduate' || $student->qualification == 'Postgraduate in Training';
})->count();
Not sure what I'm doing wrong?
You can utilize scopes in combination with withCount():
class Student extends Model
{
public function scopeTransfer($query)
{
return $query->where('status', '7');
}
public function scopePostgraduate($query)
{
return $query->where('qualification', 'Postgraduate')
->orWhere('qualification', 'Postgraduate in Training');
}
}
class Bursary_Administrator extends Model
{
public function students()
{
return $this->hasMany(Student::class);
}
public function students_transfer()
{
return $this->hasMany(Student::class)->transfer();
}
public function students_postgraduate()
{
return $this->hasMany(Student::class)->postgraduate();
}
}
$students = $bursary_administrator->students()/*->whereIn('status',[1,4,6,7])*/
->whereHas('bursaries.statuses', function($query) use ($request) {
$query->whereIn('status',[1,4,6,7])
->whereYear('status_start','<=',$request->year)
->where(function ($query) use ($request){
$query->whereYear('status_end','>=',$request->year)
->orWhereNull('status_end');
})
->where(function ($query) use ($request){
$query->whereYear('registration_date','<=',$request->year)
->orWhereNull('registration_date');
});
})
->with('bursaries','bursaries.statuses','bursaries.enrolments','bursaries.enrolments.courses')
->withCount('students_transfer', 'students_postgraduate')
->orderBy('student_name')->orderBy('student_middle_names')->orderBy('student_surname')->get();
Reason it wasnt working was because I was thinking of it as a database result instead of parent/child relationship.
ie, instead of:
$summary['students_postgraduate'] = $students->filter(function ($student) {
return $student->qualification == 'Postgraduate' || $student->qualification == 'Postgraduate in Training';
})->count();
I should of been doing:
$summary['students_postgraduate'] = $students->filter(function ($student) {
return $student->bursaries[0]->qualification == 'Postgraduate' || $student->bursaries[0]->qualification == 'Postgraduate in Training';
})->count();
I have the tables
threads
- id
replies
- id
- repliable_id
- repliable_type
I want to add another column to the Thread, which is the id of the most recent reply.
Thread::where('id',1)->withRecentReply()->get()
And the following query scope
public function scopeWithRecentReply() {
return $query->addSelect([
'recent_reply_id' => Reply::select('id')
->whereHasMorph('repliable', ['App\Thread'], function ($q) {
$q->where('repliable_id', '=', 'threads.id');
})->latest('created_at')
->take(1),
]);
}
I have also tried
public function scopeWithRecentReply() {
return $query->addSelect([
'recent_reply_id' => Reply::select('id')
->where('repliable_id', '=', 'threads.id')
->latest('created_at')
->take(1),
]);
}
But in both cases the
recent_reply_id => null
If instead of threads.id i enter an integer, it works and the recent_reply_id is not null
For example
public function scopeWithRecentReply() {
return $query->addSelect([
'recent_reply_id' => Reply::select('id')
->whereHasMorph('repliable', ['App\Thread'], function ($q) {
$q->where('repliable_id', '=', 1);
})->latest('created_at')
->take(1),
]);
}
My question is
Is there a way to be able to fetch the recent_reply_id using the respective threads.id ?
I would suggest using appends instead of query scopes so in your Thread model we will add
protected $appends = ['recent_reply_id'];
.....
public function replies () {
// you need to add here your relation with replies table
}
public function getRecentReplyIdAttribute () {
return $this->replies()->latest('id')->first()->id;
}
now wherever you query the threads table you will have access to recent_reply_id like
$thread = Thread::where('id',1)->withRecentReply()->get();
$thread->recent_reply_id;
enter image description hereI am trying to implement a many to many relationship search with 2 models.
i get input from multiple checkbox values and want to search for items that match A or B when there is an input of data.
I read this url and wrote the same logic.
https://laracasts.com/discuss/channels/laravel/many-to-many-relationship-with-2-pivot-table-data-search
public function search(Request $request)
{
$languages = $request->lang;
$fields = $request->field;
$agencies = Agency::with('languages')->with('specialized_fields')
->orWhereHas('languages', function($query) use ($languages) {
$query->whereIn('language_id', $languages);
})
->orWhereHas('specialized_fields', function($query) use ($fields) {
$query->whereIn('specialized_field_id', $fields);
})
->get();
dd($agencies);
}
i expected to achieve A or B search but instead I got this error.
Argument 1 passed to Illuminate\Database\Query\Builder::cleanBindings() must be of the type array, null given, called in /var/www/jtf/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php on line 907
it seems that it causes this error if either A or B is null, but why??? Does the OrWhereHas method work only when theres an input??
/added info/
my error message
my agency model
class Agency extends Model {
protected $guarded = [
'id'
];
public function languages(){
return $this->belongsToMany('App\Language');
}
public function specialized_fields(){
return $this->belongsToMany('App\SpecializedField');
}
public function region(){
return $this->hasOne('App\Region');
} }
I believe it's because either $languages or $fields is null.
Since ->whereIn() is expecting an array, but you're passing null.
You just need to make sure you're passing an array.
$languages = array_filter((array) $request->lang); // cast to array & remove null value
$fields = array_filter((array) $request->field);
$agencies = Agency::with('languages', 'specialized_fields')
->orWhereHas('languages', function($query) use ($languages) {
$query->whereIn('language_id', $languages);
})
->orWhereHas('specialized_fields', function($query) use ($fields) {
$query->whereIn('specialized_field_id', $fields);
})
->get();
I'm speculating that you started your where query chain with an orWhereHas() which may have caused the problem, try starting with whereHas() instead.
public function search(Request $request){
$languages = $request->lang;
$fields = $request->field;
$agencies = Agency::with('languages', 'specialized_fields') // you can get away by just using one with(), not needed but its cleaner this way
->whereHas('languages', function($query) use ($languages) { // previously orwherehas
$query->whereIn('language_id', $languages);
}) ->orWhereHas('specialized_fields', function($query) use ($fields) {
$query->whereIn('specialized_field_id', $fields);
})
->get();
dd($agencies);
}
I try to filter my users by role in a subquery but returns all records
here I have a normal Model query which I extend with a subquery if the request contains the position parameter
$query = User::select()-> ....
and here comes the extension on $request->has('position')
if ($request->has('position')) {
$role = $request->get('position');
if ($role == 'all') {
$query->with('roles');
} else {
$query->with(['roles' => function($query) use($role) {
$query->where('id', $role);
}]);
}
} else {
$query->with('roles');
}
but this one returns the filtered and plus other users
I got it working using whereHas model method, here is the hole refactoring
if ($request->has('position')) {
$role = $request->get('position');
if ($role !== 'all' && $role !== 0 ) {
$query->whereHas('roles', function($query) use($role) {
return $query->where('id', $role);
});
}
}
I get this error msg Call to a member function addEagerConstraints() on a non-object when I am trying to call a function from my model.
Here is the function:
public static function checkClaimById($claim_id) {
$result = Claim::with('orders')
->find($claim_id)
->where('orders.user_id', Auth::user()->id)
->whereNull('deleted_at')
->count();
if($result >= 1) {
return true;
} else {
return false;
}
}
I have the Model "claim" with has a field order_id and it belongs to an order.
And I have the model "order" and one Order has many claims.
Can someone help me?
thanks
Regards
I have modified my function like this:
public static function checkClaimById($claim_id) {
$result = Claim::with(array('orders' => function($query)
{
$query->where('user_id', Auth::user()->id);
}))
->where('id', $claim_id)
->whereNull('deleted_at')
->count();
if($result >= 1) {
return true;
} else {
return false;
}
}
Found the solution here: http://laravel.com/docs/eloquent#eager-loading