Im building the chat section of my app with vueJs and laravel backend. I want to fetch my messages grouped by days. So when messages display, I want them to look something like this.
`Today
**All messages sent and received today, ordered by time**
Yesterday
**Yesterday's messages**
9/12/2018
**Messages for that day**
In my Chat model, I wrote an accessor for this like so;
public function getMessagesAttribute(){
return $this
->groupBy(function($q){
return $q->created_at->format('Y-m-d');
});
However, this does not give anything different from what I got when I use orderBy('created_at', 'ASC') in the controller. I will appreciate any assistance/guidance to achieve what I want please.
You could feed the results of your function into a loop that starts with the first date, sets the date as a variable, then compares it to the next date, which, if the next date has a smaller value, it gets preceded with a header field to result in grouping.
$date=null;
$next_date=null;
while($this) {
$date = $this->created_at;
if($next_date != null && $next_date<$date) {
*put your group title here*;
*put date/message here*;
} else {
*put date/message here*;
}
$next_date=$date;
}
Maybe build an array out of it, or something like that.
What about
$today = \Carbon\Carbon::now()->format('Y-m-d');
$yesterday = \Carbon\Carbon::yesterday()->format('Y-m-d');
$any_day = \Carbon\Carbon::createFromFormat('d/m/Y', '9/12/2018')->format('Y-m-d'); //used your example date
$messages_today = Message::where('created_at', 'like', "{$today}%")->orderBy('created_at', 'desc')->get();
$messages_yesterday = Message::where('created_at', 'like', "{$yesterday}%")->orderBy('created_at', 'desc')->get();
$messages_any_day = Message::where('created_at', 'like', "{$any_day}%")->orderBy('created_at', 'desc')->get();
It needs some tweeking according to your needs. But that should do the trick for you.
Related
Here is the code in which I get the user if it's g10_eng_unwh is equal to 1.
public function purchased(User $user)
{
if ($user->g10_eng_unwh == 1) {
$token = "g10_eng_unwh";
}
if ($user->g7_eng_unwh == 1) {
$token = "g7_eng_unwh";
}
$time = Carbon::now()->format('Y-m-d');
dd($user->email, $time, $token);
}
Instead, I want to get the user only when it's g10_eng_unwh value changes from 0 to 1.
Is there any way?
You need to get the past value at the beginning so that you can apply the condition, it will have to be stored somewhere. Most likely you will need to create g10_eng_unwh_old or something like that. I assume that g10_eng_unwh is a column in the database, in this case create g10_eng_unwh_old and store the old value in it.
In this case, you could get it even on request. For example
DB::query()
->where('g10_eng_unwh', 1)
->where('g10_eng_unwh_old', 0)
->get();
im new to Laravel and facing an interesting Issue right now in my App.
I have 3 tables.
Producers
id
producer_name
Types
id
type_name
Models
id
model_name
device_type_id
device_producer_id
Within my Producers Model I have defined the follwing Filter method:
public function scopeFilterByType($query, $type_id)
{
$query->whereHas('models', function($q) use $type_id { $q->where('device_type_id', $type_id );});
}
Using Tinker I can do the following:
App\DeviceProducer::filterByType(3)->get()
And get full response with my Producers associated to my given type.
I created an Function so when a user select a device type Ajax will load all Producers from this type.
public function reqProducer(Request $request)
{
$producers = DeviceProducer::filterByType($request->type_id)->get();
return response()->json( $producers );
}
But when AJAX is calling my endpoint it gets HTTP500 error.
I figured out when using a request without WhereHas for example:
$producers = DeviceProducer::where('id', $request->producer_id)->get();
It just works fine and I get my results. So it seems have to do something with "WhereHas". I know I could Solve this by first asking Models Table and the creating an Foreach loop. But I this solution would be less readable then my first attempt.
Does anyone has an suggestion what im doing wrong or is it just like there is noch AJAX support for WhereHas querys?
Kind regards
Mike
I think this is your issue use $type_id
Please fix as
public function scopeFilterByType($query, $type_id)
{
$query->whereHas('models', function($q) use ($type_id) { $q->where('device_type_id', $type_id );});
}
I'm making my project,and want to increment date from fetching to_date filed with 6 months if last to_date is gone then add more 6 months and so on what can i do for this?
$abc=(Session::get('email'));
$email= $request->input('email');
if (Maintenance::where('email', '=', $email)) {
$users=Carbon::create(2019,0,30)->addMonths(6)->toDatestring();
if (Maintenance::where('maintenance_status', '=', 'PAID')->orderBy('todate','DESC')) {
$check = Maintenance::select('to_date')->where('maintenance_status', '=', 'PAID')->orderBy('to_date','DESC')->get();
// $users= Carbon($check[0])->addmoths(6);
$users = Carbon::addMonths(6)->toDatestring();
i expect the output of 30-06-2019,30-12-2019 and so on but the actual output is only increment one time using Carbon and i want to increment fetching from database date
It looks like you are overwriting your variable instead of adding to it.
$users = Carbon\Carbon::create(2019,0,30)->addMonths(6)->toDatestring();
returns 2019-06-30.
$users = Carbon\Carbon::addMonths(6)->toDatestring(); would overwrite it, but it actually breaks "PHP Error: Call to a member function addMonths() on string".
Don't store the string as your variable. Instead, keep it as a instance of Carbon so that you can call functions on it. Then when you need to use it call toDatestring().
It would look something like this:
$date_to_increment = Carbon\Carbon::create(2019,0,30)->addMonths(6);
echo($date_to_increment->toDatestring()); // 2019-06-30
if ($your_condition) {
$date_to_increment->addMonths(6);
echo($date_to_increment->toDatestring()); // 2019-12-30
}
As far as applying it to your case, there are a few issues. Your first condition is invalid. I believe it will always return true as you never execute the query. I'm also assuming since you are matching an email that there will only be one result. So lets use the query builder method first() to save a step as this will return a single entry instead of an array.
$maintenance = Maintenance::where('email', '=', $email)->first();
if ($maintenance) {
// do stuff
}
Then you have a few more conditions that have similar issues, but more importantly, they are re-querying so you are losing the restrictions in your collection each time.
Instead:
$maintenance = Maintenance::where('email', '=', $email)->first();
if ($maintenance) {
if ($maintenance->maintenance_status === 'PAID') {
// do something
}
}
Finally, to use the value from the database:
if ($maintenance->maintenance_status === 'PAID') {
$date = Carbon\Carbon::parse($maintenance->to_date)->addMonths(6);
$maintenance>to_date = $date->toDatestring();
$maintenance->save();
}
I am trying to export excel from database in laravel. What i want to do is, there is a form by which admin can select "From" , "To" , "Bookingtype" and "Usertype" . From and To's are date, bookingtype is like Booked or Cancelled and userype is Normal or agent.
When admin select any kind of needs from this, for example when admin selects a date from , from and to then selects cancelled and Agent and press export button, they should get excel. And like wise they can execute different different queries.
So far , i have accomplished to get excel by using three parameters like from, to and bookingtype. But how to use fourth parameter also which is user type ?
This is my code:
public function query()
{
$from = $this->from;
$to = $this->to;
$bookingtype = $this->bookingtype;
$usertype = $this->usertype;
return Booking::query()->whereBetween('createdAt',[$from, $to])->where('status', '=', $bookingtype);
}
And the important is , some time admin can only select from and to and they dont need other two options. So in that situation how to execute only that with one query function ? I am passing these from a from to controller and then class of maatwebsite. So what i am asking is, how to make a query which executes only what are been sent ?
If we send from and to alone, then that should only execute and if we sent three parameters then that should execute like wise ! hope all understands. Do let me know if anything needed.
hope this will help you if not the let me know
$bokingQuery = Booking::query();
$from = $this->from;
$to = $this->to;
if(isset($from) && isset($to))
$bokingQuery->whereBetween('createdAt',[$from, $to]);
$bookingtype = $this->bookingtype;
if(isset($bookingtype ))
$bokingQuery->where('status',$bookingtype);
$usertype = $this->usertype;
if(isset($usertype)) //
$bokingQuery->whereHas('usertype',, function($query) use ($usertype) {
$query->whereUserType($usertype);
});
$bokingQuery->get();
You must be create your conditions due to the input parameters.
public function query(){
$conditions=[];
if(isset($this->from) && $this->from){
$conditions[]=['createdAt', '>=', $this->from];
}
if(isset($this->to) && $this->to){
$conditions[]=['createdAt', '<=', $this->to];
}
if(isset($this->bookingtype) && $this->bookingtype){
$conditions[]=['status', $this->bookingtype];
}
if(isset($this->usertype) && $this->usertype){
$conditions[]=['usertype', $this->usertype];
}
return Booking::where($conditions)->get();
}
I'm working with the latest codeIgniter released, and i'm also working with jquery datatables from datatables.net
I've written this function: https://gist.github.com/4478424 which, as is works fine. Except when I filter by using the text box typing something in. The filter itself happens, but my count is completely off.
I tried to add in $res = $this->db->count_all_results() before my get, and it stops the get from working at all. What I need to accomplish, if ($data['sSearch'] != '') then to utilize the entire query without the limit to see how many total rows with the search filter exists.
If you need to see any other code other than whats in my gist, just ask and I will go ahead and post it.
$this->db->count_all_results() replaces $this->db->get() in a database call.
I.E. you can call either count_all_results() or get(), but not both.
You need to do two seperate active record calls. One to assign the results #, and one to get the actual results.
Something like this for the count:
$this->db->select('id');
$this->db->from('table');
$this->db->where($your_conditions);
$num_results = $this->db->count_all_results();
And for the actual query (which you should already have):
$this->db->select($your_columns);
$this->db->from('table');
$this->db->where($your_conditions);
$this->db->limit($limit);
$query = $this->db->get();
Have you read up on https://www.codeigniter.com/userguide2/database/active_record.html#caching ?
I see you are trying to do some pagination where you need the "real" total results and at the same time limiting.
This is my practice in most of my codes I do in CI.
$this->db->start_cache();
// All your conditions without limit
$this->db->from();
$this->db->where(); // and etc...
$this->db->stop_cache();
$total_rows = $this->db->count_all_results(); // This will get the real total rows
// Limit the rows now so to return per page result
$this->db->limit($per_page, $offset);
$result = $this->db->get();
return array(
'total_rows' => $total_rows,
'result' => $result,
); // Return this back to the controller.
I typed the codes above without testing but it should work something like this. I do this in all of my projects.
You dont actually have to have the from either, you can include the table name in the count_all_results like so.
$this->db->count_all_results('table_name');
Count first with no_reset_flag.
$this->db->count_all_results('', FALSE);
$rows = $this->db->get()->result_array();
system/database/DB_query_builder.php
public function count_all_results($table = '', $reset = TRUE) { ... }
The
$this->db->count_all_results();
actually replaces the:
$this->db->get();
So you can't actually have both.
If you want to do have both get and to calculate the num rows at the same query you can easily do this:
$this->db->from(....);
$this->db->where(....);
$db_results = $this->get();
$results = $db_results->result();
$num_rows = $db_results->num_rows();
Try this
/**
* #param $column_name : Use In Choosing Column name
* #param $where : Use In Condition Statement
* #param $table_name : Name of Database Table
* Description : Count all results
*/
function count_all_results($column_name = array(),$where=array(), $table_name = array())
{
$this->db->select($column_name);
// If Where is not NULL
if(!empty($where) && count($where) > 0 )
{
$this->db->where($where);
}
// Return Count Column
return $this->db->count_all_results($table_name[0]);//table_name array sub 0
}
Then Simple Call the Method
Like this
$this->my_model->count_all_results(['column_name'],['where'],['table name']);
If your queries contain a group by, using count_all_results fails. I wrote a simple method to work around this. The key to preventing writing your queries twice is to put them all inside a private method that can be called twice. Here is some sample code:
class Report extends CI_Model {
...
public function get($page=0){
$this->_complex_query();
$this->db->limit($this->results_per_page, $page*$this->results_per_page);
$sales = $this->db->get()->result(); //no table needed in get()
$this->_complex_query();
$num_results = $this->_count_results();
$num_pages = ceil($num_results/$this->results_per_page);
//return data to your controller
}
private function _complex_query(){
$this->db->where('a', $value);
$this->db->join('(subquery) as s', 's.id = table.s_id');
$this->db->group_by('table.column_a');
$this->db->from('table'); //crucial - we specify all tables here
}
private function _count_results(){
$query = $this->db->get_compiled_select();
$count_query = "SELECT count(*) as num_rows FROM (".$query.") count_wrap";
$r = $this->db->query($count_query)->row();
return $r->num_rows;
}
}