I Try To Pass Parameter To With() Function For Model:
Model::with(['functionA($parameters)', 'functionB'])
I think you are looking for this type.
Model::with(['functionA' => function($query) use ($parameters) {
$query->where('some_column', $parameters);
}, 'functionB'])->get();
Unfortunately, you can't use 'with' for normal function, it's used for eloquent's relationships.
for your case you can proceed like this:
$model = new Model(); // or $model = Model::where(anyConditionYouWant)->first();
$model->functionA($parameters);
you can use your functions any time you want without declare them in 'with' sentence
Related
I'm trying to get the right data from the database, I'm retriving a model with a media relation via eloquent, but I want to return a photo that contains the 'main' tag stored in JSON, if this tag is missing, then I would like to return the first photo assigned to this model.
how i assign tags to media
I had 3 ideas:
Use orWhere() method, but i want more likely 'xor' than 'or'
$models = Model::with(['media' => function ($query) {
$query->whereJsonContains('custom_properties->tags', 'main')->orWhere();
}]);
return $models->paginate(self::PER_PAGE);
Raw SQL, but i don't really know how to do this i tried something with JSON_EXTRACT and IF/ELSE statement, but it was to hard for me and it was a disaster
Last idea was to make 2 queries and just add media from second query if there is no tag 'main'
$models = Model::with(['media' => function ($query) {
$query->whereJsonContains('custom_properties->tags', 'main');
}]);
$models_all_media = Model:: with(['media']);
return $models->paginate(self::PER_PAGE);
but i tried something like
for($i=0; $i<count($models); $i++) {
$models->media = $models_all_media
}
but i can't do this without get() method, beacuse i don't know how to change this to LengthAwarePaginator class after using get()
try using whereHas https://laravel.com/docs/9.x/eloquent-relationships
Model::with('media')
->whereHas('media',fn($media)=>$media->whereJsonContains('custom_properties->tags', 'main'))
->paginate(self::PER_PAGE);
as per your comment you can use
$models = Model::with(['media' => function ($query) {
$query->whereJsonContains('custom_properties->tags', 'main');
}])
->leftJoin('media', function ($join) {
$join->on('models.id', '=', 'media.model_id')
->whereNull('media.custom_properties->tags->main');
})
->groupBy('models.id')
->paginate(self::PER_PAGE);
return $models;
I am new to the laravel, i am joining three tables based on conditions every thing is working fine but i need to write conditionally if the $field is array it should run with whereIn otherwise it should run where condition,can you please help me to acheive this thing
//$field sometimes it's an array sometimes it's a string.
public function find($field){
}
For conditional constraints, you can use the when() clause:
$query = DB::table(...);
$data = $query
->when(is_array($field), function ($query) use ($field) {
$query->whereIn('my_field', $field);
}, function ($query) use ($field) {
$query->where('my_field', $field);
})
->get();
Now, as a tip, you could do this: Wrap the $fields variables to an array and then use always the whereIn clause. You can achieve this with the Arr::wrap() function:
use Illuminate\Support\Arr;
// ...
$query = DB::table(...);
$data = $query
->whereIn('my_field', Arr::wrap($field))
->get();
PS: I have linked the relevant functions to the docs so you can know how they work and their params.
I'm trying to make a method to retrieve model with a relationship I'd like to be able to fetch the relation based on a boolean parameter
for example, I can do it using the if condition like the following
if($load == true){
$users = User::with('login')->all()->paginate();
}else{
$users = User::all()->paginate();
}
I'm wondering if there's a way to do it without the if condition on the fly
You can use the when() method on the query builder. Note that you don't need to use the all() method when you want to use a paginator.
User::query()
->when($load, fn($query) => $query->with('login'))
->paginate();
you can use when method:
$users = User::when($load, function ($query) {
return $query->with('login');
})->paginate(10);
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
I want to check something in if, and if that condition is true I want to update the record that was fetched before.
$resultQuery = DB::table('cards')->where('api_id', $card->id)->first();
if (this condition will pass I want to update this record) {
$resultQuery->update(array('price_usd' => $card->prices->usd));
}
When I use the ->update() like this, I get an error:
Call to undefined method stdClass::update();
How can I do this ?
The first() function on laravel query builder returns a stdClass meaning Standard Class.
There is no function called update() in stdClass in php. You have called update() on stdClass, and that causes the error.
There are several ways to achieve your goal.
Use Laravel query builder update() function.
$resultQuery = DB::table('cards')->where('api_id', $card->id)->first();
if (your_condition) {
Db::table('cards')
->where('api_id', $card->id)
->update([
'price_usd' => $card->prices->usd
]);
}
If you don't want to fetch the card data, don't call first()
$resultQuery = DB::table('cards')->where('api_id', $card->id);
if (your_condition) {
$resultQuery
->update([
'price_usd' => $card->prices->usd
]);
}
Use Eloquent models (Laravel's preferred way)
Create an Eloquent model for Cards (if you have not done already).
public class Card extends Model
{
}
Use eloquent query builder to fetch data. And use model update() function to update data.
$resultingCard = Card::where('api_id', $card->id)->first();
if (your_condition) {
$resultingCard->update([
'price_usd' => $card->prices->usd,
]);
}
If you're using model
You can add in card controller
$card = Card::where('api_id', $card->id)->first();
if (someConditional)
{
// Use card properties, number is a example.
$card->number = 10
// This line update this card.
$card->save();
}
You can learn more about eloquent here.
Something like this:
$resultQuery = DB::table('cards')->where('api_id', $card->id);
if ($resultQuery->count()) {
$object = $resultQuery->first();
$object->price_usd = $card->prices->usd;
$object->save();
}
Or look for an alternative solutions here: Eloquent ->first() if ->exists()
I have the following base query I use for retrieving collections with their relations, scopes, sorting, filtering,... This base query is used on almost all my models by extending the class this base query is in.
return $this->runSortQuery(
$query->when($request->has('filter'),
function($query) use ($request) {
return $query->search($request->filter);
}
)->when($request->has('with'),
function($query) use ($request) {
return $query->with(
explode(',', $request->with)
);
}
)->when($request->has('scopes'),
function($query) use ($request) {
return $query->scopes(
json_decode($request->scopes, true)
);
}
) /* and so on... */, $request
)->paginate((isset($request->paginate)) ? $request->paginate : 15);
Is it possible to replace the callback in every when with a custom function call? The reason I want this is because this base function is getting really long and I would like the method in the callback in it's own function, for readability and to keep this maintainable.
I tried this, but this obviously does not work.
$query->when($request->has('filter'), $this->filter($query, $request->filter))
->when($request/* and so on... */);
Can this be done in another way or what would be a good pattern or method to do this?
Yes, you can use the callables like so:
$query->when($request->has('filter'), [$this, 'someMethodNameInClass'])
->...
Check out this SO thread to learn more