i'm working on a small project using Laravel and i do my best to understand the Laravel documentation to create a nice solutions, but this time i found some difficult to understand the WHEN clause
can someone explain to me this code by giving me an example:
$role = $request->input('role');
$users = DB::table('users')
->when($role, function ($query, $role) {
return $query->where('role_id', $role);
})
->get();
Docs : https://laravel.com/docs/7.x/queries#conditional-clauses
Also i would like to know what stand for the second parameter [] in the input function
request()->input('field', []);
As long as the variable role equates to true, this query will execute:
return $query->where('role_id', $role);
In terms of your second question, if request parameter 'field' is not filled the default value set will be: [].
Another Example:
$foo = $request->input('test', 69);
If the request parameter test isn't filled, the parameter foo will be 69.
Related
Can someone help me out, I'm trying to do a where query on a Child Model. Everything seems fine when I have a value for the id but it returns nothing when no id is supplied.
My goal is to get all data when no id is supplied and get specific data when id supplied.
Here's my code
Report::with(['project'])
->whereHas('project' function($q) use($programId){
if($programId){
$q->where('program_id', $programId);
}
})->get();
Is there a better way to achieve my goal? or I just lack something on the query? Thank you in advance.
You can use when method for this.
The when method only executes the given closure when the first argument is true. If the first argument is false, the closure will not be executed.
Report::with('project')
->when($programId, function ($query) use ($programId) {
$query->whereHas('project' function($q) use($programId){
$q->where('project.program_id', $programId);
});
})->get();
So I have a little complex answer for this type of questions where you can create a query and do every logic to it.
// Initialise the model
$query = new Report;
// Start building the query
$query->with('project');
// Check if project Id exists
if ($projectId) {
return $query->whereHas('project', function ($subQuery) use ($projectId) {
$subQuery->where('program_id', $programId);
})->get();
} else {
return $query->get();
}
I do a specific relation query all over the application, where I only need the User's subscriptions that have active column set to true.
And I have a scope method in User model, which applies said filter, to avoid copy/paste, like:
public function scopeWithActiveSubscriptions($query)
{
$query->with([
'subscriptions' => function ($query) {
$query->where('active', true);
},
]);
}
Now sometimes I want to eager-load the plan of each subscription, too.
For that I tried something like:
$user = User::where('id', 1)
->withActiveSubscriptions()
->with('subscriptions.plan')
->first();
$subscriptionList = $user->subscriptions;
But query results to all subscriptions,
in other words, ignores the ->where('active', true) part (of scope method).
How can I make this work correctly?
A quick solution would be modifying the scopeWithActiveSubscriptions method to allow it to accept another optional parameter that tells it which additional relations should also be included and thus you don't loose your filtering.
public function scopeWithActiveSubscriptions($query, array $with = [])
{
// just merges hard coded subscription filtering with the supplied relations from $with parameter
$query->with(array_merge([
'subscriptions' => function ($query) {
$query->where('active', true);
}
], $with));
}
Now you can tell that scope which nested relations you want to include and you no longer need to call with to include them by yourself.
$user = User::where('id', 1)
->withActiveSubscriptions(['subscriptions.plan'])
// ->with('subscriptions.plan') // no longer needed as we're telling the scope to do that for us
->first();
$subscriptionList = $user->subscriptions;
With that you can pass custom relations to the scope something like (am improvising here just for demo purposes)
$user = User::where('id', 1)
->withActiveSubscriptions([
'subscriptions.plan' => fn($q) => $q->where('plans.type', 'GOLD')
])->first();
Learn more about Laravel's Eloquent Scopes.
Hope i have pushed you further.
Seems Laravel does not have yet any chainable (Builder-style) solution (for asked situation), and we ended up editing the scope filter.
Into something like:
public function scopeWithPendingSubscriptions(Builder $query, $subRelations = null)
{
$query->with([
'subscriptions' => function (HasMany $query) use ($subRelations) {
$query->where('active', '=', true);
if ($subRelations) {
$query->with($subRelations);
}
},
]);
}
Which allows me to do query like:
// ...
->withActiveSubscriptions('plan');
Instead of my old (not working) code, which was:
// ...
->withActiveSubscriptions()
->with('subscriptions.plan');
Note that even passing nested-filters is now possible, like:
// ...
->withActiveSubscriptions(['plan' => function ($query) {
$query->where('name');
}]);
(Basically same as Laravel's ->with(...) method.)
I want to select all the users in my table "User" except the first One cause its the admin,
im using this function index in my controller but it doesn't work .
public function index()
{
// this '!=' for handling the 1 row
$user = User::where('id', '!=', auth()->id())->get();
return view('admin.payroll',compact('user'))->with(['employees' => User::all()]);
}
Better to used here whereNotIn Method
Note: first you find the admin role users and create a static array
$exceptThisUserIds = [1];
$user = User::whereNotIn('id', $exceptThisUserIds)->get();
It's not a good idea to specify the admin user with just id. A better design would be using some sort of a flag like is_admin as a property of your User model.
Still you can use the following code to get the users who have an id greater than 1:
User::where('id', '>', 1)->get()
For getting data skipping the first one you should use skip() method and follow the code like below
public function index()
{
$user = User::orderBy('id','asc')->skip(1)->get();
return view('admin.payroll',compact('user'))->with(['employees' => User::all()]);
}
I have posts table that has related table where I store different translations based on post_id now when I want to return translation data based on user selected locale it says:
mb_strpos(): Argument #1 ($haystack) must be of type string, Closure given
Here is my function
$posts = Post::with('translations', function($q) {
$q->where('translate_code', app()->getLocale());
})->get();
dd($posts); // returning error above
But if I do this
$posts = Post::with('translations')->get();
dd($posts);
I will get following results
Here is translations data details:
My question is:
How can I return the one translation that has current locale name only?
If you using callback in with then use array of relations like below. Older version of laravel was working which you mentioned but latest version need array of relations when using callback.
$posts = Post::with(['translations'=> function($q) {
$q->where('translate_code', app()->getLocale());
}])->get();
using conditional eager loading should be like this:
$posts = Post::with(['translations'=> function($q) {
$q->where('translate_code', app()->getLocale());
}])->get();
while the relation name is the key, a closer to get data should be the value for the associative array for 'with' statement.
You can query your relation by using whereHas().
Docs: Laravel Docs Relationships
For example:
$posts = Post::whereHas('translations', function ($query) {
$query->where('translate_code', 'en');
})->get();
Maybe try to put the app()->getLocale() into a variable first. (after trying this out in tinker, this does seem te return a string, so may passing it by reference might help).
I'm using Laravel 4. Say I have an Eloquent model (Patient) and I want to get a patient with the name Bob, I would do this:
$patient = Patient::where('name', '=', 'Bob');
What is the best way to check to see if $patient is a valid record?
If the database query does not find any matching results, it returns null. Therefore...
$patient = Patient::where('name','=','Bob')->first();
if ( is_null($patient) ) {
App::abort(404);
}
(Note: in your original question you forgot ->first() (or ->get()) in your query. Don't forget that or else you will get an Eloquent object instead of a result.)
use this:
$patient = Patient::where('name', '=', 'Bob')->firstOrFail();
it will return Eulqouent model on success or throw ModelNotFoundException upon failure.
I know this is old, but this came up as the 2nd google hit on a search, so . . . for cases where you are not expecting one record or cannot use ->firstOrFail() (my use case is an async typeahead api that returns up to 10 results) the only thing that worked for me was count():
$patient = Patient::where('name', '=', 'Bob')->get(); //you could have more than one bob
if (!count($patient)) {
return 'No records found';
}
$patient = Patient::where('name','Bob')->get();
if ( $patient->isEmpty() ) {
return response(['error' => 'Record not found'], 404);
}
Something like Patient::where('name', '=', 'Bob')->exists() may work. It will return a boolean.
Just use empty() from native php will solve everything, if object null it will return true, if laravel's collection from query builder is empty (but initialized) it will return true too.
$contributor = Contributor::whereVendor('web')->first();
if(empty($contributor)){
...
}
use findOrFail($id) in case of you are passing id parameter to fetch a single record
I ended up on this while seeking solution of ::find($id)->firstOrFail syntax which is error-full.
$patient = Patient::findOrFail($id);