How can I detect if the user is on the homepage of my website with CakePhp?
May I use $this->webroot?
The goal is to do something only if the current page is the homepage.
Simply you can try this:
if ($this->request->here == '/') {
// some code
}
Also it is good to read this part of documentation:
You can use CakeRequest to introspect a variety of things about the
request. Beyond the detectors, you can also find out other information
from various properties and methods.
$this->request->webroot contains the webroot directory.
$this->request->base contains the base path.
$this->request->here contains the full address to the current request
$this->request->query contains the query string parameters.
You can find it by comparing the present page with webroot or base
if ($this->here == $this->webroot){ // this is home page }
OR
if ($this->here == $this->base.'/'){ // this is home page }
You can get it properly by checking against params like below:
if($this->params['controller']=='homes' && $this->params['action']=='index')
in this way you can check for any page of cakephp on view side
Assuming you are going to do something from the AppController, it's best to see if the current controller/action pair is the one you define as "homepage" (as Cake can route a user anywhere from the '/' route and you probably still want the logic to be triggered when the action is called directly with the full /controller/action URI and not just on /). In your AppController just add a check:
if ($this->name == 'Foo' && $this->action == 'bar') {
// Do your stuff here, like
echo 'Welcome home!';
}
That way it will trigger whenever the bar action is requested from the FooController. You can obviously also put this logic in the specific controller action itself (and that might make more sense since it's less overhead).
You can use $this->request->query['page'] to determine where you are,
if ( $this->request->query['page'] == '/' ){
//do something
}
Edit:
check $this->request object using echo debug($this->request), it contains many informations you can use. Here is a sample of what you get:
object(CakeRequest) {
params => array(
'plugin' => null,
'controller' => 'pages',
'action' => 'display',
'named' => array(),
'pass' => array(
(int) 0 => 'home'
)
)
data => array()
query => array()
url => false
base => ''
webroot => '/'
here => '/'
}
If your home page is home.ctp as mentionned by the cakePHP convention. In PagesController, you can change the display function to look like :
(added code starts at the comment /* Custom code start*/ )
public function display()
{
$path = func_get_args();
$count = count($path);
if (!$count) {
return $this->redirect('/');
}
$page = $subpage = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
/* Custom code start*/
if("home"==$page){
// your code here
}
/* Custom code end*/
$this->set(compact('page', 'subpage'));
try {
$this->render(implode('/', $path));
} catch (MissingTemplateException $e) {
if (Configure::read('debug')) {
throw $e;
}
throw new NotFoundException();
}
}
The way I achieved that was by using $this->params. If you use print_r($this->params);, you will see the content of that variable for you. It will return an array. You will see the difference of when you are versus when you are not in the home page. You will have to use one of the keys in $this->params to make your evaluations with an if statement. That was how I achieved it. Maybe you can find this approach useful too.
Related
I'm writing a small routing system for a project. It's not perfect and it's a custom solution that will map the url to their templates if requested from the user. I want to generate a dynamic page based on an unique id for each event inserted inside the database from the user. So if the user request the event 1234 it will get a page with the event detail at the url https://mysitedomain.com/event/1234. I need to understand how to achieve this with my code, I'm using a front controller and red bean as ORM to access the database.
Here is the code of my router. Any suggestion will be appreciated. for now I'm only able to serve the templates.
<?php
namespace Router;
define('TEMPLATE_PATH', dirname(__DIR__, 2).'/assets/templates/');
class Route {
private static $assets = ['bootstrap' => 'assets/css/bootstrap.min.css',
'jquery' => 'assets/js/jquery.min.js',
'bootstrapjs' => 'assets/js/bootstrap.min.js',
];
public static function init()
{
if( isset($_SERVER['REQUEST_URI']) ){
$requested_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH);
if( $requested_uri === '/' ){
echo self::serveTemplate('index', self::$assets);
}
elseif( $requested_uri != '/' ){
$requested_uri = explode('/', $_SERVER['REQUEST_URI']);
if( $requested_uri[1] === 'event' ){
echo self::serveTemplate('event', self::$assets, ['event_id' => 001] );
}
else{
echo self::serveTemplate($view, self::$assets);
}
}
}
}
private static function serveTemplate(string $template, array $data, array $event_id = null)
{
if( !is_null($event_id) ){
$data[] = $event_id;
ob_start();
extract($data);
require_once TEMPLATE_PATH."$template.php";
return ob_get_clean();
}
else{
ob_start();
extract($data);
require_once TEMPLATE_PATH."$template.php";
return ob_get_clean();
}
}
}
?>
Writing a router from scratch is a little complex, you have to play a lots with regular expression to accommodate various scenario of requested url and your router should handle HTTP methods like POST, GET, DELETE, PUT and PATCH.
You may want to use existing libraries like Fast Route, easy to use and it's simplicity could give you idea how it is created.
I wonder if I have some logic for my url routing, Using a custom coding php will be a better idea than using the Yii urlManager inside protected/config/main.php.
the "logic" mentioned above means some if{ ... }else{ ... } case, which I think keeping in the format of urlManager is a bad idea for Readability. But I am not sure is there other solution, or something I miss understand about urlManager, or may be my connect about MVC developing in Yii is not correct. So please correct me if I go wrong.
Here is what I want to do :
if the first parameter of url is 'admin' ,then take the 2nd parameter as controller name, take the 3rd parameter as action name, and route to the controller locate inside the 'admin' folder.
if first parameter of url is 'forum' & with only one more parameter, then route to 'Forum' controller while passing the 2nd parameter into action 'index'.
if first parameter of url is 'forum' & with more than one more parameter, then route to 'ForumPost' controller, passing all the parameter except the first one as a array into action 'index'.
Except the case mentioned above, go the default way as Yii do. first parameter for controller name, 2nd parameter as action name.
P.S. Readability and easy to maintenance is my first consider so I am avoid to using .htaccess (my partner don't know about .htaccess, only php)
Edit :
I have write my rounteController (sorry, not clean code. I will break it down into functions later)
public function actionIndex(){
$is_Admin = false;
$args = func_get_args ();
//Language handle
$arg_1 = strtolower ($args[0]);
if($arg_1 == 'fr' || $arg_1 == 'en' ){
setLanguage($arg_1);
array_shift($args);
}
//check if admin
$arg_1 = strtolower ($args[0]);
if($arg_1 == 'admin'){
$is_Admin = true;
array_shift($args);
//admin index
if(count($args) == 0){
$this->redirect(array('admin/'));
exit();
}
//controller in admin
$controllerName = strtolower ($args[0]);
if(count($args) == 1){
//controller only
$this->redirect(array('admin_'.$controllerName.'/'));
exit();
}elseif(count($args) == 2){
//controller + action
$controllerName = strtolower ($args[0]);
$actionName = strtolower ($args[1]);
$this->redirect(array('admin_'.$controllerName.'/'.$actionName));
exit;
}else{
//controller + action + parameter
$controllerName = strtolower ($args[0]);
$actionName = strtolower ($args[1]);
$para = $args[2];
if(is_numeric ($para){
// id parameter
$this->redirect(array(
'admin_'.$controllerName.'/'.$actionName,
'id'=>$para;
));
exit;
}else{
// string parameter
$this->redirect(array(
'admin_'.$controllerName.'/'.$actionName,
'str'=>$para;
));
exit;
}
}
}
//forum
$arg_1 = strtolower ($args[0]);
if($arg_1 == 'forum'){
if(count($args) < 2){
//only one more parameter after 'forum'
//rounte to 'forum' controller
$cateSlug = $arg_1 = strtolower ($args[1]);
$this->redirect(array(
'forum/index',
'cateSlug'=> $cateSlug)
);
exit();
}else{
//only one more parameter after 'forum'
//rounte to 'forumPost' controller
$cateSlug = strtolower ($args[1]);
$topicSlug = strtolower ($args[2]);
$this->redirect(array('
forumPost/index',
'cateSlug'=> $cateSlug,
'topicSlug'=> $topicSlug)
);
exit();
}
}
//----normal case ---
//site index
if(count($args) == 0){
$this->redirect(array('site/index'));
exit;
}
if(count($args) == 1){
//controller only
$controllerName = strtolower ($args[0]);
$this->redirect(array($controllerName.'/'));
exit;
}elseif(count($args) == 2){
//controller + action
$controllerName = strtolower ($args[0]);
$actionName = strtolower ($args[1]);
$this->redirect(array($controllerName.'/'.$actionName));
exit;
}else{
//controller + action + parameter
$controllerName = strtolower ($args[0]);
$actionName = strtolower ($args[1]);
$para = $args[2];
if(is_numeric ($para){
// id paremeter
$this->redirect(array(
$controllerName.'/'.$actionName,
'id'=>$para;
));
exit;
}else{
// string paremeter
$this->redirect(array(
$controllerName.'/'.$actionName,
'str'=>$para;
));
exit;
}
}
}
Edit 2 :
The $this->redirect() function is not direct to the controller.... It's still pass thought urlManager .....
I think you have realize modules:
admin;
forum;
and then you can use:
site.com/admin/ - admin panel
site.com/forum/ - forum
and also
site.com/site/index will be home page
it just first thing which I decided, this variant will right if you will have forum in one application with your web app.
My code is :
public function join_membership()
{
$this->layout = 'colorbox';
$membership_id = $this->Cookie->read('membership_id');
$membership = $this->Membership->find('first', array('conditions'=>array('Membership.id'=>$membership_id)));
$this->set('membership',$membership);
if($this->request->is('post'))
{
if($this->JoinMembership->save($this->request->data['JoinMembership']))
{
$this->redirect(array('action' => 'member_login'));
}
}
}
This code save the data in database properly but after that it displays blank page, it doesn't redirect to the given function.
Thanks in advance....
In case anybody has trouble telling where their whitespace/output is (like I did), put this small block right before your $this->redirect call:
$file = '';
$line = '';
if (headers_sent($file, $line)) {
die('Output in ' . $file . ' at line ' . $line);
}
It will stop your controller action and print out the exact file and line where the whitespace/output is.
Try with the following code into your if condition.
$this->redirect(array('controller' => 'Controller_Name', 'action' => 'member_login'));
You can also try to print something into if condition you used. Also use the else part and also print something into else part. Check it in debug mode 2.
1) Is the member_login action located in the same controller as join_membership? If no then add the Controller => "Some_Controller" key value paire to the array.
2) If one does not work, check if the if condition is working like so
if($this->JoinMembership->save($this->request->data['JoinMembership']))
{
debug("in");exit();
$this->redirect(array('action' => 'member_login'));
}
}
You should see "in" message if the if condition is returning true.
Please note that you can use
$this->redirect("action_name");
$this->redirect("/controller_name/action_name");
I'm building a tutorialsystem with codeigniter and would like to achieve the following URL structure:
/tutorials --> an introduction page with the list of all the categories
/tutorials/{a category as string} --> this will give a list of tutorials for the given category, e.g. /tutorials/php
/tutorials/{a category as string}/{an ID}/{tutorial slug} --> this will show the tutorial, e.g. /tutorials/php/123/how-to-use-functions
/tutorials/add --> page to add a new tutorial
The problem is that when I want to use the first two types of URLs, I'd need to pass parameters to the index function of the controller. The first parameter is the optional category, the second is the optional tutorial ID. I've did some research before I posted, so I found out that I could add a route like tutorials/(:any), but the problem is that this route would pass add as a parameter too when using the last URL (/tutorials/add).
Any ideas how I can make this happen?
Your routing rules could be in this order:
$route['tutorials/add'] = "tutorials/add"; //assuming you have an add() method
$route['tutorials/(:any)'] = "tutorials/index"; //this will comply with anything which is not tutorials/add
Then in your controller's index() method you should be able to work out whether it's the category or tutorial ID is being passed!
I do think that a remap must be of more use to your problem in case you want to add more methods to your controller, not just 'add'. This should do the task:
function _remap($method)
{
if (method_exists($this, $method))
{
$this->$method();
}
else {
$this->index($method);
}
}
A few minutes after posting, I think I've found a possible solution for this. (Shame on me).
In pseudo code:
public function index($cat = FALSE, $id = FALSE)
{
if($cat !== FALSE) {
if($cat === 'add') {
$this->add();
} else {
if($id !== FALSE) {
// Fetch the tutorial
} else {
// Fetch the tutorials for category $cat
}
}
} else {
// Show the overview
}
}
Feedback for this solution is welcome!
I have a page with URL http://arslan/admin/category/index/0/name/asc/10 in Codeigniter.
In this URL, the uri_segment start from 0. This (0) is the default search value, name and asc are the default sort field and order, and 10 is the pagination index.
Now if I move to an add page with URL (http://arslan/admin/category/add/)
similarly like above "add" is the current function.
Now if i want to go back through a link to back page... How can I divert the user back? I can't make the URL go back.
Can somebody help me please?
I am not sure if i understand the question correctly, if not please ignore my answer, but I think you want a link to "go back to previous page", similar to the back-button in a web browser.
If so you could use javascript to solve this by simply using this line:
Go back
I extend the session class by creating /application/libaries/MY_Session.php
class MY_Session extends CI_Session {
function __construct() {
parent::__construct();
$this->tracker();
}
function tracker() {
$this->CI->load->helper('url');
$tracker =& $this->userdata('_tracker');
if( !IS_AJAX ) {
$tracker[] = array(
'uri' => $this->CI->uri->uri_string(),
'ruri' => $this->CI->uri->ruri_string(),
'timestamp' => time()
);
}
$this->set_userdata( '_tracker', $tracker );
}
function last_page( $offset = 0, $key = 'uri' ) {
if( !( $history = $this->userdata('_tracker') ) ) {
return $this->config->item('base_url');
}
$history = array_reverse($history);
if( isset( $history[$offset][$key] ) ) {
return $history[$offset][$key];
} else {
return $this->config->item('base_url');
}
}
}
And then to retrieve the URL of the last page visited you call
$this->session->last_page();
And you can increase the offset and type of information returned etc too
$this->session->last_page(1); // page before last
$this->session->last_page(2); // 3 pages ago
The function doesn't add pages called using Ajax to the tracker but you can easily remove the if( !IS_AJAX ) bit to make it do so.
Edit:
If you run to the error Undefined constant IS_AJAX, assumed IS_AJAX
add the line below to /application/config/constants.php
define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
There are two ways to solve your problem: First you could place a link that is using the javascript back-function onclick, like this ...
go back
... or you always save the current full page url into a cookie and use that for generating the back link - a helper could look like this (not tested) ...
/**
* save url to cookie
*/
if(!function_exists('urlhistory_save'))
{
function urlhistory_save()
{
$CI =& get_instance();
$CI->load->library('session');
$array = array(
'oldUrl' = $CI->session->userdata('newurl'),
'newurl' = $CI->uri->uri_string()
);
$CI->session->set_userdata($array);
}
}
/**
* get old url from cookie
*/
if(!function_exists('urlhistory_get'))
{
function urlhistory_get()
{
$CI =& get_instance();
$CI->load->library('session');
return $CI->session->userdata('oldurl');
}
}
In your controller you would use urlhistory_save() to save the current URL and in the view youd could use urlhistory_get() to retreive the old address like this:
<a href="<?php echo base_url().urlhistory_get(); ?>go back</a>
The most simplest way to redirect to your previous page , try this it work for me
redirect($this->agent->referrer());
you need to import user_agent library too $this->load->library('user_agent');
You can create a Session to go to back page as:
$this->session->set_userdata('ses_back_jobs','controller
name'.array_pop(explode('controller name',$this->input->server('REQUEST_URI'),2))); //Back page
Then if u want to redirect to some page use it:
redirect($this->session->userdata('ses_back_jobs'));
or use it to the anchor.