CodeIgniter - $this->uri->segment() returns empty - php

I am trying to get the CodeIgniter calender library to work, and for that I need to use $this->uri->segment(), according to the documentation at least. The url for the calender looks like this:
http://www.example.com/index.php/tasks/calendar/2015/03
Which means, as far as I can understand, that $this->uri->segment(3) would be the year, and $this->uri->segment(4) the month. However, both of these returns nothing at all, here is the code for my calender page:
echo "Selected year: ".$this->uri->segment(3)." and month: ".$this->uri->segment(4);
echo $this->calendar->generate($this->uri->segment(3), $this->uri->segment(4));
The first line is merely used for debugging purposes, and confirms that none of the commands returns any output. The calender library is loaded in the controller, with the following code:
public function calendar() {
// Calender configuration (must be done prior to loading the library
$conf = array(
'start_day' => 'monday',
'show_next_prev' => true,
'next_prev_url' => base_url() . 'index.php/tasks/calendar'
);
// Load libraries and helpers
$this->load->library('calendar',$conf);
// Show page, including header and footer
$this->load->view('templates/header', $data);
$this->load->view('tasks/calendar', $data);
$this->load->view('templates/footer');
}
Can anyone tell me where I am failing? I read the documentation over and over again, and checked my code, but I can't see what I do different than their example?
UPDATE
I think I have ruled out that the problem is related to the $this->uri->section() function. Is likely to do with the controller loading an incorrect page, when additional sections is added to the URL after .../tasks/calendar/(...). I still haven't found a solution, but I wanted to let you know, in case others who read this had the same issue.
UPDATE 2
I think it might be a routing issue, the routes.php looks like this, for anything related to tasks:
$route['tasks/create'] = 'tasks/create';
$route['tasks/calendar/(:num)/(:num)'] = 'tasks/calendar/$1/$2';
$route['tasks/calendar'] = 'tasks/calendar';
$route['tasks'] = 'tasks';
$route['tasks/(:any)'] = 'tasks/view/$1';

for this to work you have to load the Codeigniter url helper since youre using base_url(). You can do this by running this $this->load->helper('url'); or by going to your autoload.php and placing it there in helper

Ok the problem here is not your URI class. The problem is that youre trying to use $this->uri->segment() inside your view. This is not how you should do this. You should only use that inside your controller. To fix this, you have two options, you can either pass your year and month as parameters to your controller method or you can use the uri->segment inside your controller.
Example 1: Passing year and month as parameters
URL: index.php/tasks/calendar/2015/03
Controller:
class Tasks extends MY_Controller {
public function calendar($year, $month){
$conf = array(
'start_day' => 'monday',
'show_next_prev' => true,
'next_prev_url' => base_url() . 'index.php/tasks/calendar'
);
$this->load->library('calendar',$conf);
$data = array(
"year" => $year,
"month" => $month
);
$this->load->view('tasks/calendar', $data);
}
}
View:
echo "Selected year: $year and month: $month";
echo $this->calendar->generate($year, $month);
Example 2: getting the variable using $this->uri
URL: index.php/tasks/calendar/2015/03
Controller:
class Tasks extends MY_Controller {
public function calendar(){
$conf = array(
'start_day' => 'monday',
'show_next_prev' => true,
'next_prev_url' => base_url() . 'index.php/tasks/calendar'
);
$this->load->library('calendar',$conf);
$data = array(
"year" => $this->uri->segment(3),
"month" => $this->uri->segment(4)
);
$this->load->view('tasks/calendar', $data);
}
}
View:
echo "Selected year: $year and month: $month";
echo $this->calendar->generate($year, $month);

What do you get if you try echo
"Selected year: ".$this->uri->segment(1)." and month: ".$this->uri->segment(2);
I'm pretty sure the index is relative based on the default_controller path setting in the routes.php config.

Related

Functions in controllers and blade - Laravel

I'm slowly starting to come to grip with Laravel but keep having little issues doing basic things.
So this is what I have at the moment
A function and a function that is called by my route both in my webcontroller.php
// Function for printing out copyright year
function copyright_info($begin_year = NULL)
{
date_default_timezone_set('Europe/London');
if(empty($begin_year) || $begin_year == date('Y'))
echo date('Y');
else
echo $begin_year." - ".date('Y');
}
// function being called by route.php to get Restaurant Page
public function restaurant () {
$cookie = Cookie::get("basket");
return view('pages.restaurant', ['basket' => $cookie]);
}
Now all the first function does is print out something like 2013-2015 once the year is provided.
So I should be able to do something like this
public function restaurant () {
// use the function and get copyright year
$year = copyright_info('2013')
$cookie = Cookie::get("basket");
// pass data to the view including the year we just created
return view('pages.restaurant', ['basket' => $cookie, 'year' => $year]);
}
Now in my restaurant.blade.php file, I'm including my footer in my includes folder that is generic to all my pages like this #include('includes.footer'). Now the footer is what actually contains a div that requires the $year I have passed to the restaurant view. in my footer.blade.php I have this
<p style="font-size: 0.9rem">Copyright © {{ $year }} | xxx.com Limited</p>
Now I would assume that when I pass data to restaurant and footer is included in restaurant the data will apply to footer when it gets included in restaurant but that doesn't happpen.
After a lot of testing, I have now found out that my function doesn't produce any data at all. This is not because the function doesn't work also because in normal PHP it does
Any guidance appreciated
Try to pass $year from restaurant.blade to footer.blade
#include('includes.footer', ['year'=>$year])
So I figured it out.
Laravel will add the variable regardless of whether it is used in the main view or the include
Always, always make sure that your functions return something. From the question you can see that my function uses echo
Hope this helps someone in the future.

CodeIgniter - Routing issues (four segments)

Following what I thought was an issue with $this->uri->segment(), I figured out that it is actually a routing issue. Problem is that I can't really figure out what is wrong, as it looks exactly like another route I am using, which works fine, except this one has two variable segments, rather than one (for the route that is working).
The file I am trying to show is located in:
[main folder]/application/views/tasks/calendar/calendar.php
And I can load it with the command:
$route['tasks/calendar'] = 'tasks/calendar';
However, when I want to pass the current year and month as the last two segments, it does not work:
$route['tasks/calendar/(:num)/(:num)'] = 'tasks/calendar/$1/$2';
To my knowledge this should mean that a link like this should work:
(...)/index.php/tasks/calendar/2015/03
However, it does not. The full routes.php looks like this:
$route['auth/(:any)'] = 'auth/view/$1';
$route['auth'] = 'auth';
$route['projects/delete/(:any)'] = 'projects/delete/$1';
$route['projects/create'] = 'projects/create';
$route['projects/(:any)'] = 'projects/view/$1';
$route['projects'] = 'projects';
$route['(:any)'] = 'pages/view/$1';
$route['default_controller'] = 'pages/view';
$route['category'] = 'category';
$route['category/(:any)'] = 'category/view/$1';
$route['tasks/create'] = 'tasks/create';
$route['tasks/calendar/(:num)/(:num)'] = 'tasks/calendar/$1/$2';
$route['tasks/calendar'] = 'tasks/calendar';
$route['tasks'] = 'tasks';
$route['tasks/(:any)'] = 'tasks/view/$1';
And my controller, tasks.php, looks like this:
public function calendar($year = null, $month = null) {
// Calender configuration (must be done prior to loading the library
$conf = array(
'start_day' => 'monday',
'show_next_prev' => true,
'next_prev_url' => base_url() . 'index.php/tasks/calendar'
);
// Load libraries and helpers
$this->load->library('calendar',$conf);
// Set variables for $data array
$data['year'] = $year;
$data['month'] = $month;
// Show page, including header and footer
$this->load->view('templates/header', $data);
$this->load->view('tasks/calendar', $data);
$this->load->view('templates/footer');
}
And the very simple view file, calendar.php, looks like this:
<?php
echo "Selected year: ".$year." and month: ".$month;
echo $this->calendar->generate($year, $month);
What the heck am I doing wrong? The delete routes for projects works just fine...
To build on what #Craig and #CodeGodie have just said, you need to re-order your route definitions slightly.
$route['tasks'] = 'tasks/index';
// Initial route that will use $year=null, $month=null
$route['tasks/calendar'] = 'tasks/calendar';
// This route will use whatever $year, $month the user provides
$route['tasks/calendar/(:num)/(:num)'] = 'tasks/calendar/$1/$2';
You may also want to set $year=null, $month=null to valid values.
$today = getdate();
if(is_null($year) || is_null($month)){
$year = $today['year'];
$month = $today['month']
}
The problem are your routes order. These routes:
$route['(:any)'] = 'pages/view/$1';
$route['default_controller'] = 'pages/view'
should be at the very bottom of your routes list or else they will be seen prior your tasks routes.
Reference: Codeigniter User Guide - URI Routing
Note: Routes will run in the order they are defined. Higher routes
will always take precedence over lower ones.

Issue using CJuiDatePicker with different formats

I am using CJuiDatePicker in my form and I need to use two different formats: mm/dd/yy to be shown and dd/mm/yy to be sent in $_POST.
$questionario->widget('zii.widgets.jui.CJuiDatePicker', array(
'model' => $modeloDoQuestionario,
'attribute' => 'data_preenchimento',
'language' => 'en',
'options' => array(
'showAnim' => 'fold',
'showButtonPanel' => true,
'showOn' => 'both',
'dateFormat' => 'dd/mm/yy',
'altField' => '#Questionarios_data_preenchimento',
'altFormat' => 'mm/dd/yy',
),
'htmlOptions' => array(
'style' => 'height:14px;'
),
));
This is the field in HTML:
<input style="height:14px;" id="Questionarios_data_preenchimento" name="Questionarios[data_preenchimento]" type="text" />
But I still get the mm/dd/yy format in $_POST... What can be wrong?
You can put in the configuration file: 'main.php' something like this:
'widgetFactory' => array(
'widgets' => array(
'CJuiDatePicker' => array(
'scriptFile' => 'jquery-ui.min.js',
'language' => 'en',
'options' => array(
'dateFormat' => 'dd/mm/yy',
'showAnim' => 'fold',
'fontSize' => '0.85em',
),
),
),
),
With this ever that you call a 'CJuiDatePicker' widget will inherit this format.
I was looking for the same thing and have a slightly different solution.
I was mainly looking for on form pages to display the date as DD-MM-YYYY and save in the database as YYYY-MM-DD.
Regardless of changing the dateFormat option on CJuiDatePicker and even trying to use altFormat (using altField as well as apparently this is necessary) option, the date did not show in the desired format, granted if I were to change the date, the format would be shown correctly.
So I created a Custom class in components and created two methods, one to reformat the date to the DD-MM-YYYY format and one to format the date to the correct YYYY-MM-DD to be saved in the database.
Here is the Custom class (the file is called Custom.php and kept in components.)
class Custom
{
/*
**This method formats the date to be human readble ie 21-06-2013
*/
public function reformatDate($date)
{
if($date == '0000-00-00')
{
$newDate = '00-00-0000';
return $newDate;
}
elseif($date == '')
{
return $date;
}
else
{
$newDate = date("d-m-Y", strtotime($date));
return $newDate;
}
}
/*
**This method formats the date to the correct format according to the database
*/
public function formatDate($date)
{
if($date == '00-00-0000')
{
$newDate = '0000-00-00';
return $newDate;
}
elseif($date == '')
{
return $date;
}
else
{
$newDate = date("Y-m-d", strtotime($date));
return $newDate;
}
}
}
Now that I had methods to change the dates to the correct formats. On the _form page I declared at the top, under the initiation of the form.
$model->date_required = Custom::reformatDate($model->date_required);
$model->date_created = Custom::reformatDate($model->date_created);
$model->date_completed = Custom::reformatDate($model->date_completed);
This now results in the date being shown correctly, both when the _form page is viewed and the date is changed via the CJuiDatePicker as i still use the dateFormat option to show the correct format when the date is changed.
Lastly I added to both the create and update actions of the controller the following.
if(isset($_POST['Tickets']))
{
$model->attributes=$_POST['Tickets'];
$model->date_created = Custom::formatDate($model->date_created);
$model->date_required = Custom::formatDate($_POST['Tickets']['date_required']);
$model->date_completed = Custom::formatDate($_POST['Tickets']['date_completed']);
if($model->save())
So before the data is then saved back to the database I format the date to the correct format and pop it into the database.
I'm not expert and only a few month into Yii and about 9 months into PHP. I know there are all sorts of before and after save methods and this may not be the best way to do it, in fact if there is a better way I am all ears. But for now this is working for me. hope ths helps someone.
/* Small Update */
After speaking with a colleague who has been doing this stuff for about a decade. he said it would be much cleaner to remove the code I placed on the form page under the form initiation and move it rather into the controller, so for example my update method appears like so
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$model->date_required = Custom::reformatDate($model->date_required);
$model->date_created = Custom::reformatDate($model->date_created);
$model->date_completed = Custom::reformatDate($model->date_completed);
So rather than reformatting the dates on the form page, it is done directly after loadModel, keeping the view cleaner.

CodeIgniter - Variable scope

I have a controller which I use for a login form. In the view, I have a {error} variable which I want to fill in by using the parser lib, when there is an error. I have a function index() in my controller, controlled by array $init which sets some base variables and the error message to '':
function index()
{
$init = array(
'base_url' => base_url(),
'title' => 'Login',
'error' => ''
);
$this->parser->parse('include/header', $init);
$this->parser->parse('login/index', $init);
$this->parser->parse('include/footer', $init);
}
At the end of my login script, I have the following:
if { // query successful }
else
{
$init['error'] = "fail";
$this->parser->parse('login/index', $init);
}
Now, of course this doesn't work. First of all, it only loads the index view, without header and footer, and it fails at setting the original $init['error'] to (in this case) "fail". I was trying to just call $this->index() with perhaps the array as argument, but I can't seem to figure out how I can pass a new $init['error'] which overrides the original one. Actually, while typing this, it seems to impossible to do what I want to do, as the original value will always override anything new.. since I declare it as nothing ('').
So, is there a way to get my error message in there, or not? And if so, how. If not, how would I go about getting my error message in the right spot? (my view: {error}. I've tried stuff with 'global' to bypass the variable scope but alas, this failed. Thanks a lot in advance.
$init musst be modified before generating your view.
To load your header and footer you can include the following command and the footer's equivalent into your view.
<?php $this->load->view('_header'); ?>
to display errors, you can as well use validation_errors()
if you are using the codeigniter form validation.
if you are using the datamapper orm for codeigniter you can write model validations, and if a query fails due to validation rule violation, you get a proper error message in the ->error property of your model.
Code for your model:
var $validation = array(
'user_name' => array(
'rules' => array('required', 'max_length' => 120),
'label' => 'Name'
)
);
You might try this:
function index() {
$init = array(
'base_url' => base_url(),
'title' => 'Login',
'error' => ''
);
$string = $this->parser->parse('include/header', $init, TRUE);
$string .= $this->parser->parse('login/index', $init, TRUE);
$string .= $this->parser->parse('include/footer', $init, TRUE);
$this->parser->parse_string(string);
}
In parse()you can pass TRUE (boolean) to the third parameter, when you want data returned instead of being sent (immediately) to the output class. By the other hand, the method parse_string works exactly like `parse(), only accepts a string as the first parameter in place of a view file, thus it works in conjunction.

change CakePhp1.3 paginator destination url?

I'm new to cakephp...and I have a page with a url this:
http://localhost/books/filteredByAuthor/John-Doe
so the controller is ´books´, the action is ´filteredByAuthor´ and ´John-Doe´ is a parameter.. but the url looks ugly so i've added a Route like this:
Router::connect('/author/:name', array( 'controller' => 'books','action' => 'filteredByAuthor'), array('pass'=>array('name'),'name'=>".*"));
and now my link is:
http://localhost/author/John-Doe
the problem is that the view has a paginator and when i change the page (by clicking on the next or prev button).. the paginator won't consider my routing... and will change the url to this
http://localhost/books/filteredByAuthor/John-Doe/page:2
the code on my view is just:
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
the documentation doesn't say anything about avoiding this and i've spent hours reading the paginators source code and api.. and in the end i just want my links to be something like this: (with the sort and direction included on the url)
http://localhost/author/John-Doe/1/name/asc
Is it possible to do that and how?
hate to answer my own question... but this might save some time to another developper =) (is all about getting good karma)
i found out that you can pass an "options" array to the paginator, and inside that array you can specify the url (an array of: controller, action and parameters) that the paginator will use to create the links.. so you have to write all the possible routes in the routes.php file. Basically there are 3 possibilities:
when the "page" is not defined
For example:
http://localhost/author/John-Doe
the paginator will assume that the it's the first page. The corresponding route would be:
Router::connect('/author/:name', array( 'controller' => 'books','action' => 'filteredByAuthor'),array('pass'=>array('name'),'name'=>'[a-zA-Z\-]+'));
when the "page" is defined
For example:
http://localhost/author/John-Doe/3 (page 3)
The route would be:
Router::connect('/author/:name/:page', array( 'controller' => 'books','action' => 'filteredByAuthor'),array('pass'=>array('name','page'),'name'=>'[a-zA-Z\-]+','page'=>'[0-9]+'));
finally when the page and the sort is defined on the url (by clicking on the sort links created by the paginator).
For example:
http://localhost/author/John-Doe/3/title/desc (John Doe's books ordered desc by title)
The route is:
Router::connect('/author/:name/:page/:sort/:direction', array( 'controller' => 'books','action' => 'filteredByAuthor'),
array('pass'=>array('name','page','sort','direction'),
'name'=>"[a-zA-Z\-]+",
'page'=>'[0-9]*',
'sort'=>'[a-zA-Z\.]+',
'direction'=>'[a-z]+',
));
on the view you have to unset the url created by the paginator, cause you'll specify your own url array on the controller:
Controller:
function filteredByAuthor($name = null,$page = null , $sort = null , $direction = null){
$option_url = array('controller'=>'books','action'=>'filteredByAuthor','name'=>$name);
if($sort){
$this->passedArgs['sort'] = $sort;
$options_url['sort'] = $sort;
}
if($direction){
$this->passedArgs['direction'] = $direction;
$options_url['direction'] = $direction;
}
Send the variable $options_url to the view using set()... so in the view you'll need to do this:
View:
unset($this->Paginator->options['url']);
echo $this->Paginator->prev(__('« Précédente', true), array('url'=>$options_url), null, array('class'=>'disabled'));
echo $this->Paginator->numbers(array('separator'=>'','url'=>$options_url));
echo $this->Paginator->next(__('Suivante »', true), array('url'=>$options_url), null, array('class' => 'disabled'));
Now, on the sort links you'll need to unset the variables 'sort' and 'direction'. We already used them to create the links on the paginator, but if we dont delete them, then the sort() function will use them... and we wont be able to sort =)
$options_sort = $options_url;
unset($options_sort['direction']);
unset($options_sort['sort']);
echo $this->Paginator->sort('Produit <span> </span>', 'title',array('escape'=>false,'url'=>$options_sort));
hope this helps =)

Categories