How can I convert native PHP7 into query eloquent Laravel? - laravel

I'm migrating from php 7 to laravel and am having trouble completing the query. how to solve data query like the example below
$year = date('Y');
$month = date('m');
select id, tglupload,
substring(CONVERT(varchar,tglupload,106),4,2) date,
COUNT(1) as Totalemployeall
from [MS_SK]
where substring(CONVERT(varchar,tglupload,106),4,2) = $month
and substring(CONVERT(varchar,tglupload,106),7,4) = $year
AND (status_allow <> 'NOTALLOW' OR status_allow is null)
GROUP BY rollup(id, tglupload)
order by id ASC

Unfortunately you have to use a raw query for that. But you can make your query nicer using the Laravel's scope function.
For example in your model (the model related with the table [MS_SK]) you can add the following 2 scope functions:
class YourModel extends Model {
public function scopeFiltrateTglUpload($query, int $month=null, int $year=null)
{
$year = $year ?? date('Y');
$month = $month ?? date('m');
return $query->where(\DB::raw("substring(CONVERT(varchar,tglupload,106),4,2)", "=", $month))
->where(\DB::raw("substring(CONVERT(varchar,tglupload,106),7,4)", "=", $year));
}
public function scopeTheStatusIsNullOrNotAllowed($query)
{
return $query->where(function($subQuery) {
$subQuery->where('status_allow', '<>', 'NOTALLOW')
->orWhereNull('status_allow');
});
}
}
Then you can use them as per below:
$result = YourModel::selectRaw('
`id`, `tglupload`,
substring(CONVERT(varchar,tglupload,106),4,2) `date`,
COUNT(1) as `Totalemployeall`
')
->filtrateTglUpload()
->theStatusIsNullOrNotAllowed()
->groupBy(\Db::raw('rollup(id, tglupload)'))
->orderBy('id')
->get();
Please note that this is just an example to give you an idea. Then you should make it work :) Please tell me in the comment if you need any help.

Related

How i can write this query in laravel?

I need help for this query in laravel
$forums = \DB::select('SELECT * FROM forums
WHERE category = '.$f.' &&
(community = "'.$c.'" || community = "xx")
ORDER BY id ASC');
But how i can write this with laravel sytaxt?
$forums = Forums::where()
Try this way
$forums = Forum::where("category", $f)
->where(function($query) use($c) {
$query->where("community", $c)
->orWhere("community", "xx");
})
->orderBy("id", "ASC")
->get();
By default, Laravel is assuming that the database table is the plural form of the model name.
I think your Model is Forum not Forums.
Try this :
$forums = Forum::where("category", $f)
->where(function($query) use($c) {
$query->where("community", $c)
->orWhere("community", "xx");
})
->orderBy("id", "ASC")
->get();

Laravel select * where id =(select id )

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();

Alias name in having clause in laravel 5.1

I'm using a function which is using alias name in "HAVING" clause and I'm getting an error,
"Unknown column 'orderStatusWithoutOpen' in 'having clause'".
Here is my code:
public static function getEquipmentPaginated($conditions = false, $id = false,$orderby='equipment_no',$order='asc',$filter=false)
{
$equipment = Equipment::select('checklist.*');
$equipment->leftjoin('checklist','equipment_id','=','equipment.id');
$equipment->addSelect('equipment.*', DB::Raw("(SELECT count(ordre.status = 001) FROM ordre LEFT JOIN checklist ON checklist.ordre_id=ordre.id WHERE checklist.equipment_id=equipment.id and ordre.status = 001 order by ordre.start_date desc limit 1) AS orderStatusWithoutOpen"));
$equipment->groupBy('equipment.id');
$start = date('Y-m-d');
$end = date('Y-m-d', strtotime('+15days'));
if($filter == '1' && $filter != "") {
$equipment->having('orderStatusWithoutOpen', "<", $filter);
}
if($filter == $start) {
$equipment->whereBetween('certificate.valid_date', [$start, $end]);
}
if($id) {
$equipment->where('equipment.customer_id', '=', $id);
}
return $equipment->paginate(10);
}
Can anyone please tell me what mistake I'm making here.
Thanks in advance.
Actually I corrected this myself. The query is working good and problem is with the pagination. So what I did is, I return the result within the if condition where I'm using 'HAVING' clause. Like Mentioned below:
if($filter == '1' && $filter != "")
{
$equipment->having('orderStatusWithoutOpen', "<", $filter);
return $equipment->get();
}
You have to bring the value in select query on which you want to order the result.
For example if equipment_fabricat.fabricat_name THEN
get that value in select(equipment_fabricat.fabricat_name) before applying order by

Laravel where in query [duplicate]

This question already has answers here:
How to do this in Laravel, subquery where in
(12 answers)
Closed 7 years ago.
How would I do this with Laravel?
SELECT movie.title
FROM movie
WHERE movie.id IN
(SELECT session.movie_id FROM session WHERE session.id = :id and date = :date)
Use DB::raw to run raw queries
$query = DB::select(DB::raw("select movie.title
FROM movie
where movie.id in
(select session.movie_id from session where session.id = $id and date = $date);"));
return $query;
You can make use of laravel's advanced-wheres:
$movie = Movie::whereIn('id', function($query) use ($id, $date) {
$query->select(DB::raw('session.movie_id'))
->from('session')
->whereRaw('session.id = ? and session.date = ? array($id, $date));
})
->get();
First off you will need a database with movies and sessions tables and two models in Laravel.
Movie Model
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Movie extends Model {
protected $fillable = ['title'];
public function sessions()
{
return $this->hasMany('App\Session');
}
}
?>
Session Model
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Session extends Model {
public function movies()
{
return $this->belongsTo('App\Movie','movie_id');
}
?>
The query in your Controller would have a method like.
public function show($id)
{
try {
$movie = Movie::with('sessions')->where('id',$id)->firstOrFail();
}
catch(ModelNotFoundException $exception)
{
abort(404);
}
return view('movies.show')->withMovie($movie);
}
However you use laravel ORM, it will generate more than one query, i would recommend you to just query in session table first and get the list, then use that result in your wherein query in movie model.
$query = "select movie.title from movie where movie.id IN ( SELECT session.movie_id FROM session WHERE session.id ='".$id."' and date = '".$date."' );
$resultSet = DB::select($query);
Hope this helps.
Use Left Join.
For example,
$first = DB::session('movie.title')->leftjoin('session','session.movie_id','=','movie.id')->where('session.id', '=', $id)->where('session.date','=','$date')->get();
To check results,
dd(first);
Hope this helps.
$query = "SELECT movie.title
FROM movie
WHERE movie.id IN
(SELECT session.movie_id FROM session WHERE session.id = ? and date = ?)";
$movie = \DB::select($query, [$id, $date]);
Using LEFT JOIN is a good option for optimized code. Otherwise Check the below explanation.
The following line of code will generate the query to fetch the movie id's. Using "toSql()" method will return the query instead of result.
$movie_id_qry = DB::table('session')->select('session.movie_id')->whereRaw('session.id = '. $id .' && date = '. $date)->toSql();
This query can be included to fetch the movie title likewise:
$movie_title = DB::table('movies')->where('movie.id', '=', $movie_id_qry)->pluck('movie.title');
For result : echo $movie_title;
The "pluck()" method will return only the title column if match found.
To retrieve the entire row use the "get()" method instead of "pluck()".
As the "toSql()" method will only generate the query, the combined DB fetching only happens in the second line of code.
Hope this is helpful.
DB::table('movies')
->select(
movies.title,
DB::raw(
'(select session.movie_id from session where session.id = id AND date = date') as movie_id'
)
)->where('movies.id','movie_id')get();

Laravel how do I get the row number of an object using Eloquent?

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();

Resources