Laravel -> Make query based on model's method result - php

I have 2 tables and models.
So, 1 CV has Many Diplomas. Relationship is defined in models.
In my edit action :
$cv = Cv::where('link', '=', $link)->firstOrFail();
Then If I'm calling relationship function diplomas like here :
$cvDiploms = $cv->diplomas;
return $cvDiploms;
It returns me array of JSON objects.
Now, I'm trying to make a query like :
$deletedDiplomas = $cv->diplomas->whereNotIn('image', $request['test-diploma'])->get();
It returns me that error :
Missing argument 1 for Illuminate\Support\Collection::get(), called in
/home/name/project/app/Http/Controllers/CvsController.php on line 272
and defined
How should I call that query to get all Cv's diplomas, where 'image' is not in $request['test-diploma'] ?

$cv->diplomas automatically calls get() on the query, so it returns a collection. You are then calling get() again, but the Collection method get() requires an argument.
You need to write $cv->diplomas() (referencing the function not the attribute) to fetch the query, which you can then filter before calling get()
$deletedDiplomas = $cv->diplomas()->whereNotIn('image', $request['test-diploma'])->get();

You are probably trying to make a query on an array object. You should use the relation itself to make the query. Try this:
$deletedDiplomas = $cv->diplomas()
->whereNotIn('image', $request['test-diploma'])
->get();

Related

Why is it not possible to use groupBy() in an eager loading query - Laravel

ErrorException:
stripos() expects parameter 1 to be string, object given
For the groupBy() call in the with() method
$user = User::with([
'pricelists' => function($query) {
$query->groupBy(function($var) {
return Carbon::parse($var->pivot->created_at)->format('m');
});
}
])->where('id', $id)->get();
I already saw a few posts talking about how to manage this problem and that it shall not be possible to use groupBy() in eloquent but I do not really understand why...
To be clear:
User and Pricelist model got a many-to-many relationship with the default timestamps() method. I am trying to get the downloaded pricelists grouped by their months they were downloaded from the current user.
After a few attempts I just deleted the above shown => function($query... statement from the with() method and just left the with(['pricelist']) to fetch all datasets and tried this:
$user->pricelists = $user->pricelists->groupBy(function($var) {
return Carbon::parse($var->pivot->created_at)->format('m');
});
return $user->pricelists;
And it works fine and returns an array with multiple arrays for each month... But returning it like this:
return $user;
returns just 1 array with all entries... I do not really get the sense behind it right now...
The two groupBy() method that you are using in the two code you provide are totally different methods.
The first groupBy() where you use it in the callback is actually being called by $query which is a query builder object. The groupBy() here is used to add SQL GROUP BY Statement into the query. And as per the documentation, it only take string variables as parameter.
The groupBy() in your second code is being called by $user->pricelists which is a laravel eloquent collection. The groupBy() method here is actually from the base collection class and is used to group the items inside the collection into multiple collections under the different key defined by the parameter passed to the function. Please read the documentation here.
For your case, the second groupBy() is the one you should be using since you plan to use a callback and will allow you to use more complicated logic.

Difference between laravel value() function and direct model access

I'm doing an Eloquent query in my Profession model, i ran an where query, retrieve the first value, then caught only the value in "id" column with ->value('id')
//This always return 1
$profession = Profession::where('name', $profession)->first()->value('id');
//This return the right value
$profession = Profession::where('name', $profession)->first()->id;
Does value() function depends on some other aspect of the query/configuration? Couldn't find anything in Laravel query builder documentation.
Profession::where('name', $profession)->first() returns a model. You cannot call value on a model. However, you may call it on a query builder as explained in the docs?
So instead of calling
$profession_id = Profession::where('name', $profession)->first()->id;
you could achive the same thing with
$profession_id = Profession::where('name', $profession)->value('id');
There is a helper function in laravel with the name value . It will always returns that value it is given for example value(true) is true
But for eloquent if you want to access the fields either you use pluck function like ->pluck(id) it will give you ids only

How to specify two or more conditions within find() method in Laravel?

I'm having problems fetching data using Model::find() with two conditions. I want to return one record that has the given member_id AND its role is guest:
$member = CalendarMembers::find(["member_id" => $r->member_id, "role" => "guest"]);
But this isn't working. I have one user that when created, a new register is added to calendar_members table specifying this user as parent, yet, when attempting to fetch this user automatically created by just giving the member_id, it will be fetched, which SHOULD NOT.
I cannot use other ways such as:
$member = \DB::table("calendar_members")->where([ ["member_id", "=", $r->member_id], ["role", "=", "guest"] ])->first();
Because then $member->delete() or $member->destroy() will throw an error saying either delete or destroy do not exist.
The find() method uses ID to get a record. You need to use the where() and first() methods:
CalendarMembers::where(['member_id' => $r->member_id, 'role' => 'guest'])->first();
you should use where for multiple conditions and get the first row with first() method, find is basically an alias for wehre('id', $id)
To make it clear, find() method will perform database query and returns single model object as result. so find is equal to,
Model::where('id', 1)->first().
find() returns Model object and where() returns QueryBuilder. But you can directly perform on query Builder without fetching model, like,
Model::where('id', 1)->delete().
REF : https://laravel.com/docs/5.6/eloquent

Laravel recovering the id of the return of a json

I'm having a problem retrieving data from a select.
When I perform the following select
$Projeto = $this->ModelProjeto
->select('projeto.*','tipoprojeto.descricao')
->join('tipoprojeto','tipoprojeto.id','=','projeto.tipoprojeto')->get();
and returns json
[{"id":1,"descricao":"house","tipoprojeto":1,"tipoprojetodescricao":"Engenharia Civil"}]
When I try to retrieve the json id with the following command: return $Projeto->id; error appears
Property [id] does not exist on this collection instance.
if I used the find method, it would work normally, but it is not possible to use join, so how do I access Project-> id using the -> get () method?
The get() method returns a collection, not an individual item.
$Projetos = $this->ModelProjeto
->select('projeto.*','tipoprojeto.descricao')
->join('tipoprojeto','tipoprojeto.id','=','projeto.tipoprojeto')
->get();
// you would need to loop the $Projetos to get each id
$Projetos->each->id
// or use the first() method if you know only one item is returned
$Projeto = $this->ModelProjeto
->select('projeto.*','tipoprojeto.descricao')
->join('tipoprojeto','tipoprojeto.id','=','projeto.tipoprojeto')
->first();
Looking at the JSON, this is an array, so instead of using get(), use first()
$Projeto = $this->ModelProjeto
->select('projeto.*','tipoprojeto.descricao')
->join('tipoprojeto','tipoprojeto.id','=','projeto.tipoprojeto')->first();
This will make sure only 1 record is returned and that it will return an object instead of a collection

How to get a Builder object from rows related to pivot - Laravel

I'm trying to get all the "books" that one user have: but I can't do it how I need.
I use the following code:
/*Gets all books from the user whose id is 1*/
$books= User::find(1)->books();
That return to me an Collection object; but I need a Builder object, as I get when I use the "select" method.
/* This code return me a "Builder" object */
Books::select(array('id', 'name', 'type'));
I need the Builder instead of Collection because I using Bllim/Datatables on my project and this package just accept a Builder object...
If I send it a Collection its throw me the next error (500 - Internal Server Error):
{
"error":
{
"type":"ErrorException",
"message":"Undefined property: Illuminate\\Database\\Eloquent\\Builder::$columns",
"file":"\/var\/www\/proyect\/myproyect\/vendor\/bllim\/datatables\/src\/Bllim\/Datatables\/Datatables.php",
"line":256
}
}
Anybody knows the solution?
EDIT:
When I use the getQuery() method twice I get the following error:
{"error":{"type":"ErrorException","message":"array_values() expects parameter 1 to be array, null given","file":"\/var\/www\/proyect\/myproyect\/vendor\/bllim\/datatables\/src\/Bllim\/Datatables\/Datatables.php","line":550}}
Is rare, because when I used the "select" method Datatables worked perfectly...
This code works:
Books::select(array('id', 'name', 'type'));
But the code you told me doesn't work:
$user = User::find(1);
$user->books()->getQuery()->getQuery();
Use method call books():
$user = User::find(1);
$user->books(); // relation object
$user->books; // dynamic property
First books() returns a relation object, that you can chain Eloquenr\Builder or Query Builder methods on.
Second books is a dynamic property - the query is automatically executed and its result is stored in the $user->relations['books'] and returned.
edit
As per comment - what you need is base Query\Builder object if you want to access columns property, so you need getQuery twice:
$user->books()
->getQuery() // get underlying Eloquent\Builder
->getQuery() // get underlying Query\Builder
->columns // public property on the above

Categories