Eloquent ORM does not allow ? operator used in JSONB lookup - laravel

Is it possible to run this postgres query with Eloquent ORM?
select * from "table" where "column"->'key' ? '1'
It throws error for using ? in the query. Is there any alternative approach?

You can use jsonb_exists function. All question marks determines as placeholder for prepared statements.
Or in php 7.4 you can use ?? (answer here: How to use Postgres jsonb '?' operator in Laravel with index support?)

Use a raw query instead:
DB::raw(" select * from \"table\" where \"column\"->'key' ? '1' ");

Related

Laravel Eloquent 'WITH' statement query

How to convert this mysql query to Eloquent
with wmh as (select * from whatsapp_message_histories ORDER BY created_at LIMIT 1)
select DISTINCT whatsapp_histories.*, wmh.created_at from whatsapp_histories
left join wmh on wmh.whatsapp_history_id = whatsapp_histories.id
ORDER BY wmh.created_at
Please Help me, thanks a lot!
(Edited)
My Problem is, I have Eloquent Model whatsapp_histories, has a relation to whatsapp_message_histories (using hasMany). My Objective is need to display whatsapp_histories order by whatsapp_message_histories.created_at. (This is eloquent, because i need to display other whatsapp_histories's relation). I can solve it in native way, but not in eloquent, but i'm not allowed to change the previous eloquent code
Try this:-
whm::with('whatsapp_histories',function($join){
$join->on('wmh.whatsapp_history_id','=','whatsapp_histories.id');
$join->orderBy('whatsapp_histories.created_at','ASC');
$join->limit(1);
})->orderBy('wmh.created_at','ASC)->get();

How can I write this query using the laravel query builder?

I'm on laravel 5.1 using postgres as the DB. I have a fiddle here in case it helps understand my issue: https://www.db-fiddle.com/f/5ELU6xinJrXiQJ6u6VH5/4
with properties as (
select
properties.*,
json_agg(property_fields.*) as property_fields
from
properties
left join fields as property_fields
on property_fields.parent = 'property' and property_fields.parent_id = properties.id
group by properties.id, properties.deal_id, properties.address
)
select
deals.*,
json_agg(properties.*) as deal_properties,
json_agg(deal_fields.*) as deal_fields
from deals
left join properties on deals.id = properties.deal_id
left join fields deal_fields on deal_fields.parent = 'deal' and deal_fields.parent_id = deals.id
group by deals.id, deals.name
order by deals.id
Writing most of this is fairly straight forward. The problem I'm having is with the with properties as (...) block. I've tried something like:
DB::statement('WITH properties AS ( ... )')
->table('deals')
->select(' deals.*, json_agg(properties.*) as deal_properties, ')
...
->get();
But I notice the execution stop after DB::statement()
Is there a method in the Query Builder that I'm missing? How can I prefix my query with the WITH properties AS (...) statement?
I think it should also be noted that I'm trying to implement a Repository Pattern and I can't just wrap a DB::statement() around the whole query.
I've created a package for common table expressions: https://github.com/staudenmeir/laravel-cte
$query = 'select properties.*, [...]';
DB::table('deals')
->withExpression('properties', $query)
->leftJoin([...])
->[...]
You can also provide a query builder instance:
$query = DB::table('properties')
->select('properties.*', [...])
->leftJoin([...])
->[...]
DB::table('deals')
->withExpression('properties', $query)
->leftJoin([...])
->[...]
if you want some data fetch from a table you can use this type of code
$user = DB::table('table name')->where('name', 'John')->where('height','!>',"7")->select('table fields which you want to fetch')->get();
Or try using the larevel Eloquent ORM which will make things easier with the database.
for more example or reference
https://laravel.com/docs/5.0/queries
I think you can actually do this with eager loading,
assuming that the relationships are set up correctly.
(More reading here: https://laravel.com/docs/5.4/eloquent-relationships#constraining-eager-loads)
So I think you'd be able to add something like
->with(['properties' => function ($query) {
$query->select('field')
->leftJoin('join statement')
->groupBy('field1', 'field2');
}])

laravel return '?' instead of '1' in WHERE clause

$datas=Elan::orderBy('created_at','desc')->where('status', 1)->take(4)->toSql();
dd($datas);
I wrote query in "laravel 5.2". I displayed it as sql query with function toSql()
and the result is:
"select * from `els` where `status` = ? order by `created_at` desc limit 4"
you can see that there is ? mark. this is why my query doesn't work. why does it return me ? instead of one. I also tried it like this '1' same result.
You may want to read about bindings if you want to understand what does ? mean.
https://laravel.com/docs/5.3/database#running-queries
If you want to debug and watch queries, you can install this debugbar: https://github.com/barryvdh/laravel-debugbar
? is used for Parameter binding which prevent against SQL injection.
If you want to see the raw SQL query which is executed with parameters values, try the below code:
DB::enableQueryLog();
$datas=Elan::orderBy('created_at','desc')->where('status', 1)->take(4)->get();
dd(DB::getQueryLog());
Hope this helps!

Laravel Query Builder: whereExists translates condition clause to question mark

If I have the following query built using the Query Builder:
$q = DB::table('Products')->whereExist(function ($q)
{
$q->select(DB::raw(1))
->from('tags_products')
->where('products.PorductId', '=', 'tags_products.ProductID');
});
The translated SQL using $q->toSql(); that is:
select * from `Products` where `exist` = (select 1 from `tags_products` where `products`.`ProductID` = ?)
Apparently, the Query Builder translates tags_products.ProductID to ?.
Why does it become "?" ?
As #Jared Eitnier very well pointed out, Laravel uses PDO to bind the parameters you pass to the Query Builder methods. However, because when you use where the third parameter represents the value, Laravel will not treat it as a column unless you explicitly tell it to, otherwise it will treat 'tags_products.ProductID' as a regular string value. So you have two options here:
1. Use DB::raw() to let the Query Builder know that the value is not a string that requires escaping:
->where('products.PorductId', '=', DB::raw('tags_products.ProductID'));
2. Use whereRaw() which will allow you to write a raw SQL statement:
->whereRaw('products.PorductId = tags_products.ProductID');
These are mysql prepared statements.
See What is the question mark's significance in MySQL at "WHERE column = ?"?
Laravel uses mysql's PDO.

Do I need to wrap strings with '' when using Doctrine update set method?

I am using Doctrine Update query as follow.
$oQuery = Doctrine_Query::create()
->update("Model")
->set("field",$value);
the problem is that if $value is string, I have to ->set("field","'".$value."'");
if it normal? Why can't doctrine do it itself?
am I missing something?
Yes, use proper Doctrine syntax:
...
->update('Model m')
->set('m.field', '?', $value)
...
This old document will tell you all about it:
http://www.symfony-project.org/doctrine/1_2/en/06-Working-With-Data

Resources