Laravel dynamic where queries using Query Builder - php

I am in new in Laravel. I want to make dynamic where queries with laravel query builder.Normally I can make dynamic queries in php
$where = array(
'hello' => 'world'
);
function get($where = null){
if($where == "") $where = "";
//Function which converts where clause into queries
wheretoqueries($where); //converts where clause
$sql = "SELECT * FROM $tbl $where";
return $sql;
}
echo get($where);
If where clause is null queries will be
SELECT * FROM $tbl
If where clause is not null queries will be
SELECT * FROM $tbl WHERE hello = "world"
Laravel orm works fine for where clause if key and value exists
A::where($where)->get();
If where is null following method will not work

You can chain the where queries as:
$query = Model::query();
if (!empty($value)) {
$query->where('column', $value);
}
$query->get();
OR
You can use when method as:
Model::when($value, function ($query) use ($value) {
return $query->where('column', $value);
})
->get();

Try this. If $where variable contain something then the query will execute otherwise it will retrieve all data from A Model.
function get($where = null){
if($where != null){
A::where('field_name', '=', $where)->first();
}else{
A::all();
}
}
Note: if your query return more than one value then you have to use get() method at end of query builder instead of first();
Reference: https://laravel.com/docs/5.3/queries#where-clauses

Related

Turning my raw SQL code in Laravel ORM code vs using it raw

I have a bit of a complicated SQL query that I need to have it on my Laravel web app in order to filter some data.
After a bit of trial and error, I figured out how my SQL query should look (the results are fine in PHPmyadmin).
But now I get some errors when using it in Laravel. I know why, but I don't know should I fix it.
So here's the file that I'm using for filtering:
<?php
namespace App\Filters;
use Illuminate\Database\Eloquent\Builder;
use DB;
use App\Student;
/**
* Class DepartamentFilter
* #package App\Filters
*/
class DoctoranziFilter extends Filter
{
/**
* #param Builder $query
* #return mixed
*/
public function apply($query)
{
if ($this->request->exists('filters')) {
$name = $this->request->get('nume');
if ($name !== null) {
$query = $query->where('nume', 'like', '%' . $name . '%');
}
$an_inmatriculare = $this->request->get('an_inmatriculare');
if ($an_inmatriculare !== null) {
$query = $query->where('an_inmatriculare', 'like', '%' . $an_inmatriculare . '%');
}
$domeniu_doctorat_id = $this->request->get('domeniu_doctorat_id');
if ($domeniu_doctorat_id !== "0") {
$query = $query->where('domeniu_doctorat_id', '=', $domeniu_doctorat_id);
}
$conducator_doctorat_id = $this->request->get('conducator_doctorat_id');
if ($conducator_doctorat_id !== "0") {
$query = $query->where('conducator_doctorat_id', '=', $conducator_doctorat_id);
}
$status = $this->request->get('status');
if ($status !== "0") {
$query = DB::Select("select * from `students`
where (
select status_student.id from `status_student`
WHERE
status_student.id = (SELECT MAX(status_student.id) from `status_student`
WHERE
status_student.student_id = students.id)
AND
status_student.status_id = 6
)
IS NOT NULL;");
}
$stare_stagiu = $this->request->get('stare-stagiu');
if ($stare_stagiu !== "0") {
$query = Student::whereHas('statusuri', function($q) use ($stare_stagiu) {
$q->where('stare_stagiu_id', '=', $stare_stagiu);
});
}
$forma_admitere_id = $this->request->get('forma_admitere_id');
if ($forma_admitere_id !== "0") {
$query = $query->where('forma_admitere_id', '=', $forma_admitere_id);
}
$campOrdonare = $this->request->get('ordonare-dupa-camp');
if($campOrdonare !== "0") {
$ordine = $this->request->get('ordine');
if($campOrdonare === "1")
{
$query = $query->orderBy('nume', $ordine);
}
else
{
$query = $query->orderBy('an_inmatriculare', $ordine);
}
}
return $query;
} else {
$query = $query->where('respins', '=', 0);
return $query;
}
}
}
The problematic part is the query on $status.
From all the others $query variable, I chain a bit of SQL. (like, a where, an order by, etc)
For the $status variable, I don't do that, I'm using raw SQL already and that is why it is not working well.
So, what should I do? Is there any way to somehow turn that DB::Select into a QueryBuilder? (I don't think so, to be honest)
I think that I need to turn that raw SQL into Eloquent but I'm having trouble doing that. I've been trying that for a long time and I couldn't do it.
I have 3 tables that this $status query needs to operate on:
STUDENTS STATUS STATUS_STUDENT
ID ID students.id
status.id
I will explain the query from the code:
"select * from `students`
where (
select status_student.id from `status_student`
WHERE
status_student.id = (SELECT MAX(status_student.id) from `status_student`
WHERE
status_student.student_id = students.id)
AND
status_student.status_id = 6
)
IS NOT NULL;"
6 would be the user input, in this case it is hardcoded for testing purposes
A student can have multiple status - but the active one is the last one that he has. Then I want to check if the student's active status id is equal to the user input (in the case above with 6, it was hardcoded for my tests). If so, return the students which match the criteria. If not, don't return anything. (so, for example, if the student has that status but it is not the active one, don't return anything)
Here's the relationship between Student and Status in code:
public function statusuri()
{
return $this->belongsToMany(Status::class, 'status_student')
->withPivot('id', 'status_id', 'stare_stagiu_id')
->withTimestamps();
}
So, how can I make this query work in my context? (having it chained with QueryBuilders while it being raw SQL). If I am right and I need to turn it into Eloquent code, can anybody help me do it? I couldn't figure it out myself.
Thanks.

laravel raw join query

I have a function that accepts raw where conditions and joins:
query('data',['fieldA','fieldB'], 'fieldA > 10 AND fieldB < 20', 'LEFT JOIN users ON data.user_id = users.id');
function query($table, $keys = [], $where = '', $joins = '') {
$query = DB::table($table)->select($keys);
if(!empty($where)) {
$query=$query->whereRaw($where);
}
if(!empty($joins)) {
$query=$query->?????????????
}
return $query->get();
}
How do I use the raw join with the query builder the way I can use whereRaw for the where condition?
Haven't good smell but works
\DB::table('data')->join('user', function($join){
$join->on(\DB::raw('( `data`.`user_id` = `user.id` or (`data`.`user_id` is null and `data`.`other_field` is null)) and 1 '),'=',\DB::raw('1'));
})
Don't bother with the query builder if you're just using raw expressions on everything.
Option 1: Utilize PDO
PDO is the underlying driver used by Laravel. To get the PDO object, run:
$pdo = DB::connection()->getPdo();
Option 2: Run raw queries
You can run entire selects through Laravel without "building" a query:
DB::select("SELECT * FROM table WHERE ..");
This even allows parameter binding when you need it.
https://laravel.com/docs/5.5/database
Here I have put some idea how can you make your method little bit generic. Do same thing for where clause and other part of the query.
query('data',['fieldA','fieldB'], 'fieldA > 10 AND fieldB < 20', 'LEFT', 'users', 'data.user_id','users.id');
function query($table, $keys = [], $where = '', $join_type = 'LEFT', $join_table='', $join_field1='', $join_field2='') {
$query = DB::table($table)->select($keys);
if(!empty($where)) {
$query=$query->whereRaw($where);
}
if(!empty($joins)&&!empty($join_type)&&$join_type=='LEFT') {
$query=$query->leftJoin($join_table, $join_field1, '=', $join_field2)
}
if(!empty($joins)&&!empty($join_type)&&$join_type=='INNER') {
$query=$query->join($join_table, $join_field1, '=', $join_field2)
}
///and so on
return $query->get();
}
//But you can make this method more generic, I just put some idea so that you can make this method more flexible
//I did not take a look at your other part of the method though.
Note: I did not put multiple joins only two table joins but you can make your method more generic form and more flexible. I just tried to put some idea that comes into my mind. If I am wrong then correct me please.
Reference:
Laravel - Joins
DB::table('data')->join('users','data.user_id','users.id')->where(~~~)

count the not null value using where condition in codeigniter

I am writing a function to count the null column with where condition but there is a problem in this function
protected function _get_mcq_attept_count2( $mcq_id){
$this->load->model('museranswer');
return $this->museranswe>count_by(array('mcq_id'=>$mcq_id,'bookrefrence!='=>" "));
}
this function made the query
SELECT COUNT(*) AS `numrows`
FROM `user_answer`
WHERE `mcq_id` = '321'
AND `bookrefrence` != ' '
this query return the empty column value
I hope this code work for it bcz in code-igniter i always use like this .
protected function _get_mcq_attept_count2($mcq_id)
{
$this->load->model('museranswer');
$where = array('mcq_id'=>$mcq_id);
return $this->museranswe>count_by($where);
}
/******************* FOR MODEL *********************/
public function count_by($where)
{
$this->db->select('count(mcq_id) as numrows');
$this->db->from('user_answer');
$this->db->where($where);
$this->db->where('bookrefrence !=',' ');
$qry = $this->db->get();
return $qry->result_array();
}
Change your query like this array("mcq_id" => "$mcq_id", "bookrefr‌​ence IS NOT NULL" => null). Hope you will get right answer. If it does not work, share your model with us.
return $this->museranswer->count_by(array('mcq_id'=>$mcq_id,'length(bookrefrence)>2'));

How to write conditional query in laravel 5.2?

How can I write this kind of queries in laravel 5.2 eloquent or query builder?
$query = Customers::leftjoin('Query string');
if(condition)
{
//This part added to query
}
else
{
//This part added to query
}
->get();
You have to remember your query in a variable, I.E. like this:
$query = Customers::leftjoin('Query string');
if(condation){
$query = $query->where('something', '=', 'something');
} else {
$query = $query->where('somethingelse', '=', 'somethingelse');
}
$query = $query->get();
Normally you would have $query->where()-get();, which is basically the same thing, $query will hold the result of your ->where() and allows you to chain further on $query

Method Chaining based on condition

How can you do method chaining based on condition in laravel 4 ? Say if one value is not false then the method inside will be chained to the method called before the if statement.
Is it possible in laravel?
$data = User::where('username', $somevariable );
if(isset( $somevar_again ))
{
$data->where('age', 21);
}
$data->orderBy('reg_date', 'DESC')->get();
return $data->first();
// tried code above and its giving me wrong result
in codeigniter I can do this
$this->db->select('e.*, v.name_en as v_name_en')
->from($this->table_name . ' e, ' . $this->ptc_venues . ' v');
$this->db->where('e.venue_id_en = v.id');
if(isset($search)){
$this->db->where('(v.name_en LIKE "%'.$search.'%")');
}
$this->db->limit($limit, $start);
$this->db->order_by('e.added_date_en', 'DESC');
I believe your problem happened because you didn't store back the resulting query after each query builder method call.
$query = User::query();
// Checking for username if exists
if (!empty($username)) {
$query = $query->where('username', $username);
}
// Check for age if exists
if (isset($age)) {
$query = $query->where('age', $age);
}
// Ordering
$query = $query->orderBy('reg_date', 'DESC');
// Get the first result
// After this call, it is now an Eloquent model
$user = $query->first();
var_dump($user);
From Laravel 5.2 and onward, you can utilise Conditional Clauses/Statements:
Sometimes you may want statements to apply to a query only when
something else is true. For instance you may only want to apply a
where statement if a given input value is present on the incoming
request. You may accomplish this using the when method
The when method only executes the given Closure when the first parameter is true. If the first parameter is false, the Closure will not be executed.
You can use the code as follows:
$data = User::where('username', $somevariable)
->when( isset($somevar_again), function ($query) {
return $query->where('age', 21);
})
->orderBy('reg_date', 'DESC')
->get();
return $data->first();
Also, note that Laravel 5.3+, it has further been extended as documented below:
You may pass another Closure as the third parameter to the when
method. This Closure will execute if the first parameter evaluates as
false

Categories