There are first_name, mid_name and last_name fields in my model. And I am receiving 2 fields (name, last_name) with POST request. I am sure last_name will be there for sure, but I want to be able to compare first_name or mid_name with name.
The issue here is, I don't want to repeat myself but I couldn't figure out a cleaner way.
$query = User::where('last_name', $request->last_name);
if ($request->name) {
$query = $query->where('first_name', $request->name);
}
$result = $query->get();
If I chain, ->orWhere('mid_name', $request->name) inside the if statement, I will end up repeating myself for rechecking for last_name.
I tried dividing this line:
$query = User::where('last_name', $request->last_name);
to this but it doesn't find even the last_name (probably because I am accessing the class?):
$query = User::class;
$lastnameQuery = $query->where('last_name', $request->last_name);
How would you approach a scenario like this to achieve it in a clean way?
Using a orWhere it could be done easily, for example:
$query = User::where('last_name', $request->last_name);
if ($request->name) {
$query = $query->where(function($query) use ($request) {
$query->where('first_name', $request->name)
->orWhere('mid_name', $request->name);
});
}
$result = $query->get();
The closure is required here to separately apply the orWhere only on the first_name and mid_name, so the pseudo query would be something like this:
WHERE last_name = 'doe' AND (first_name = 'john' OR mid_name = 'john')
Related
I have a table name "warga" , the table consist:
id (primary key), no_card, name, description. The no_card is a group from some id.
Then, I will count the description based on no_card.
This is the SQL code :
-SQL code :
SELECT description, COUNT(description) as cnt
FROM ( SELECT distinct no_card, description FROM `warga` ) as t
GROUP by description ;
the SQL already show the data that I need, then in the laravels :
$data = DB::table('warga')->selectRaw('description , COUNT(description ) AS CountData')
->select('no_card', 'description')->distinct()->from('warga')
->groupby('description')
->get();
When I run the program, the alis table CountData is not detected,
Do you have suggestion to fix it?
Thank you,
You can use subquery tables as closures or passing them as builder objects.
DB::table(Closure, alias) or DB::query()->from(Closure, alias)
DB::table(Builder, alias) or DB::query()->from(Closure, alias)
$subquery = DB::table('warga')
->select('no_card', 'description')
->distinct();
$results = DB::table($subquery, 't')
->select('description')
->selectRaw('count(description) as cnt')
->groupBy('description')
->get();
$results = DB::table(function ($query) {
$query->from('warga')
->select('no_card', 'description')
->distinct();
}, 't')
->select('description')
->selectRaw('count(description) as cnt')
->groupBy('description')
->get();
You can even make the query look very SQL-like if you want.
$query = DB::query()
->select('description')
->selectRaw('count(description) as cnt')
->from(function ($sub) {
$sub->select('no_card', 'description')
->distinct();
}, 't')
->groupBy('description')
->get();
I would like to LIKE search.
If 'product' column has "AQ" string display data.
I wrote below code but I couldn't get any record.
Could you teach me right code please?
public function w_mo_fb_m()
{
$word = "AQ";
$images = ImageGallery::where('product', 'like', "%$word%")->orderBy('id', 'desc')->get();
return view('w_mo_fb_m',compact('images'));
}
How about try this.
where('product', 'LIKE', '%'.$word.'%')
//or
where('product', 'LIKE', "%{$word}%")
If this still not working you may need to run raw SQL to see if you can get any record. (you need to replace ImageGallery with your actual table name)
DB::select('select * from ImageGallery where product LIKE = ?', ['%'.$word.'%']);
I am using laravel eager loading to load data on the jquery datatables. My code looks like:
$columns = array(
0 => 'company_name',
1 => 'property_name',
2 => 'amenity_review',
3 => 'pricing_review',
4 => 'sqft_offset_review',
5 => 'created_at',
6 => 'last_uploaded_at'
);
$totalData = Property::count();
$limit = $request->input('length');
$start = $request->input('start');
$order = $columns[$request->input('order.0.column')];
$dir = $request->input('order.0.dir');
$query = Property::with(['company','notices']);
$company_search = $request->columns[0]['search']['value'];
if(!empty($company_search)){
$query->whereHas('company', function ($query) use($company_search) {
$query->where('name','like',$company_search.'%');
});
}
$property_search = $request->columns[1]['search']['value'];
if(!empty($property_search)){
$query->where('properties.property_name','like',$property_search.'%');
}
if(!Auth::user()->hasRole('superAdmin')) {
$query->where('company_id',Auth::user()->company_id);
}
$query->orderBy($order,$dir);
if($limit != '-1'){
$records = $query->offset($start)->limit($limit);
}
$records = $query->get();
With this method I received error: Column not found: 1054 Unknown column 'company_name' in 'order clause' .
Next, I tried with following order condition:
if($order == 'company_name'){
$query->orderBy('company.name',$dir);
}else{
$query->orderBy($order,$dir);
}
However, it also returns similar error: Column not found: 1054 Unknown column 'company.name' in 'order clause'
Next, I tried with whereHas condition:
if($order == 'company_name'){
$order = 'name';
$query->whereHas('company', function ($query) use($order,$dir) {
$query->orderBy($order,$dir);
});
}else{
$query->orderBy($order,$dir);
}
But, in this case also, same issue.
For other table, I have handled this type of situation using DB query, however, in this particular case I need the notices as the nested results because I have looped it on the frontend. So, I need to go through eloquent.
Also, I have seen other's answer where people have suggested to order directly in model like:
public function company()
{
return $this->belongsTo('App\Models\Company')->orderBy('name');
}
But, I don't want to order direclty on model because I don't want it to be ordered by name everytime. I want to leave it to default.
Also, on some other scenario, I saw people using join combining with, but I am not really impressed with using both join and with to load the same model.
What is the best way to solve my problem?
I have table like: companies: id, name, properties: id, property_name, company_id, notices: title, slug, body, property_id
The issue here is that the Property::with(['company','notices']); will not join the companies or notices tables, but only fetch the data and attach it to the resulting Collection. Therefore, neither of the tables are part of the SQL query issued and so you cannot order it by any field in those tables.
What Property::with(['company', 'notices'])->get() does is basically issue three queries (depending on your relation setup and scopes, it might be different queries):
SELECT * FROM properties ...
SELECT * FROM companies WHERE properties.id in (...)
SELECT * FROM notices WHERE properties.id in (...)
What you tried in the sample code above is to add an ORDER BY company_name or later an ORDER BY companies.name to the first query. The query scope knows no company_name column within the properties table of course and no companies table to look for the name column. company.name will not work either because there is no company table, and even if there was one, it would not have been joined in the first query either.
The best solution for you from my point of view would be to sort the result Collection instead of ordering via SQL by replacing $records = $query->get(); with $records = $query->get()->sortBy($order, $dir);, which is the most flexible way for your task.
For that to work, you would have to replace 'company_name' with 'company.name' in your $columns array.
The only other option I see is to ->join('companies', 'companies.id', 'properties.company_id'), which will join the companies table to the first query.
Putting it all together
So, given that the rest of your code works as it should, this should do it:
$columns = [
'company.name',
'property_name',
'amenity_review',
'pricing_review',
'sqft_offset_review',
'created_at',
'last_uploaded_at',
];
$totalData = Property::count();
$limit = $request->input('length');
$start = $request->input('start');
$order = $columns[$request->input('order.0.column')];
$dir = $request->input('order.0.dir');
$query = Property::with(['company', 'notices']);
$company_search = $request->columns[0]['search']['value'];
$property_search = $request->columns[1]['search']['value'];
if (!empty($company_search)) {
$query->whereHas(
'company', function ($query) use ($company_search) {
$query->where('name', 'like', $company_search . '%');
});
}
if (!empty($property_search)) {
$query->where('properties.property_name', 'like', $property_search . '%');
}
if (!Auth::user()->hasRole('superAdmin')) {
$query->where('company_id', Auth::user()->company_id);
}
if ($limit != '-1') {
$records = $query->offset($start)->limit($limit);
}
$records = $query->get()->sortBy($order, $dir);
Using Laravel eloquent how do I make a query like this:
select * from branches where user_id =(select id from users where name ='sara' )
Assuming that you have a user relationship in your Branch model you could use whereHas:
$branches = Branch::whereHas('user', function ($query) {
$query->where('name', 'sara');
})->get();
Update
If you're using v8.57.0 or above, you can now use the whereRelation() method instead:
Branch::whereRelation('user', 'name', 'sara')->get();
$id = Users::select('id')->where('name','sara')->first();
$barnches = branches::where('id',$id)->get();
Here Users and branches are models , first is using for 1 row and get for many rows
I would split it into two queries. First getting the id, then getting the list. Expecting your models to be called "User" and "Branches"
$user = User::where('name', 'sara');
$id = $user->id;
$branches = Branch::where('id', $id);
This site may help you Link
Try this.
$name = 'sara';
$results = BranchModel::whereIn("user_id", function ($query) use ($name) {
$query->select("id")
->from((new UserModel)->getTable())
->where("name", $name);
})->get();
You can use this:
$users = User::whereName("sara")->get()->pluck('id');
Branch::whereIn('user_id',$users)->get();
I'd like to know the position of a user based on its creation date. How do I do that using Eloquent?
I'd like to be able to do something like this:
User::getRowNumber($user_obj);
I suppose you want MySQL solution, so you can do this:
DB::statement(DB::raw('set #row:=0'));
User::selectRaw('*, #row:=#row+1 as row')->get();
// returns all users with ordinal 'row'
So you could implement something like this:
public function scopeWithRowNumber($query, $column = 'created_at', $order = 'asc')
{
DB::statement(DB::raw('set #row=0'));
$sub = static::selectRaw('*, #row:=#row+1 as row')
->orderBy($column, $order)->toSql();
$query->remember(1)->from(DB::raw("({$sub}) as sub"));
}
public function getRowNumber($column = 'created_at', $order = 'asc')
{
$order = ($order == 'asc') ? 'asc' : 'desc';
$key = "userRow.{$this->id}.{$column}.{$order}";
if (Cache::get($key)) return Cache::get($key);
$row = $this->withRowNumber($column, $order)
->where($column, '<=',$this->$column)
->whereId($this->id)->pluck('row');
Cache::put($key, $row);
return $row;
}
This needs to select all the rows from the table till the one you are looking for is found, then selects only that particular row number.
It will let you do this:
$user = User::find(15);
$user->getRowNumber(); // as default ordered by created_at ascending
$user->getRowNumber('username'); // check order for another column
$user->getRowNumber('updated_at', 'desc'); // different combination of column and order
// and utilizing the scope:
User::withRowNumber()->take(20)->get(); // returns collection with additional property 'row' for each user
As this scope requires raw statement setting #row to 0 everytime, we use caching for 1 minute to avoid unnecessary queries.
$query = \DB::table(\DB::raw('Products, (SELECT #row := 0) r'));
$query = $query->select(
\DB::raw('#row := #row + 1 AS SrNo'),
'ProductID',
'ProductName',
'Description',
\DB::raw('IFNULL(ProductImage,"") AS ProductImage')
);
// where clauses
if(...){
$query = $query->where('ProductID', ...));
}
// orderby clauses
// ...
// $query = $query->orderBy('..','DESC');
// count clause
$TotalRecordCount = $query->count();
$results = $query
->take(...)
->skip(...)
->get();
I believe you could use Raw Expresssions to achieve this:
$users = DB::table('users')
->select(DB::raw('ROW_NUMBER() OVER(ORDER BY ID DESC) AS Row, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
However, looking trough the source code looks like you could achieve the same when using SQLServer and offset. The sources indicates that if you something like the following:
$users = DB::table('users')->skip(10)->take(5)->get();
The generated SQL query will include the row_number over statement.
[For Postgres]
In your model
public function scopeWithRowNumber($query, $column = 'id', $order = 'asc'){
$sub = static::selectRaw('*, row_number() OVER () as row_number')
->orderBy($column, $order)
->toSql();
$query->from(DB::raw("({$sub}) as sub"));
}
In your controller
$user = User::withRowNumber()->get();