Query database table using LIKE in Laravel - laravel

I am trying to query a table using where like :
Auth::user()
->friends
->where('friend.first_name','LIKE','%'.$firstName.'%')
->all()
The query does work properly without using the LIKE statement only when i add the LIKE keyword it doesn't return any results.

Using all() will work without the builder where() statement.
When grabbing data using the query, use get() instead:
Auth::user()->friends->where('something','LIKE','%'.$something.'%')->get()

I think you are confused between a laravel relation and a eloquent collection. First let me go straight to answer, you would have to do
Auth::user()
->friends()
->where('friend.first_name','LIKE','%'.$firstName.'%')
->get()
To explain what's wrong with your code, ->where('name', 'Like', '%something%') This is a query builder method. You have to use it on the query builder, or Before you actually retrieve the model / model collection.
Auth::user()->friends()
This would give you a relation Illuminate\Database\Eloquent\Relations\HasMany that you can apply where like on.
Auth::user()->friends
This will return you a Illuminate\Database\Eloquent\Collection. And yes, it is a collection, so you will have to use collection method. Take a look at the where method for collection. You can see it only support key => value pair. It does not support "LIKE"
The where method filters the collection by a given key / value pair:
If you want to use achieve a "Like" on collection, you can probably use the filter method, which support custom callback.
The filter method filters the collection using the given callback, keeping only those items that pass a given truth test:
To conclude, when you define a friends "HasMany" relation on User, you have two way to retrieve it.
If you want to apply additional query builder method, you need to use user->friends() which do not return you data, it return you a relation that you can use query builder method. Once you do user->friends, it get you a collection. You cannot apply query builder on that anymore. So basically, user->friends is act the same way as user->friends()->get()

Don't Use all() and use get().
Auth::user()->friends()->where('something','LIKE','%'.$something.'%')->get()

Related

what is difference between model->name and model() in laravel?

I want to know the difference between laravel eloquent conisgnment->runsheet->name and $consignment->runsheet()->name
i notice that there is performance difference but why? also I notice that when I try to get relationship property like $consignment->runsheet->name it work fine but $consignment->runsheet()->name doesn't work
The first one
$consignment->runsheet
retrieve a collection (so it's already made a query to DB)
while the second
$consignment->runsheet()
is a query builder (hasn't made a database query) you can chain it like any query builder instance
so if you want to get a property from the second one you can do it like:
$consignment->runsheet()->first()->name;
OR
$consignment->runsheet()->value('name');

Eloquent model setRelation generating array instead of Collection

If you are doing $instance = $model->with('categories')->find($id); and after var_dump($instance->categories) it going to return Collection of categories.
But on the project I'm working on in some heavy queries, we are not using with and getting data with a combination of GROUP_CONCAT and CONCAT, like this:
\DB::raw('GROUP_CONCAT(DISTINCT CONCAT(categories.id, ",,", categories.name) SEPARATOR ";;") as categories'),
And then we are building relations manually parsing result and creating a relationship using $instance->setRelation($relation, $data) but for some reason, it's returning an array of objects instead of Collection.
There are also option to use setRelations() and this method returning Collection but I found if you have bidirectional relations it's creating recursion and working really slow. For example: if in User model we have set $this->hasMany('Comments') and in Comments model we have set return $this->belongsTo('User'); and after when we running setRelations() to manually build relations it is create nesting models with recursion (User->Comments->User and so on).
The third option is to not use setRelation() or setRelations() and just to manually create Collection, populating it and set to model. But in such case, it will not be set as a model relation.
Any suggestions on how to build manually in the right way (to create relation is same way eloquent creating with with).
Group return collection of collection so you have to remove the keys of first collection and for that you can use values function of collection like this
$instance->setRelation('relation', $data->values()->all());
Details https://laravel.com/docs/5.6/collections#method-values

Prevent hydration model objects with eloquent

I would like to understand what happen when using the toArray () method in a case like this:
Ad::query()->with('nominations')->where(['id'=>$id])->get()->toArray();
Eloquent prevents the construction of the collection and the hydration of individual model objects and directly returns an array or eloquent first hydrates the collection and the model objects and then converts everything into an array (thus doing an extra operation)?
If the answer was the second, how can I get the first behavior with eloquent?
I specify with eloquent because it would be nice to be able to do this by continuing to refer in an abstract way to the entities without then mentioning specific database features in the code (for example the name of the tables).
Answering both your questions. The second one will happen. And you can't make Eloquent create an array, you can just convert an object or collection to an array.
Also, your query has a lot of redundant code, you could just do this:
Ad::with('nominations')->find($id)->toArray()

How to use eager loading with custom query builder in Laravel

I am new to Laravel 5.4 and working on some query manipulation. Now I have created an query using query builder which is shown below:
$view = DB::table('blocks')
->leftjoin('programmes', 'blocks.programme_id', '=', 'programmes.id')
->select('blocks.id', 'blocks.programme_id', 'blocks.name', 'blocks.colour', 'blocks.year', 'programmes.title AS programme');
I have two more table "dates" and "modules". Each dates as well as module belongs to blocks.
Now I want to fetch all blocks with programmes, dates and modules. I know i can use with() method to get all of these. But as per my knowledge on Laravel, I can use with() method only if I have model file of each table and have relationship between them.
But do not want to use model and define relationship between them. I just want to know How can I get block data with programmes, dates and modules without creating model and defining relationship betwen them in model? Is there any other way to use with() method without model?
Block dates and modules are conditional, Sometime I dont want get data of this table with block.
Please help me on this.
You can't do it automatically. Eager loading is only for Eloquent model so you cannot use it with query builder. However in most cases you can use Eloquent also for getting more complicated queries (you can also use joins when using Eloquent) so you will be able to use eager loading.
But if you don't want to use Eloquent at all, obviously you will need to create some custom mechanism for eager loading.

Laravel not returning join query to blade

I have two queries, one is lighter on data by using the pivot table as a filter to get data from the main table (student in this case).
$students=\DB::table('student')->join('school_student', 'student.id', '=','school_student.student_id')->get();
This returns a query result from the controller. But will not load into the blade:
$this->layout->content=\View::make('admin.students.index')->with('student', $students);
Whereas this versions returns a similar more data heavy (i.e. outputs all school data each time)
but works in blade.
$students = \Student::with(array('schools' => function($query){$query->where('school_id', '=', 1);}))->get();
Is it simply that DB and view are incompatible?
If so what is the Laravel 4 method to query one table and it's pivot only.
Any help appreciated.
In the blade
#if($student->count())
The first example produces this error:
Call to a member function count() on a non-object
DB::...->get() returns an array, so you can't call ->count() on it (hence "non-object"), but instead you need count($students).
The reason ->count() works when you do the 'more data heavy' method is that you're using Eloquent and it returns Eloquent Collections.
So, basically, you're doing two different things and expecting to treat them the same.
Also, while I'm here I should point out that I think your Eloquent query isn't quite right. First off you're hardcoding the id as 1 (whereas in the DB-style query you don't care about the school ID, and you just use it to join to the pivot table - maybe you used an incomplete query), but also you're using with but you should probably look at has. with eager-loads models, but has is what you want if you just want to check for a condition on a join table.

Resources