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
Related
I'm trying to get the data without using eager loading in a Eloquent Model but I needed to cast it into Array to use in some part of the code.
In order words, I wanna just get the data like this example:
$invoice->invoice_type_id->name;
Since it's an array what I'm writing is: nfe['invoice_type_id']['name']
But I'm getting this error (because it's an array):
Trying to get property of non object
So, my query is:
Invoice::query()->where('order_id', $order_id)->get()->toArray();
And my model I already have the relationship declared:
public function invoiceType()
{
return $this->belongsTo(InvoiceType::class);
}
I have a model called Shift on my application, and I've defined my relationships and scopes on it like this:
Relationship:
public function status()
{
return $this->belongsTo(ShiftStatus::class);
}
With scope:
public function scopeWithStatus($query)
{
$query->with('status');
}
Now, when I retrieve shifts and try to call these scopes, I do the following:
$shifts = Shift::all()
->withStatus()
->withProfession()
...
->get();
return response([
'message' => 'Shifts retrieved.',
'shifts' => $shifts
]);
However, I get this error...
"message": "Method Illuminate\\Database\\Eloquent\\Collection::withStatus does not exist.",
I'm not sure why this is happening? It should pick up the scope shouldn't it?
It is not possible to use a query scope in a Collection, since query scope is a concept used in Eloquent to add constraints to a database query while Collections are just a collection of things (data, objects, etc).
So, remove all(). Also i think you are missing return statement in scope (not a part of this question, but you need to update the code )
when you call Shift::all() you get all the shifts table record from db as a collection , then you load the relation on that collection which makes that error.
you should not be loading the result from db unless your query is ready, you should tell the query builder to load the relation then call the result:
$shifts = Shift::withStatus()
->withProfession()
...
->get();
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.
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();
As one can see above, there is a 'eagerLoad' section and the querybuilder accepts calling $query->with('relation') but produces the following error: Method addEagerConstraints does not exist.
I've tried to find some documentation on this matter but didn't find much. Is it possible at all to use eager loading in this case? If so, could anyone tell how?
Update
As some people pointed out it is possible and the error is caused by another error in my code. Here are some samples:
// Querybuilder
$query->select([
'persons.id as alumni_id',
...
]);
$query->where('...'); // Based on search parameters
$query->groupBy('alumni_id');
$query->with('relation');
$result = collect($query->get());
// Model
public function relation()
{
// Note: relation does have a column person_id
return $this->hasMany(Relation::class, 'person_id', 'alumni_id')->get();
}
Produces
BadMethodCallException in Macroable.php line 81: Method addEagerConstraints does not exist.
As far as I've learned, It is not possible to use eager loading to load Model relations with the querybuilder. (as the querybuilder is not leveraging Eloquent, it doesn't know about the relations)
If anyone knows this to be (partially) incorrect, please let me know.
This should work
// Querybuilder
$query->select([
'persons.id as alumni_id',
...
]);
$query->where('...'); // Based on search parameters
$query->groupBy('alumni_id');
$query->with('relation');
$result = $query->get(); // already returns a collection
// Model
public function relation()
{
// Note: relation does have a column person_id
// A relation should return an Eloquent object (HasMany in this case), not a collection
return $this->hasMany(Relation::class, 'person_id', 'alumni_id');
}