Laravel Eloquent complex where - php

How to convert this code to Laravel (Eloquent):
$query = 'SELECT * FROM posts p WHERE (p.is_public = 1)';
if (isset($date)){ //$date format is '2018-09-01 00:00:00'
$query .= ' AND (p.created_at > "'.$date.'")';
}
if (isset($search)){
$query .= ' AND ((p.title LIKE "%'.$search.'%") OR (p.body LIKE "%'.$search.'%"))';
}

try this:
assume Post is your model
$posts = Post::where('is_public', 1);
if (isset($date)) {
$posts->where('created_at', '>', $date);
}
if (isset($search)) {
$posts->where(function($query) use ($search) {
$query->where('title', 'like', "%'.$search.'%")
->orWhere('body', 'like', "%'.$search.'%");
});
}
$posts = $posts->get();

This is Example code : assume Post is your model
$getPosts=Post::query()->where('is_public',1);
$getPosts->when(isset($date),function($q) use ($date){
$q->where('created_at','>',$date);
});
$getPosts->when(isset($search),function($q) use ($search){
$q->where('title','like','%'.$search.'%');
$q->orWhere('body','like','%'.$search.'%');
});
$posts=$getPosts->get();

You should try this:
$query = Post::where('is_public', '1');
if (isset($date)){ //$date format is '2018-09-01 00:00:00'
$query->where('created_at', '>', $date);
}
if (isset($search)){
$query->whereRaw('title LIKE "%'.$search.'%" OR body LIKE "%'.$search.'%"');
}
$posts = $query->get();

Related

Laravel-5.6 'LIKE' in where select

I use this query and i get a error :
$description = $request->get('description');
if (!empty($description)){
$description_query = Transcationhistorique::where(['sender_id' => $user_id, "%$description%", 'LIKE','description'])
->orWhere('receiver_id', $user_id)->get();
}else{
$description_query = "" ;
}
and this is the error that I get :
"SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'where
clause' (SQL: select * from transcation_historique where
(sender_id = 32 and 0 = %salaire% and 1 = LIKE and 2 =
description) or receiver_id = 32)"
and this what really i want to run:
select * from `transcation_historique` where (`sender_id` = 32 and `description` = %salaire%) or `receiver_id` = 32)
Try this,
$description_query = Transcationhistorique::where(
function($query) use ($user_id, $description){
return $query->where('sender_id', $user_id)
->where('description', 'like', '%' . $description .'%');
}
)
->orWhere('receiver_id', $user_id)
->get();
It seems like your where query is not structured correctly.
You should use the following structure if you want to use operators other than "="
Source
$query->where([
['column_1', '=', 'value_1'],
['column_2', '<>', 'value_2'],
[COLUMN, OPERATOR, VALUE],
...
])
My suggestion is:
$description = $request->get('description');
if (!empty($description)){
$description_query = Transcationhistorique::where([
['sender_id', '=', $user_id],
['description', 'LIKE', "%{$description}%"]
])
->orWhere('receiver_id', $user_id)->get();
}else{
$description_query = "" ;
}
Try this one:
Transcationhistorique::where('receiver_id', '=', $user_id)
->orWhere(function ($query) use ($user_id, $description) {
$query->where('sender_id', '=', $user_id)->where('description', 'LIKE', "%".$description."%");
})->get();
You can use multiple where method as and.
Can you try following codes?
$description = $request->get('description');
if (!empty($description)){
$description_query = Transcationhistorique::where('sender_id', $user_id)
->where("description", 'LIKE','%' . $description . '%')
->orWhere('receiver_id', $user_id)->get();
}else{
$description_query = "" ;
}

Get data whereBeetween two coloms

I'm using Laravel 5.5.
I have Table centrals with Model Centrals
and table like this
my Controller
$from = $request->year_from;
$to = $request->year_to;
$month_from = $request->month_from;
$month_to = $request->month_to;
$param = $request->get('parameters_id', []);
$search = Centrals::whereIn('parameters_id', $param)
->where('type', 'Monthly')
->where('year', $from)
->whereBetween('months_id', [$month_from, $month_to])
->orderBy('year')
->get();
now how i get data
example request:
$request->year_from = 2016;
$request->month_from = 1; /* 1 =Jan*/
$request->year_from = 2018;
$request->month_from = 3; /* 3 =Mar*/
The following should do the trick:
$search = Centrals::whereIn('parameters_id', $param)
->where('type', 'Monthly')
->where(function($q) use ($yearFrom, $monthFrom) {
$q->where('year', '>', $yearFrom);
$q->orWhere(function($q2) use ($yearFrom, $monthFrom) {
$q2->where('year', $yearFrom);
$q2->where('month', '>=', $monthFrom);
});
})
->where(function($q) use ($yearTo, $monthTo) {
$q->where('year', '<', $yearTo);
$q->orWhere(function($q2) use ($yearTo, $monthTo) {
$q2->where('year', $yearTo);
$q2->where('month', '<=', $monthTo);
});
})->get();

Convert SQL Query into Laravel query

I am trying to check the given input is already existed between the c_start and c_end through query, but it is not working. Here is my controller.. for example if person 1 booked a room from 10 to 12 then person can't book the same room at same date from 11 to 12 or any time between the existing booked time.
/* namespace App\booking; */
namespace App\Http\Controllers;
use App\booking;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use DB;
use App\Quotation;
use DateTime;
class RoombookController extends Controller {
public function insert_check(Request $request) {
$roomname = $request->input('roomname');
$book = $request->input('bookdate');
$dbstime = explode(':', $request->input('starttime'));
$dbetime = explode(':', $request->input('endtime'));
$dbstime[0] = $dbstime[0] * 60;
$dbetime[0] = $dbetime[0] * 60;
$dbsum = array_sum($dbstime);
$dbesum = array_sum($dbetime);
$users = DB::table("bookings")
->select("id")
->where('bookdate', '=', $request->input('bookdate'))
->where('roomname', '=', $request->input('roomname'))
->where(function ($query){
$query->where('c_start', '<', $dbsum);
$query->orWhere('c_end', '>', $dbsum);
})
->orWhere(function($query){
$query->where('c_start', '<', $dbesum);
$query->orWhere('c_end', '>', $dbesum);
});
if ($users->count() == 0) {
$booking = new booking;
$booking->bookdate = $request->input('bookdate');
$booking->roomname = $request->input('roomname');
$booking->starttime = $startTime = $request->input('starttime');
$booking->endtime = $finishTime = $request->input('endtime');
$booking->purpose = $request->input('Purpose');
$booking->booked_by = Auth::user()->id;
$smstime = explode(':', $startTime);
$emstime = explode(':', $finishTime);
$smstime[0] = $smstime[0] * 60;
$emstime[0] = $emstime[0] * 60;
$startsum = array_sum($smstime);
$endsum = array_sum($emstime);
$booking_time = $startTime . ' to ' . $finishTime;
$booking->c_start = $startsum;
$booking->c_end = $endsum;
$booking->booking_time = $booking_time;
$time = ($etime - $stime) / 60;
$booking->total_duration = $time;
$booking->save();
return view("bookmessage");
} else {
return view("duplicateValue");
}
}
}
Change query to:
$users = DB::table("bookings")
->select("id")
->where('bookdate', '=', $request->get('bookdate'))
->where('roomname', '=', $request->get('roomname'))
->where(function ($query) use ($dbsum, $dbesum){
$query->where(function ($query) use ($dbsum){
$query->where('c_start','<',$dbsum);
$query->Where('c_end','>',$dbsum);
})
->orWhere(function($query) use($dbesum){
$query->where('c_start','<',$dbesum);
$query->orWhere('c_end','>',$dbesum);
});
});
Try this code and let me know if it works:
$whereCondition = array('bookdate'=>$request->input('bookdate'),'roomname'=>$request->input('roomname'));
$users = DB::table("bookings")
->select("id")
->where($whereCondition)
->where(function ($query use $dbsum){
$query->where('c_start','<',$dbsum);
$query->orWhere('c_end','>',$dbsum);
})
->orWhere(function($query use $dbesum){
$query->where('c_start','<',$dbesum);
$query->orWhere('c_end','>',$dbesum);
})
->get();
You can run your sql query directly in laravel query builder .You can try this:
$sql = "SELECT * FROM `bookings` WHERE `bookdate`='2016-12-27' AND `roomname`='3' AND (($dbsum>`c_start` AND $dbsum<`c_end`) OR ($dbesum>`c_start` AND $dbesum<`c_end`))";
$result = DB::select(DB::raw($sql))
$result variable contains your output. You must be use your DB class
use DB;
this is the query from which i got my correct result
$whereCondition = array('bookdate'=>$request->input('bookdate'),'roomname'=>$request->input('roomname'));
$users = DB::table("bookings")
->select("id")
->where('bookdate', '=', $request->get('bookdate'))
->where('roomname', '=', $request->get('roomname'))
->whereRaw(DB::raw("((c_start<$dbsum and c_end>$dbsum) or (c_start<$dbesum and c_end>$dbesum ))"))
->get();

Laravel Query with subquery not working

Maybe I am doing this incorrectly, however what I want to do logically is this:
I want to first select all posts that contain a certain string.
Then from those results, I want to narrow it down to only posts within a certain date (Y|m|d).
So this is what im doing at the moment:
$results = DB::table('posts');
if ($query == null){
$query = "Posted On: " . $date;
}else {
$results->where('posts.title', 'LIKE', "%$query%")
->orWhere('posts.meta_description', 'LIKE', "%$query%")
->orWhere('posts.meta_keywords', 'LIKE', "%$query%")
->orWhere('posts.body', 'LIKE', "%$query%")
->orWhere('posts.seo_title', 'LIKE', "%$query%");
$query = $query." / Posted On: " . $date;
}
$results->where(function($query) use ($date){
$date = explode('-', $date);
if (!isset($date[1])){
$query->whereYear('created_at', '=', $date[0]);
}else if(isset($date[1]) && !isset($date[2])){
$query->whereYear('created_at', '=', $date[0])
->whereMonth('created_at', '=', $date[1]);
}else if (isset($date[1]) && isset($date[2])){
$query->whereYear('created_at', '=', $date[0])
->whereMonth('created_at', '=', $date[1])
->whereDay('created_at', '=', $date[2]);
}
});
$results = $results->paginate($this->paginate_size());
However, this query is still just returning anything that contains the query string and ignoring the fact that I want to select a subset that are only posts on a specific year/month/day.
What am I missing?
Edit:
Using $results->toSql(); I get the query:
select * from `posts` where `posts`.`title` LIKE ? or
`posts`.`meta_description` LIKE ? or `posts`.`meta_keywords` LIKE ? or
`posts`.`body` LIKE ? or `posts`.`seo_title` LIKE ? and year(`created_at`) = ?
However, it is not working...
If I enter for example the query "Lorem" it will find all of the posts with the text Lorem in it.
However, when I add a specific date like just "2015", it should not show ANY posts from 2015 with the query Lorem since it does not exist.
So there is some logic problem here. Any ideas?
You shouldn't need a subquery.
If you have the proper query in place you should be able to access in the same query.
Of course you can have the dynamic where with the conditions, but do it on the same query. Something along the lines, for example:
if ($query == null){
$query = "Posted On: " . $date;
}
$results->where('posts.title', 'LIKE', "%$query%")
->orWhere('posts.meta_description', 'LIKE', "%$query%")
->orWhere('posts.meta_keywords', 'LIKE', "%$query%")
->orWhere('posts.body', 'LIKE', "%$query%")
->orWhere('posts.seo_title', 'LIKE', "%$query%");
$date = explode('-', $date);
if (!isset($date[1])){
$results->whereYear('created_at', '=', $date[0]);
}else if(isset($date[1]) && !isset($date[2])){
$results->whereYear('created_at', '=', $date[0])
->whereMonth('created_at', '=', $date[1]);
}else if (isset($date[1]) && isset($date[2])){
$results->whereYear('created_at', '=', $date[0])
->whereMonth('created_at', '=', $date[1])
->whereDay('created_at', '=', $date[2]);
}
$results = $results->paginate($this->paginate_size());
You can use the whereDate() Eloquent method:
$results = DB::table('posts');
if ($query == null){
$query = "Posted On: " . $date;
}else {
$results->where(function($q) {
$q->where('posts.title', 'LIKE', "%$query%")
->orWhere('posts.meta_description', 'LIKE', "%$query%")
->orWhere('posts.meta_keywords', 'LIKE', "%$query%")
->orWhere('posts.body', 'LIKE', "%$query%")
->orWhere('posts.seo_title', 'LIKE', "%$query%");
})->whereDate('created_at', '=', date('Y-m-d');
$query = $query." / Posted On: " . $date;
}
$results = $results->paginate($this->paginate_size());

Laravel4 query cloning

This problem is driving me nuts.
It appears that cloning a query doesn't work as expected since my last composer update.
The weird thing is that if I don't perform ->get()on the first query clone, the second query executes fine. From the moment I perform the ->geton both query clones, I receive an error:
General error: 2031
The clone should create a deep copy of the original query, but something doesn't seem right.
Any ideas? Here is my query (it looks more complex than it is, and the query itself is fine):
//Query dates
$query_onetime = clone $query;
$query_onetime = $query_onetime->join('events_dates', function($join) use ($input_date_start, $input_date_end){
$join->on('events.id', '=', 'events_dates.event_id');
$join->where('events_dates.start_date', "<=", $input_date_end);
$join->where('events_dates.end_date', '>=', $input_date_start);
});
//Select fields
$events_onetime = $query_onetime->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
if(isset($data["include_recurrent"]) && $data["include_recurrent"]){
//Query recurrent dates
$query_recurrent = clone $query;
$query_recurrent = $query_recurrent->join('events_dates_recurrent', 'events.id', '=', 'events_dates_recurrent.event_id')
->where(function($join) use ($input_date_start, $input_date_end) {
//Create a dynamic query to get all recurrent dates within the input time interval
$query_string = "ABS(DATEDIFF('" . $input_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
$temp_date_start = $input_date_start;
while(strtotime($temp_date_start) < strtotime($input_date_end)){
$temp_date_start = date('Y-m-d', strtotime($temp_date_start . " +1 day"));
//Create a raw query string
$query_string = $query_string . " OR ABS(DATEDIFF('" . $temp_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
}
$join->whereRaw($query_string);
});
//Select fields
$events_recurrent = $query_recurrent->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
$events = array_merge($events_onetime, $events_recurrent);
EDIT: for info on request, here is the full query.
I avoided it because it is pretty long.
// Queries events based on map bounds, category and date
$query = DB::table('events')
->join('places', function($join) use ($data){
$join->on('events.place_id', '=', 'places.id')
->where('places.lat', '>', $data['sw_lat'])
->where('places.lat', '<', $data['ne_lat'])
->where('places.lng', '>', $data['sw_lng'])
->where('places.lng', '<', $data['ne_lng']);
})->join('event_categories', function($join) use ($data){
$join->on('events.category_id', '=', 'event_categories.id');
});
// The category id is optional
if(isset($data["category_id"])){
$query = $query->where('event_categories.id', '=', $data['category_id']);
}
//Query subcategory
$query = $query->leftJoin('event_subcategories', function($join) use ($data){
$join->on('events.subcategory_id', "=", "event_subcategories.id");
});
//Query keywords
$query = $query->join('events_keywords', 'events.id', '=', 'events_keywords.event_id');
//Reverse date format
$input_date_start = date("Y-m-d", strtotime($data["date_start"]));
$input_date_end = date("Y-m-d", strtotime($data["date_end"]));
//Query dates
$query_onetime = clone $query;
$query_onetime = $query_onetime->join('events_dates', function($join) use ($input_date_start, $input_date_end){
$join->on('events.id', '=', 'events_dates.event_id');
$join->where('events_dates.start_date', "<=", $input_date_end);
$join->where('events_dates.end_date', '>=', $input_date_start);
});
//Select fields
$events_onetime = $query_onetime->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
foreach($events_onetime as $event){
$temp_event = EventModel::find($event->id);
$event->keywords = $temp_event->keywords;
}
if(isset($data["include_recurrent"]) && $data["include_recurrent"]){
//Query recurrent dates
$query_recurrent = clone $query;
$query_recurrent = $query_recurrent->join('events_dates_recurrent', 'events.id', '=', 'events_dates_recurrent.event_id')
->where(function($join) use ($input_date_start, $input_date_end) {
//Create a dynamic query to get all recurrent dates within the input time interval
$query_string = "ABS(DATEDIFF('" . $input_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
$temp_date_start = $input_date_start;
while(strtotime($temp_date_start) < strtotime($input_date_end)){
$temp_date_start = date('Y-m-d', strtotime($temp_date_start . " +1 day"));
//Create a raw query string
$query_string = $query_string . " OR ABS(DATEDIFF('" . $temp_date_start . "', CAST(events_dates_recurrent.start_date AS DATE)) % events_dates_recurrent.repeat_interval) = 0";
}
$join->whereRaw($query_string);
});
//Select fields
$events_recurrent = $query_recurrent->select('events.id AS id', 'events.name AS name', 'event_categories.id as category_id', 'event_categories.category as category',
'event_subcategories.id as subcategory_id', 'event_subcategories.subcategory as subcategory',
'short_description', 'time_description',
'price_description', 'nr_going', 'nr_checkedin', 'homepage', 'fbpage', 'profile_pic',
'places.id AS place_id', 'places.name AS place_name', 'lat', 'lng', 'address')
->groupBy('events.id')
->get();
//At this point we just have the events, but we also need the keywords per event.
foreach($events_recurrent as $event){
$temp_event = EventModel::find($event->id);
$event->keywords = $temp_event->keywords;
}
$events = array_merge($events_onetime, $events_recurrent);
} else {
//Else return only the non-recurrent events
$events = $events_onetime;
}
return $events;
}
Your $query object is an instance of Illuminate\Database\Eloquent\Builder and it maintains a reference to a Illuminate\Database\Query\Builder which holds the actual query. According to the PHP Docs, the clone keyword performs a shallow copy of an object, meaning that references are copied as references. Thus, $query and $query_onetime both maintain a reference to the same Illuminate\Database\Query\Builder instance and changes to one affect the other.
This issue with needing to clone the underlying query has been fixed in Laravel 4.1, but if you don't want to upgrade you can try this workaround:
$query_onetime = clone $query;
$query_onetime->setQuery(clone $query->getQuery());
// Any additional joins specific to $query_onetime

Categories