I used CodeIgniter's calendar library to populate data from a database table but apparently it has following issues:
No more than 1 reocrd is shown
Entries below the day 9 of the month are not shown while everything else is working
Why would this happen?
Model:
class reminders_model extends CI_Model {
var $conf;
function reminders_model() {
parent::__construct();
$this->conf = array(
'start_day' => 'monday',
'month_type' => 'long',
'day_type' => 'long'
);
$this->conf['template'] = '
{table_open}
<table class="calendar">
{/table_open}
{week_day_cell}
<th class="day_header">{week_day}</th>
{/week_day_cell}
{cal_row_start}<tr class="days">{/cal_row_start}
{cal_cell_start}<td class="day">{/cal_cell_start}
{cal_cell_content}
<span class="day_listing">{day}</span> • {content} {/cal_cell_content}
{cal_cell_content_today}
<div class="today"><span class="day_listing">{day}</span>• {content}</div>{/cal_cell_content_today}
{cal_cell_no_content}
<span class="day_listing">{day}</span> {/cal_cell_no_content}
{cal_cell_no_content_today}
<div class="today"><span class="day_listing">{day}</span></div>{/cal_cell_no_content_today}
';
}
function get_calendar_data($year, $month) {
$query = $this->db->select('date, reason')->from('reminders')->like('date', "$year-$month", 'after')->get();
$cal_data = array();
foreach ($query->result() as $row) {
$cal_data[substr($row->date, 8, 2)] = $row->reason;
}
return $cal_data;
}
function generate($year, $month) {
$this->load->library('calendar', $this->conf);
$cal_data = $this->get_calendar_data($year, $month);
return $this->calendar->generate($year, $month, $cal_data);
}
Controller:
<?php
class reminders extends CI_Controller {
function index($year = null, $month = null) {
if (!$year) {
$year = date('Y');
}
if (!$month) {
$month = date('m');
}
$this->load->model('/summary/reminders_model');
if ($day = $this->input->post('day')) {
$this->reminders_model->add_calendar_data(
"$year-$month-$day",
$this->input->post('reason')
);
}
$data['calendar'] = $this->reminders_model->generate($year, $month);
$this->load->view('summary/reminders_view', $data);
}
View:
<?php echo $calendar; ?>
In order to put more than one item into a day, say the 15th you'll have to create a multi-dimensional array to get multiple appointments on it. For instance.
function get_calendar_data($year, $month) {
$query = $this->db->select('date, reason')->from('reminders')->like('date', "$year-$month", 'after')->get();
$cal_data = array();
foreach ($query->result() as $row) {
$day = date('j',$row->date);
$cal_data[$day][] = $row->reason;
}
return $cal_data;
}
As for the reason your only getting 9, I'm guessing it has to do with your substr()
Related
I have this php function in codeigniter where it fetches the data from my database:
function fetch_data()
{
$data = $this->projectionchart_model->make_query();
$array = array();
foreach($data as $row)
{
$array[] = $row;
}
$output = array(
'current' => intval($_POST["current"]),
'rowCount' => 10,
'total' => intval($this->projectionchart_model->count_all_data()),
'rows' => $array
);
echo json_encode($output);
}
I want to use the number_format function to some of columns and right now it's building everything in an array. How could I remove the array and list the data individually as variables so I can apply a function to some of them and then output them?
Thank you
Edit: explaining in more detail
This function fetch_data() calls the make_query() function stored in the projectionchart_model file which contains the following:
function make_query()
{
if(isset($_POST["rowCount"]))
{
$this->records_per_page = $_POST["rowCount"];
}
else
{
$this->records_per_page = 10;
}
if(isset($_POST["current"]))
{
$this->current_page_number = $_POST["current"];
}
$this->start_from = ($this->current_page_number - 1) * $this->records_per_page;
$this->db->select("*");
$this->db->from("projection_chart");
if(!empty($_POST["searchPhrase"]))
{
$this->db->like('ae', $_POST["searchPhrase"]);
$this->db->or_like('client', $_POST["searchPhrase"]);
$this->db->or_like('product', $_POST["searchPhrase"]);
$this->db->or_like('week_of', $_POST["searchPhrase"]);
$this->db->or_like('month', $_POST["searchPhrase"]);
$this->db->or_like('type', $_POST["searchPhrase"]);
}
if(isset($_POST["sort"]) && is_array($_POST["sort"]))
{
foreach($_POST["sort"] as $key => $value)
{
$this->db->order_by($key, $value);
}
}
else
{
$this->db->order_by('id', 'DESC');
}
if($this->records_per_page != -1)
{
$this->db->limit($this->records_per_page, $this->start_from);
}
$query = $this->db->get();
return $query->result_array();
}
So the output currently is this:
I want to format the Planned Spend, Cleared and Total Commission with the number_format php function but right now it's all in an array.
How could I accomplish this?
I have calendar whose dates are booked and saved in database. I am trying to pull the bookings from database and show then under corresponding date. Everything is working fine, except the thing, I want the date to be just text instead of link when there are more than 5 events to that date.
I am aware of the calendar template no content cell and content cells. But i want the date to have no link when it has more than 5 events attached to it.
My Model:
public function bookingcalender($year=null,$month=null)
{
if(!$year)
{
$y = date('Y');
}
else
{
$y = $year;
}
if(!$month)
{
$m = date('m');
}
else
{
$m = $month;
}
$this->config = array(
'show_next_prev' => TRUE,
'next_prev_url' => 'http://joshuaflinn.com/CI/booking/show',
'template' => '{table_open}<table class="availability-calendar">{/table_open}
{heading_row_start}<tr class="toolbar">{/heading_row_start}
{heading_title_cell}<th colspan="{colspan}">{heading}</th>{/heading_title_cell}
{heading_previous_cell}<th><</th>{/heading_previous_cell}
{heading_next_cell}<th>></th>{/heading_next_cell}
{heading_row_end}</tr>{/heading_row_end}
{week_row_start}<tr>{/week_row_start}
{week_day_cell}<td>{week_day}</td>{/week_day_cell}
{week_row_end}</tr>{/week_row_end}
{cal_row_start}<tr>{/cal_row_start}
{cal_cell_start}<td>{/cal_cell_start}
{cal_cell_start_today}<td>{/cal_cell_start_today}
{cal_cell_start_other}<td class="other-month">{/cal_cell_start_other}
{cal_cell_content}{day}<span class="date-data">{content}</span>{/cal_cell_content}
{cal_cell_content_today}<div class="highlight">{day}</div>{/cal_cell_content_today}
{cal_cell_no_content}{day}{/cal_cell_no_content}
{cal_cell_no_content_today}<div class="highlight">{day}</div>{/cal_cell_no_content_today}
{cal_cell_blank} {/cal_cell_blank}
{cal_cell_other}{day}{/cal_cel_other}
{cal_cell_end}</td>{/cal_cell_end}
{cal_cell_end_today}</td>{/cal_cell_end_today}
{cal_cell_end_other}</td>{/cal_cell_end_other}
{cal_row_end}</tr>{/cal_row_end}
{table_close}</table>{/table_close}'
);
$this->load->library('calendar',$this->config);
$conf_data = $this->get_booked_dates($year,$month);
return $this->calendar->generate($year,$month,$conf_data);
}
public function get_booked_dates($year,$month)
{
$query = $this->db->select('client_name,booking_date')->from('bookings')->like('booking_date',"$year-$month")->get();
$cal_data = array();
foreach($query->result() as $row)
{
$dt = explode("-", $row->booking_date);
$dt = $dt[2];
$k = ($dt >= 10 ? substr($row->booking_date, 8,2) : substr($row->booking_date, 9,1));
if( #$cal_data[$k] == '' )
{
$cal_data[$k] = $row->client_name;
}
else
{
$cal_data[$k] .= ','.$row->client_name;
}
}
return $cal_data;
}
The options you have are limited since Codeigniters Calendar Library only have the two pseudo variables cal_cell_no_content and cal_cell_contentin the template to play with in terms of what content you want to display.
A quick look behind the door reveals that the library uses isset() to determine which of the two pseudo variables to use.
And it calls str_replace {content} before {day} that opens up for a somewhat hacky solution:
public function bookingcalender($year=null,$month=null)
{
if(!$year)
{
$y = date('Y');
}
else
{
$y = $year;
}
if(!$month)
{
$m = date('m');
}
else
{
$m = $month;
}
$this->config = array(
'show_next_prev' => TRUE,
'next_prev_url' => 'http://joshuaflinn.com/CI/booking/show',
'template' => '{table_open}<table class="availability-calendar">{/table_open}
{heading_row_start}<tr class="toolbar">{/heading_row_start}
{heading_title_cell}<th colspan="{colspan}">{heading}</th>{/heading_title_cell}
{heading_previous_cell}<th><</th>{/heading_previous_cell}
{heading_next_cell}<th>></th>{/heading_next_cell}
{heading_row_end}</tr>{/heading_row_end}
{week_row_start}<tr>{/week_row_start}
{week_day_cell}<td>{week_day}</td>{/week_day_cell}
{week_row_end}</tr>{/week_row_end}
{cal_row_start}<tr>{/cal_row_start}
{cal_cell_start}<td>{/cal_cell_start}
{cal_cell_start_today}<td>{/cal_cell_start_today}
{cal_cell_start_other}<td class="other-month">{/cal_cell_start_other}
{cal_cell_content}{content}{/cal_cell_content}
{cal_cell_content_today}<div class="highlight">{content}</div>{/cal_cell_content_today}
{cal_cell_no_content}{day}{/cal_cell_no_content}
{cal_cell_no_content_today}<div class="highlight">{day}</div>{/cal_cell_no_content_today}
{cal_cell_blank} {/cal_cell_blank}
{cal_cell_other}{day}{/cal_cel_other}
{cal_cell_end}</td>{/cal_cell_end}
{cal_cell_end_today}</td>{/cal_cell_end_today}
{cal_cell_end_other}</td>{/cal_cell_end_other}
{cal_row_end}</tr>{/cal_row_end}
{table_close}</table>{/table_close}'
);
$this->load->library('calendar',$this->config);
$conf_data = $this->get_booked_dates($year,$month);
return $this->calendar->generate($year,$month,$conf_data);
}
public function get_booked_dates($year,$month)
{
$query = $this->db->select('client_name,booking_date')->from('bookings')->like('booking_date',"$year-$month")->get();
$cal_data = array();
foreach($query->result() as $row)
{
$dt = explode("-", $row->booking_date);
$k = intval($dt[2]); // MAKE INTEGER OF DAY NUMBER
if( #$cal_data[$k] == '' )
{
$cal_data[$k] = $row->client_name;
}
else
{
$cal_data[$k] .= ','.$row->client_name;
}
}
// LOOP THROUGH EACH DAY TO FIND THOSE WITH MORE THAN 5 EVENTS
foreach($cal_data as $key=>$val){
// COUNT THE NUMBER OF COMMAS THAT OCCUR IN STRING
$count = strlen($val) - strlen(str_replace(',','',$val));
if($count > 4){ // IF MORE THAN 4 COMMAS (> 5 EVENTS) THEN NO LINK...
$cal_data[$key] = '{day}<span class="date-data">'.$val.'</span>';
} else { // LINKED DAY
$cal_data[$key] = '{day}<span class="date-data">'.$val.'</span>';
}
}
return $cal_data;
}
Note: that I have changed two rows in the template: {cal_cell_content}{content}{/cal_cell_content} and {cal_cell_content_today}<div class="highlight">{content}</div>{/cal_cell_content_today}
You now only need to set {content} since {day} is specified inside the content also containing the html returned from the query.
Update: I have now tested the solution and it seems to work fine!
You have to manipulate or extend the Calendar library if you need a more flexible solution and if you don't want to mix template html in the content returned from your query.
I made a method that writes a view with a calendar table which shows all months of a year using the calendaring class.
Controller:
<?php
class Calendar extends CI_Controller {
public function this_year() {
$data['title'] = 'Calendar: ' . date('Y');
$this->load->library('calendar');
$prefs = array(
'local_time' => 'none',
'start_day' => 'sunday',
'month_type' => 'long',
'day_type' => 'short',
'show_next_prev' => FALSE,
'show_other_days' => TRUE,
'template' => '
{table_open}<table class="table table-condensed">{/table_open}
{heading_row_start}<tr class="info">{/heading_row_start}
{cal_cell_start_today}<td class="today">{/cal_cell_start_today}
{cal_cell_start_other}<td class="other-day">{/cal_cell_start_other}
'
);
$this->load->library('calendar', $prefs);
$data['calendar'] = '<table class="table-calendar"><tr>';
for ($i = 1; $i <= 12; $i++) {
if ($i % 3 == 0) {
$data['calendar'].= "<td>{$this->calendar->generate(date('Y'), $i)}</td>";
$data['calendar'].= '</tr><tr>';
}
else {
$data['calendar'].= "<td>{$this->calendar->generate(date('Y'), $i)}</td>";
}
}
$data['calendar'].= '</tr></table>';
$this->template->load('template/index', __CLASS__ . "/" . __FUNCTION__, $data);
}
}
*On VIEW, just echo '$calendar'
It works as well, and returns this.
But I didn't found a way to highlight only the current month using a template in the calendaring class. I tried to modify the default template but it doesn't work because when I change the class of {heading_title_cell}<th colspan="{colspan}">{heading}</th>{/heading_title_cell}, it modifies all the month's labels like this.
I'm using the default methods (same code) from the basic class tutorial. Any suggestion?
It is possible to extend CI_Calendar to force the method generate() pass his $month variable to the parse_template() method. Then, parse_template($month) will be able to apply an exception while parsing the declared template on {heading_row_start}<tr>{/heading_row_start}:
CI_Calendar::parse_template($month), 483:
if($val == 'heading_row_start'){
if( $month == date('m')){
$this->replacements[$val] = '<tr class="info">';
}
}
else{
$this->replacements[$val] = $match[1];
}
I need to set the pagination order of my register based on field ($results[$key]['Movimento']['status']) created in afterFind callback.
afterFind:
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
if(isset($val['Movimento']['data_vencimento'])) {
$data = $val['Movimento']['data_vencimento'];
$dtVc = strtotime($data);
$dtHj = strtotime(date('Y-m-d'));
$dtVencendo = strtotime("+7 day", $dtHj);
if ($dtVc < $dtHj) {
$results[$key]['Movimento']['status'] = 'vencido';
} elseif ($dtVc <= $dtVencendo) {
$results[$key]['Movimento']['status'] = 'vc15dias';
} else {
$results[$key]['Movimento']['status'] = 'aberto';
}
}
if(isset($val['Movimento']['data_pagamento'])) {
$results[$key]['Movimento']['status'] = 'quitado';
}
}
return $results;
Pagination:
$options = array(
...
'order' => array('Movimento.status' => 'ASC')
);
$this->controller->paginate = $options;
$movimentos = $this->controller->paginate('Movimento');
I know this does not work because the field is created after the paginator call.
Can I make it work?
as I understand, you want to sort by data_pagamento and than by data_vencimento (has it the mysql-type date?)
so you don't need your afterFind-function for ordering, simply use:
'order' => array(
'Movimento.data_pagamento DESC',//first all rows with not-empty data_pagamento
'Movimento.data_vencimento DESC',// first all dates in the furthest future
)
here are the following codes:
controller.php
function getchart() {
$prac = $this->input->post('prac_name');
$datee = $this->input->post('datee');
$this->load->model('appoint');
$results['appoint'] = $this->appoint->getappoint($prac , $datee);
$this->load->view('ajax/getappchart' , $results);
}
model.php
function getappoint($prac , $datee) {
$this->db->select('rdv.id as rdvid, startTime, endTime, day, firstname, lastname');
$this->db->from('rdv');
$this->db->join('contact', 'contact.id = rdv.contact_id');
$this->db->where('people_id',$practicien);
$this->db->where('DATE(day)', $datee);
$this->db->order_by('TIME(startTime)', 'ASC');
$query = $this->db->get();
//print_r($this->db->last_query());
return $query;
}
view.php
if ($appoint->num_rows() > 0) {
foreach($appoint->result() as $sub_row)
{
// display output.
}
} else {
echo 'No Appointments on Above Date.';
}
?>
what i need is, there are appointments with sametime and day(mostly 2 same).
if there is morethan 2, i need to set two different class style for both the appointment.
how can i achieve this ?
Thanks.
Final answer: done it with the help of #minhaz-ahmed
if ($appoint->num_rows() > 0) {
$appoint_counter = array();
foreach ($appoint->result() as $sub_row) {
//i am assuming your startTime is H:M:S, and day Y-M-D format
$key = strtotime($sub_row['day'] . ' ' . $sub_row['startTime']);
if (!isset($appoint_counter[$key])) {
$appoint_counter[$key] = 0;
}
$appoint_counter[$key] ++;
$style_class = 'YOUR_1ST_CLASS';
if ($appoint_counter[$key] > 2) {
$style_class = 'YOUR_2ND_CLASS';
}
//REST VIEW CODE
}
}
else {
echo 'No Appointments on Above Date.';
}
You can do like this
if ($appoint->num_rows() > 0) {
$appoint_counter = array();
foreach ($appoint->result() as $sub_row) {
//i am assuming your startTime is H:M:S, and day Y-M-D format
$key = strtotime($sub_row['day'] . ' ' . $sub_row['startTime']);
if (!isset($appoint_counter[$key])) {
$appoint_counter[$key] = 0;
}
$appoint_counter[$key] ++;
}
foreach ($appoint->result() as $sub_row) {
//i am assuming your startTime is H:M:S, and day Y-M-D format
$key = strtotime($sub_row['day'] . ' ' . $sub_row['startTime']);
$style_class = 'YOUR_1ST_CLASS';
if ($appoint_counter[$key] > 2) {
$style_class = 'YOUR_2ND_CLASS';
}
//YOUR REST VIEW
}
} else {
echo 'No Appointments on Above Date.';
}
What do you mean by class style? Anyway, the code below assumes you will put the results in a datagrid.
$prev_date = "";
$prev_time = "";
$results = $query->result();
foreach($results as $appointment) {
if ($prev_date != $appointment->day) // Assuming "day" is tables date
# Display output here
if ($prev_time != $appointment->startTime) // Logically, display should sort appointments by their starting time
# Display output here
# Display appointment rows here
$prev_date = $appointment->day;
$prev_time = $appointment->startTime;
}
if (empty($results)) {
# Display "no appointments found" output here
}