laravel 5.4 bitwise operations not working as expected (Eloquent) - laravel

This has me stumped. I'm trying to filter $ages=Ages::all(); based on a productmask field using bitwise operator &
(code should be self-explanatory)
I've tried
#foreach($ages->where('productmask', '&', 2) as $option)
and
#foreach($ages->filter(function($i){return ((int)($i->productmask & 2)); }) as $option)
and
#foreach($ages->filter(function($i){return ((int)($i->productmask & 2) == 2); })->values() as $option)
and none work when productmask = 3 but do work when productmask is exactly 2.
What are my options here (no pun intended)? Why doesn't this work?
I'm pretty sure it would work if I did a \DB::whereRaw (because I can run this against the Db and it works and I get the 2 and 3 entries):
SELECT * from ages WHERE productmask&2
but here it's bypassing fluent and hitting the database inside a view?? Not good form.
Anyone using bit masks out there ever run into this?
thanks in advance.

Well, I don't know why I had to do this exactly, but here's what i did to get it to work:
#foreach($locations->filter(function($i){if (decbin($i->productmask) & 16) return $i; }) as $option)
Basically, I had to use decbin() on the collection's field value ($ages->productmask) so that the compare would resolve correctly.
Works now! Hope this helps someone.

From the source here suggests that
where() takes 3 parameters, name of the column, operator and value to
be compared against.
The operator can be one of the following: '=', '<', '>', '<=', '>=',
'<>', '!=', 'like', 'not like', 'between', 'ilike'
However I found something that you might need to look here.
This will help you to fix your issues.
For further digging see PHP documentation also read this SO post
and as far as your question is concerned
use your query like this
$ages->whereRaw('(productmask & 2)')

Related

Add extra column to laravel select query

It may sound as a duplicate question. Please I have not found a working solution.I want to add additional field to my query in laravel but I am getting error. This is the php implementation
select id, "extra_column as type" from cases
have tried
DB::table('cases')
->select(['id'])
->selectSub(function($query){
$query->selectRaw('extra_column');
},'type')
->get();
but I keep getting error
You need to use like this:
DB::table('cases')
->select(['id', 'extra_column as type'])
->get();
Please try addSelect('extra_column as type').
DB::table('cases')
->select(['id'])
->addSelect(`<additional column>`) // We can able to use variable as well $value = 'extra_column as type';
->get();
I later found out the solution. the extra_column was missing a double quote
DB::table('cases')
->select(['id'])
->selectSub(function($query){
$query->selectRaw('"extra_column"');
},'type')
->get();
You can find that scenario in Laravel docs like so,
$query = DB::table('users')->select('name');
$users = $query->addSelect('age')->get();
OR you can do something like this also:
DB::table('users')->select('name')
->addSelect('email as user_email');
and in case this triggers an issue as you told, please make sure that this column exists in your database.

Where with a greater than option in Laravel

i have a filter function and if i select the number 3 it should show me also the tests with the number 1 and 2
so i need a multiple "where" who shows me all tests with the number who are less than 3
i tried something like this:
$tests = DB::table('tests')->orderBy('name', 'asc')-where('number', < 3)->get();
it shows me that is not possible but is there a right laravel syntax to do something like this?
i cant find anything about it
because i always use where('number', 1) so like this
Your condition is not correct, so change it to:
where('number', '<=', 3) // '<=' for 1,2,3. If you want only 1,2 try '<'
and there is an issue here:
-where
change it to:
->where
and try again.
You need to use less than mark as a string ('<') as a 2nd param and value as a 3rd param. For example:
$tests = DB::table('tests')->orderBy('name', 'asc')->where('number', '<', 3)->get();
If you use equal to ('=') mark you can use value as a 2nd param.
You can get detail knowledge from below link with multiple examples
https://laravel.com/docs/5.7/queries#where-clauses
$selected_number = '3';
$tests = DB::table('tests')->where('number', '<=', $selected_number)->orderBy('name', 'asc')->get();

Laravel Sorting Data with Relationship and Pagination

I need sorting the Records data according to Relationship.
I am trying below Query.
$data = Lead::with('bdm', 'status_code', 'bdm.bdm')->get()->sortByDesc('bdm.bdm.name');
It works fine but I need data with pagination which is giving by Laravel 5 by default.
So If I am trying with below query . It is giving error.
$data = Lead::with('bdm', 'status_code', 'bdm.bdm')->pagination(20)->sortByDesc('bdm.bdm.name');
I am trying an other way to do the same task. It works fine but it is not sorting the records.
$data = Lead::with(['bdm','status_code', 'bdm.bdm' => function ($query) {
$query->orderBy('name', 'desc');
}])->paginate(20);
So kindly can anyone give me solution how to adjust this query.
Any Help will be appreciated.
Thanks
You should be using a join statement to do that.
If I were to assume your column names it should look something like this:
$data = Lead::with(['status_code', 'bdm.bdm'])
->join('bdms', 'bdms.id', '=', 'leads.bdm_id')
->orderBy('bdms.name', 'desc')
->paginate(20);
And the first bdm parameter in your query is redundant. It will be handled during bdm.bdm anyway.

Getting last element of the Collection

guys, I'm trying to get the last element from the data returned to me but the problem is that it is throwing me an error which is
Call to undefined method Illuminate\Database\Query\Builder::last()
Here is my code
$last_saved_snapshot = \EnginePerformanceTestSnapshot::where('engine_performance_test_id', $id)->last();
Please tell me what is it that I'm doing wrong. Thanks
P.S I'm using Laravel 5.0
Try something like that:
$last_saved_snapshot = \EnginePerformanceTestSnapshot::where('engine_performance_test_id', $id)
->get()
->last();
The last method call is not working because namespace Illuminate\Database\Eloquent; does not have any last() method. The right way to do this is to do something like this:
$last_saved_snapshot = EnginePerformanceTestSnapshot::query()
->where('engine_performance_test_id', $id)
->orderBy('id', 'desc')
->first();
Otherwise, you need to get all items, since last() is part of the collection class so it expects a collection or array to be able to work and not a query builder. It is less efficient and a bad practice to fetch all data just for one.
I found another way to do it and that is:
$last_saved_snapshot = \EnginePerformanceTestSnapshot::where('engine_performance_test_id', $id)->orderBy('id', 'desc')->first();
This is working but if somebody can tell me why is the last not working then that would be a great help. Thanks
Try this, less code:
\EnginePerformanceTestSnapshot::
where('engine_performance_test_id', $id)
->latest()
->first();

Working with Eloquent, How to select popular comments

I am designer trying to learn coding here and Laravel is so great in that it enables design like me to be able to create something myself smile
On to my question, I followed some of tutorial and now I learn to build simple blog system.
So I have Post model that has relationship $this->morphMany('Like','likeable','likeable_type'); with Like model.
Everything works great so far. Now I want to be able to create 'Popular Posts' page that basically shows the posts ordered by popularity, which is number of likes in my case.
The 'likes' table has these field id | likable_id | likeable_type
'likeable_type', in this case, is 'Post'
'likeable_id' is the post id linked to id in 'posts' table
So in my controller, I tried this.
$popular_ids = DB::table('likes')
->select('likeable_id')
->groupBy('likeable_id')
->orderBy(DB::raw('COUNT(likeable_id)'), 'DESC')
->get();
$popular_posts = Post::whereIn('id',array_pluck($popular_ids,'likeable_id'))->paginate(15);
This gives me all the popular posts but not in the order that I want.
I'm not sure if there is better way to achieve this or it seems that I only miss another 'orderBy' method?
Any suggestion on this?
ps. Sorry for my poor English
SQL IN does not maintain order. To achieve this have to user ORDER BY FIELD('id', , ,...) to achieve this.
$ids = array_pluck($popular_ids,'likeable_id');
$raw = DB::raw('FIELD(id,' + implode(',', $ids) + ')');
$popular_posts = Post::whereIn('id', $ids)->orderBy($raw)->paginate(15);
For more information refer to,
Maintaining order in MySQL "IN" query
I would do this with a join. It's kinda complex but if you want to understand the internals you should read into LEFT JOIN and INNER JOIN. This example is particularly ugly because of the polymorphic relationship.
Post::select('posts.*', DB::raw('COUNT(DISTINCT likes.id) AS popularity'))
->leftJoin('likes', function ($join)
{
$join->on('likes.likeable_id', '=', 'posts.id')
->on('likes.likeable_type', '=', DB::raw("'Post'"));
})
->orderBy('popularity', 'DESC')
->paginate(15);
There is a bonus in that the popularity value is now available on the posts.
$post->popularity;
Thank you Collin for your time! Your answer leads me to the light!!! I modified your answer a bit and finally get what I need. I'm still trying to fully understand it though. This is what I ended up with.
Post::select('posts.*', DB::raw('COUNT(likes.likeable_id) AS popularity'))
->join('likes', function($join)
{
$join->on('likes.likeable_id', '=', 'posts.id')
->on('likes.likeable_type', '=', DB::raw("'Post'"));
})
->groupBy('likes.likeable_id')
->orderBy('popularity', 'DESC')
->paginate(15);
Ps. Even though this code gives me what I want, I'm not sure if I did my db design right.

Resources