Create dynamic page with php - php

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.

Related

altorouter routes doesn't work

i'm trying to use altorouter for set routing map of my php project, at this moment the file routes.php is this
<?php
$router = new AltoRouter();
$router->setBasePath('/home/b2bmomo/www/');
/* Setup the URL routing. This is production ready. */
// Main routes that non-customers see
$router->map('GET','/', '', 'home');
$router->map( 'GET', '/upload.php', 'uploadexcel');
$match = $router->match();
// call closure or throw 404 status
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
?>
i have 2 files in the principal directory of my project, index.php and upload.php, what's wrong?
have you modified your .htaccess files to rewrite as per the altorouter site?
your routes look wrong. try like this:
// 1. protocol - 2. route uri -3. static filename -4. route name
$router->map('GET','/uploadexcel', 'upload.php', 'upload-route');
as it looks like you are wanting a static page (not a controller) try this (allows for both):
if($match) {
$target = $match["target"];
if(strpos($target, "#") !== false) { //-> class#method as set in routes above, eg 'myClass#myMethod' as third parameter in mapped route
list($controller, $action) = explode("#", $target);
$controller = new $controller;
$controller->$action($match["params"]);
} else {
if(is_callable($match["target"])) {
call_user_func_array($match["target"], $match["params"]); //call a function
}else{
require $_SERVER['DOCUMENT_ROOT'].$match["target"]; //for static page
}
}
} else {
require "static/404.html";
die();
}
which is pretty much from here: https://m.reddit.com/r/PHP/comments/3rzxic/basic_routing_in_php_with_altorouter/?ref=readnext_6
and get rid of that basepath line.
good luck
you car run class#function via "call_user_func_array":
if ($match) {
if (is_string($match['target']) && strpos($match['target'], '#') !== false) {
$match['target'] = explode('#', $match['target']);
}
if (is_callable($match['target'])) {
call_user_func_array($match['target'], $match['params']);
} else {
// no route was matched
header($_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
die('404 Not Found');
}
}

Wordpress add_rewrite_tag(), add_rewrite_rule(), and post_link()

I am trying to do the following:
Rewrite the URL structure of my WordPress installation so that a language field is in there. E.g. http://www.mydomain.com/lang/
I want to then take the input from /lang/ and use it to display the appropriate content. E.g. if lang is 'en' I will take custom fields in English and display the theme in English.
Here is what I have so far:
<?php
function add_directory_rewrite() {
global $wp_rewrite;
add_rewrite_tag('%lang%', '(.+)');
add_rewrite_rule('^/(.+)/', 'index.php?p=$matches[1]&lang=$matches[2]', 'top');
add_permastruct('lang', '%lang%');
}
add_action( 'init', 'add_directory_rewrite' );
?>
This works as far as getting the language but the problem I am facing is now the_permalink() has "/%lang%/" where /en/ is supposed to be or /fr/ or /de/ or whatever language. To add more detail my permalink structure is /%lang%/%category%/%postname%/ and lets say I have a category called food and a post with the title chicken, the_permalink will generate http://www.mydomain.com/%lang%/food/chicken/
Any idea what I'm doing wrong? Cheers.
You additionally need to add a function that will take the permalink that contains the erroneous '/%lang%/' segment, and replace it with the appropriate default language for the post. Typically you can do this either by the 'pre_post_link' filter, or the 'post_link' filter. If you use the former, you will be creating the permalink from scratch (totally custom urls that use nothing that core WP has to offer). If the latter is use, then you can filter the permalink after WP has done it's magic, but before it is used on the site. Here is an example:
function lou_rewrite_lang_in_permalink($permalink, $post, $leavename) {
// find the default post language via a function you have created to
// determine the default language url. this could be based on the current
// language the user has selected on the frontend, or based on the current
// url, or based on the post itself. it is up to you
$default_post_language = get_default_post_lang($post);
// once you have the default language, it is a simple search and replace
return str_replace('%lang%', $lang, $permalink);
}
add_filter('post_link', 'lou_rewrite_lang_in_permalink', 11, 3);
You don't mention it so I will. With your original solo function, you are gunna have a hard time if it is stand alone. The reason is because, though you have told the rewriter that a new url segment exists, you didn't tell WordPress to expect it as a url param. Thus, even though you have some fancy code to rewrite the url and tell WordPress the fancy lang param, WordPress does not know that it should be looking for it, and thus ignores it. You need to add something like this to rectify that:
function lou_add_lang_query_var($vars) {
// tell WP to expect the lang query_var, which you can then later use
$vars[] = 'lang';
// return the new list of query vars, which includes our lang param
return array_unique($vars);
}
add_filter('query_vars', 'lou_add_lang_query_var', 10, 1);
This will tell the WP() class that it needs to accept the 'lang' instead of just skipping over it. Then later you can do something like this to figure out that the current page sent as it's language:
function lou_somefunction() {
// do stuff
...
// access the $wp object
global $wp;
// determine the language from the query_vars of the current page
$lang = $wp->query_var['lang'];
// do other stuff with $lang
...
}
Hope this helps.
EDIT
First I want to say, this is an absolute travesty that language urls are not natively supported by WordPress. I have honestly never needed to do this, but most of my clients are not international companies, with international needs. I will be submitting something to WordPress in code form to solve this in a later version, but as of now, you will need a plugin like the one I have created below.
So I did a lot of investigation to make this happen. After a short conversation with the questioner, if found that my solution was incomplete. Naturally, I started digging. What seems like it should be an otherwise mediocre task, has turned out to be a VERY-not-mediocre task. The short version is, WordPress simply does not want you to insert extra parts of the url, in the middle or beginning of the url, on every url. You can easily do this with post urls ONLY with the above code, but anything more (pages, attachments, author pages, etc...) you must do something special. You can also add parts to the end of the url (endpoints), but even that is complicated.
I have worked with the WordPress rewriter extensively in the past and present, and I have what is considered Expert knowledge on the topic. Despite that, it still took me 4-5 hours to write something that will allow you to prepend a language indicator to all urls, that can then later be used to determine what language the page should be displayed in, regardless of page type. There is one catch, that I think is acceptable. You must know and specify exactly what language prefixes you want to support. I don't foresee this as a problem for anyone who would make use of this, but none-the-less, it is a limitation, simply because of the way that the rewrite engine works.
At long last, here is a plugin that you can use to accomplish this. I works on a barebone WP install, with a WooTheme as the theme. If you have other third party plugins installed, there is a possibility that this will not work for all their urls, depending on how they added their rewrite rules. In the short term, I will probably be converting this to a plugin for WP, and getting it up on Wordpress.org, but that is several days away, at least. Here is a working prototype of the code in plugin form. Create a new directory in your plugins folder (something like /wp-content/plugins/lou-lang), and then paste this code in a php file inside that folder (something like /wp-content/plugins/lou-lang/lou-lang.php). Then activate the plugin, via your admin dashboard, which will be labeled 'Loushou Language URLs'.
CODE:
<?php (__FILE__ == $_SERVER['SCRIPT_FILENAME']) ? die(header('Location: /')) : null;
/**
* Plugin Name: Loushou Language URLs
* Plugin URI: http://quadshot.com/
* Description: Adding the ability to have language support in your frontend urls.
* Version: 0.1-beta
* Author: Loushou
* Author URI: http://quadshot.com/
*/
class lou_rewrite_takeover {
protected static $add_rules = array();
public static function pre_init() {
// debug
add_action('admin_footer-options-permalink.php', array(__CLASS__, 'qsart_rewrite_debug'));
// add rw tag
add_action('init', array(__CLASS__, 'add_directory_rewrite'));
// rw rule adds
add_filter(is_admin() ? 'setup_theme' : 'do_parse_request', array(__CLASS__, 'do_parse_request'), 0);
add_filter('post_rewrite_rules', array(__CLASS__, 'post_rewrite_rules'));
add_filter('date_rewrite_rules', array(__CLASS__, 'date_rewrite_rules'));
add_filter('root_rewrite_rules', array(__CLASS__, 'root_rewrite_rules'));
add_filter('comments_rewrite_rules', array(__CLASS__, 'comments_rewrite_rules'));
add_filter('search_rewrite_rules', array(__CLASS__, 'search_rewrite_rules'));
add_filter('author_rewrite_rules', array(__CLASS__, 'author_rewrite_rules'));
add_filter('page_rewrite_rules', array(__CLASS__, 'page_rewrite_rules'));
add_filter('rewrite_rules_array', array(__CLASS__, 'final_rules_correction'), PHP_INT_MAX, 1);
// query vars
add_filter('query_vars', array(__CLASS__, 'add_lang_query_var'), 10, 1);
add_filter('request', array(__CLASS__, 'default_language'), 9);
// fix permalinks
$link_filters_needing_rewrite = array(
'post_link',
'post_type_link',
'page_link',
'attachment_link',
'search_link',
'post_type_archive_link',
'year_link',
'month_link',
'day_link',
'feed_link',
'author_link',
'term_link',
'category_feed_link',
'term_feed_link',
'taxonomy_feed_link',
'author_feed_link',
'search_feed_link',
'post_type_archive_feed_link',
);
add_filter('pre_post_link', array(__CLASS__, 'change_permalink_structure'), 10, 3);
foreach ($link_filters_needing_rewrite as $link_filter)
add_filter($link_filter, array(__CLASS__, 'rewrite_lang_in_permalink'), 11, 3);
}
public static function do_parse_request($cur) {
self::get_page_permastruct();
self::get_author_permastruct();
self::correct_extras();
return $cur;
}
public static function get_supported_langs() {
return apply_filters('lou-get-supported-languages', array(
'en',
));
}
public static function add_directory_rewrite() {
global $wp_rewrite;
$supported_languages = self::get_supported_langs();
add_rewrite_tag('%lang%', '('.implode('|', $supported_languages).')');
}
public static function unleadingslashit($str) {
return ltrim($str, '/');
}
public static function final_rules_correction($rules) {
global $wp_rewrite;
$new_rules = array();
$supported_languages = self::get_supported_langs();
$find = implode('|', $supported_languages);
$find_find = '#(?<!\()('.preg_quote($find, '#').')#';
$preg_node = str_replace('%%%', '(\d+)', preg_quote($wp_rewrite->preg_index('%%%'), '#'));
foreach ($rules as $k => $v) {
if (preg_match($find_find, $k)) {
$nk = preg_replace($find_find, '('.$find.')', $k);
$parts = explode('?', $v);
$index = array_shift($parts);
$pv = implode('?', $parts);
$pv = preg_replace_callback('#'.$preg_node.'#', function ($matches) use ($wp_rewrite) {
return $wp_rewrite->preg_index($matches[1]+1);
}, $pv);
$nv = $index.'?lang='.$wp_rewrite->preg_index(1).(!empty($pv) ? '&'.$pv : '');
$new_rules[$nk] = $nv;
} else {
$new_rules[$k] = $v;
}
}
return $new_rules;
}
public static function change_permalink_structure($struct) {
$struct = self::unleadingslashit($struct);
$struct = preg_replace('#^%lang%/?#', '', $struct);
return '/%lang%/'.$struct;
}
public static function extras_rewrite_rules($rules, $struct) {
global $wp_rewrite;
if ( is_array( $struct ) ) {
if ( count( $struct ) == 2 )
$new_rules = $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($struct[0]), $struct[1] );
else
$new_rules = $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($struct['struct']), $struct['ep_mask'], $struct['paged'], $struct['feed'], $struct['forcomments'], $struct['walk_dirs'], $struct['endpoints'] );
} else {
$new_rules = $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($struct) );
}
return $new_rules + $rules;
}
public static function post_rewrite_rules($rules) {
global $wp_rewrite;
// hack to add code for extras type urls (usually created by other plugins)
$func = array(__CLASS__, 'extras_rewrite_rules');
foreach ($wp_rewrite->extra_permastructs as $type => $struct) {
$filter = ($type == 'post_tag' ? 'tag' : $type).'_rewrite_rules';
add_filter($filter, function ($rules) use ($struct, $func) { return call_user_func_array($func, array($rules, $struct)); });
}
return $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($wp_rewrite->permalink_structure), EP_PERMALINK ) + $rules;
}
public static function date_rewrite_rules($rules) {
global $wp_rewrite;
return $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($wp_rewrite->get_date_permastruct()), EP_DATE) + $rules;
}
public static function root_rewrite_rules($rules) {
global $wp_rewrite;
return $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($wp_rewrite->get_date_permastruct()), EP_DATE) + $rules;
}
public static function comments_rewrite_rules($rules) {
global $wp_rewrite;
return $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($wp_rewrite->root . $wp_rewrite->comments_base), EP_COMMENTS, false, true, true, false) + $rules;
}
public static function search_rewrite_rules($rules) {
global $wp_rewrite;
return $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($wp_rewrite->get_search_permastruct()), EP_SEARCH) + $rules;
}
public static function author_rewrite_rules($rules) {
global $wp_rewrite;
return $wp_rewrite->generate_rewrite_rules( self::change_permalink_structure($wp_rewrite->get_author_permastruct()), EP_AUTHORS) + $rules;
}
public static function page_rewrite_rules($rules) {
global $wp_rewrite;
$page_structure = self::get_page_permastruct();
return $wp_rewrite->generate_rewrite_rules( $page_structure, EP_PAGES, true, true, false, false ) + $rules;
}
protected static function get_page_permastruct() {
global $wp_rewrite;
if (empty($wp_rewrite->permalink_structure)) {
$wp_rewrite->page_structure = '';
return false;
}
$wp_rewrite->page_structure = self::change_permalink_structure($wp_rewrite->root . '%pagename%');
return $wp_rewrite->page_structure;
}
protected static function get_author_permastruct() {
global $wp_rewrite;
if ( empty($wp_rewrite->permalink_structure) ) {
$wp_rewrite->author_structure = '';
return false;
}
$wp_rewrite->author_structure = self::change_permalink_structure($wp_rewrite->front . $wp_rewrite->author_base . '/%author%');
return $wp_rewrite->author_structure;
}
protected static function correct_extras() {
global $wp_rewrite;
foreach ($wp_rewrite->extra_permastructs as $k => $v)
$wp_rewrite->extra_permastructs[$k]['struct'] = self::change_permalink_structure($v['struct']);
}
public static function get_default_post_lang($post) {
return ( $lang = get_query_var('lang') ) ? $lang : 'en';
}
public static function rewrite_lang_in_permalink($permalink, $post=0, $leavename=false) {
// find the default post language via a function you have created to
// determine the default language url. this could be based on the current
// language the user has selected on the frontend, or based on the current
// url, or based on the post itself. it is up to you
$lang = self::get_default_post_lang($post);
// once you have the default language, it is a simple search and replace
return str_replace('%lang%', $lang, $permalink);
}
public static function add_lang_query_var($vars) {
// tell WP to expect the lang query_var, which you can then later use
$vars[] = 'lang';
// return the new list of query vars, which includes our lang param
return array_unique($vars);
}
public static function default_language($vars) {
if (array_diff( array_keys($vars), array('preview', 'page', 'paged', 'cpage') ))
$vars['lang'] = !empty($vars['lang']) ? $vars['lang'] : 'en';
return $vars;
}
public static function qsart_rewrite_debug() {
if (isset($_COOKIE['rwdebug']) && $_COOKIE['rwdebug'] == 1) {
global $wp_rewrite;
echo '<pre style="background-color:#ffffff; font-size:10px;">';
print_r($wp_rewrite->rules);
echo '</pre>';
}
}
}
if (defined('ABSPATH') && function_exists('add_action')) {
lou_rewrite_takeover::pre_init();
}
By default, the only language code supported by this plugin is 'en'. Obviously you need more than just that. Thus, once you have installed the plugin, you can add some code to your <theme>/functions.php file that looks something like this, to add the remainders.
function more_languages($list) {
$my_languages = array(
'de', 'zh', 'bg', 'fr'
);
return array_unique($list + $my_languages);
}
add_filter('lou-get-supported-languages', 'more_languages', 10, 1);
Once you have both installed the plugin and defined your custom languages, then you have one final step. You must save your permalinks. To do this from the admin, go to: Settings -> Permalinks -> Save Changes (button). After all of this, you should be good to go!
Hopefully this helps someone, and hopefully I can block out some time to get this up on wp.org.
The question is old but.. I was working on a lightweight solution for multi-language site and i came across the same problem. There is no easy way to do it with built-in WordPress functions. However (like mentioned by user1254824) there is a really easy trick to achieve it.
You can intercept the $_SERVER['REQUEST_URI'] global var, extract the /lang/ part and remove it before WordPress parsing. WordPress will serve you the regular page, but now you have your lang parameter in a var.
function localization_uri_process() {
global $lang; // then you can access $lang value in your theme's files
if( preg_match("%\A/([a-z]{2})/%", $_SERVER['REQUEST_URI'], $matches) ){
$lang = $matches[1];
$_SERVER['REQUEST_URI'] = preg_replace("%\A/[a-z]{2}/%", '/', $_SERVER['REQUEST_URI'] );
}
else
$lang = 'en'; // your default language
}
add_action( 'plugins_loaded', 'localization_uri_process' );
Then, you can also use filters to automatically rewrite all your links.
PS : The code need to be in a plugin. It won't work in your template php files.
I stumbled across this post while looking for a solution to put a language tag in front of the url path. While the wp_rewrite-solution is pretty much solid it kind of didn't work for my purpose (e.g. not having the language tag in front for the default language etc.).
So I took a closer look at the qTranslate-plugin and after I while I figured out that it uses a very simple and elegant solution:
Basically it does two things:
(Obviously) It changes all the Wordpress generated links (e.g. post_link, post_type_link, page_link etc.) to include the correct language tag in the url.
Instead of manipulating complex rewrite rules to have wordpress accept and correctly handle the language tag, it just hooks into "plugins_loaded" (that's right before Wordpress tries to parse the request) and manipulates $_SERVER['REQUEST_URI'] by cleaning out the language tag.
So if you e.g. call www.example.com/en/myurlpath Wordpress only "sees" www.example.com/myurlpath.
$_SERVER['REQUEST_URI'] = "/en/myurlpath" before the manipulation.
$_SERVER['REQUEST_URI'] = "/myurlpath" after the manipulation.
This way your only "job" is to clean up any urls before Wordpress is parsing them.

Yii and multilingual URLs

I'm trying to create multilingual application. I've implemented ability of translationable content and next step should be showing it to user. I want to have ability of changing language depending on URL. I've found a couple of components for those purposes but they all create urls which I don't like. For example, my application's default language is English and I have content which is translated into French. I have page "contacts", for instance. And URLs which will be generated by application will be: mysite.com/en/contacts, mysite.com/fr/contacts, but I want to have mysite.com/contacts for default language and mysite.com/fr/contacts for French language. It's simillar for site's root too. mysite.com/ - for default language and mysite.com/fr for French.
Is there any methods for implementing these functionality?
I'm using XUrlManager extension XUrlManager on GitHub
Yii generates URL's based on UrlManager rules. If you want URL's without /lang/ code - you need just create correct rules. For example, if you dublicate records in rules array:
'rules'=>array(
'<_c:\w+>/<_a:\w+>'=>'<_c>/<_a>',
'<language:\w{2}>/<_c:\w+>/<_a:\w+>'=>'<_c>/<_a>',
);
your URL's will be generated withou /en/ and /fr/, but URL's with code works too. By default, XUrlManager use previously selected language and store this in session or cookie.
If you want only hide /en/ and use /fr/ and others always, you can change your XUrlManager extension with:
public function createUrl($route,$params=array(),$ampersand='&')
{
if(!isset($params['language']) && Yii::app()->language!=='en')
$params['language']=Yii::app()->language;
return parent::createUrl($route,$params,$ampersand);
}
I've found very elegant method for solving my problem on http://www.elisdn.ru
Reimplement CHttpRequest
class DLanguageHttpRequest extends CHttpRequest
{
private $_requestUri;
public function getRequestUri()
{
if ($this->_requestUri === null)
$this->_requestUri = DMultilangHelper::processLangInUrl(parent::getRequestUri());
return $this->_requestUri;
}
public function getOriginalUrl()
{
return $this->getOriginalRequestUri();
}
public function getOriginalRequestUri()
{
return DMultilangHelper::addLangToUrl($this->getRequestUri());
}
}
Reimplement CUrlManager
class DLanguageUrlManager extends CUrlManager
{
public function createUrl($route, $params=array(), $ampersand='&')
{
$url = parent::createUrl($route, $params, $ampersand);
return DMultilangHelper::addLangToUrl($url);
}
}
Change config
return array(
'sourceLanguage'=>'en',
'language'=>'ru',
'components'=>array(
'request'=>array(
'class'=>'DLanguageHttpRequest',
...
),
'urlManager'=>array(
'class'=>'DLanguageUrlManager',
...
),
),
...
'params'=>array(
'translatedLanguages'=>array(
'ru'=>'Russian',
'en'=>'English',
'de'=>'Deutsch',
),
'defaultLanguage'=>'ru',
),
);
Create DMultilangHelper
class DMultilangHelper
{
public static function enabled()
{
return count(Yii::app()->params['translatedLanguages']) > 1;
}
public static function suffixList()
{
$list = array();
$enabled = self::enabled();
foreach (Yii::app()->params['translatedLanguages'] as $lang => $name)
{
if ($lang === Yii::app()->params['defaultLanguage']) {
$suffix = '';
$list[$suffix] = $enabled ? $name : '';
} else {
$suffix = '_' . $lang;
$list[$suffix] = $name;
}
}
return $list;
}
public static function processLangInUrl($url)
{
if (self::enabled())
{
$domains = explode('/', ltrim($url, '/'));
$isLangExists = in_array($domains[0], array_keys(Yii::app()->params['translatedLanguages']));
$isDefaultLang = $domains[0] == Yii::app()->params['defaultLanguage'];
if ($isLangExists && !$isDefaultLang)
{
$lang = array_shift($domains);
Yii::app()->setLanguage($lang);
}
$url = '/' . implode('/', $domains);
}
return $url;
}
public static function addLangToUrl($url)
if (self::enabled())
{
$domains = explode('/', ltrim($url, '/'));
$isHasLang = in_array($domains[0], array_keys(Yii::app()->params['translatedLanguages']));
$isDefaultLang = Yii::app()->getLanguage() == Yii::app()->params['defaultLanguage'];
if ($isHasLang && $isDefaultLang)
array_shift($domains);
if (!$isHasLang && !$isDefaultLang)
array_unshift($domains, Yii::app()->getLanguage());
$url = '/' . implode('/', $domains);
}
return $url;
}
}
After all of these steps your application will have URLs which you want
More information here

How to detect if the current page is the homepage with CakePhp?

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.

An example of an MVC controller

I have been reading a lot about how and why to use an MVC approach in an application. I have seen and understand examples of a Model, I have seen and understand examples of the View.... but I am STILL kind of fuzzy on the controller. I would really love to see a thorough enough example of a controller(s). (in PHP if possible, but any language will help)
Thank you.
PS: It would also be great if I could see an example of an index.php page, which decides which controller to use and how.
EDIT: I know what the job of the controller is, I just don't really understand how to accomplish this in OOP.
Request example
Put something like this in your index.php:
<?php
// Holds data like $baseUrl etc.
include 'config.php';
$requestUrl = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$requestString = substr($requestUrl, strlen($baseUrl));
$urlParams = explode('/', $requestString);
// TODO: Consider security (see comments)
$controllerName = ucfirst(array_shift($urlParams)).'Controller';
$actionName = strtolower(array_shift($urlParams)).'Action';
// Here you should probably gather the rest as params
// Call the action
$controller = new $controllerName;
$controller->$actionName();
Really basic, but you get the idea... (I also didn't take care of loading the controller class, but I guess that can be done either via autoloading or you know how to do it.)
Simple controller example (controllers/login.php):
<?php
class LoginController
{
function loginAction()
{
$username = $this->request->get('username');
$password = $this->request->get('password');
$this->loadModel('users');
if ($this->users->validate($username, $password))
{
$userData = $this->users->fetch($username);
AuthStorage::save($username, $userData);
$this->redirect('secret_area');
}
else
{
$this->view->message = 'Invalid login';
$this->view->render('error');
}
}
function logoutAction()
{
if (AuthStorage::logged())
{
AuthStorage::remove();
$this->redirect('index');
}
else
{
$this->view->message = 'You are not logged in.';
$this->view->render('error');
}
}
}
As you see, the controller takes care of the "flow" of the application - the so-called application logic. It does not take care about data storage and presentation. It rather gathers all the necessary data (depending on the current request) and assigns it to the view...
Note that this would not work with any framework I know, but I'm sure you know what the functions are supposed to do.
Imagine three screens in a UI, a screen where a user enters some search criteria, a screen where a list of summaries of matching records is displayed and a screen where, once a record is selected it is displayed for editing. There will be some logic relating to the initial search on the lines of
if search criteria are matched by no records
redisplay criteria screen, with message saying "none found"
else if search criteria are matched by exactly one record
display edit screen with chosen record
else (we have lots of records)
display list screen with matching records
Where should that logic go? Not in the view or model surely? Hence this is the job of the controller. The controller would also be responsible for taking the criteria and invoking the Model method for the search.
<?php
class App {
protected static $router;
public static function getRouter() {
return self::$router;
}
public static function run($uri) {
self::$router = new Router($uri);
//get controller class
$controller_class = ucfirst(self::$router->getController()) . 'Controller';
//get method
$controller_method = strtolower((self::$router->getMethodPrefix() != "" ? self::$router->getMethodPrefix() . '_' : '') . self::$router->getAction());
if(method_exists($controller_class, $controller_method)){
$controller_obj = new $controller_class();
$view_path = $controller_obj->$controller_method();
$view_obj = new View($controller_obj->getData(), $view_path);
$content = $view_obj->render();
}else{
throw new Exception("Called method does not exists!");
}
//layout
$route_path = self::getRouter()->getRoute();
$layout = ROOT . '/views/layout/' . $route_path . '.phtml';
$layout_view_obj = new View(compact('content'), $layout);
echo $layout_view_obj->render();
}
public static function redirect($uri){
print("<script>window.location.href='{$uri}'</script>");
exit();
}
}
<?php
class Router {
protected $uri;
protected $controller;
protected $action;
protected $params;
protected $route;
protected $method_prefix;
/**
*
* #return mixed
*/
function getUri() {
return $this->uri;
}
/**
*
* #return mixed
*/
function getController() {
return $this->controller;
}
/**
*
* #return mixed
*/
function getAction() {
return $this->action;
}
/**
*
* #return mixed
*/
function getParams() {
return $this->params;
}
function getRoute() {
return $this->route;
}
function getMethodPrefix() {
return $this->method_prefix;
}
public function __construct($uri) {
$this->uri = urldecode(trim($uri, "/"));
//defaults
$routes = Config::get("routes");
$this->route = Config::get("default_route");
$this->controller = Config::get("default_controller");
$this->action = Config::get("default_action");
$this->method_prefix= isset($routes[$this->route]) ? $routes[$this->route] : '';
//get uri params
$uri_parts = explode("?", $this->uri);
$path = $uri_parts[0];
$path_parts = explode("/", $path);
if(count($path_parts)){
//get route
if(in_array(strtolower(current($path_parts)), array_keys($routes))){
$this->route = strtolower(current($path_parts));
$this->method_prefix = isset($routes[$this->route]) ? $routes[$this->route] : '';
array_shift($path_parts);
}
//get controller
if(current($path_parts)){
$this->controller = strtolower(current($path_parts));
array_shift($path_parts);
}
//get action
if(current($path_parts)){
$this->action = strtolower(current($path_parts));
array_shift($path_parts);
}
//reset is for parameters
//$this->params = $path_parts;
//processing params from url to array
$aParams = array();
if(current($path_parts)){
for($i=0; $i<count($path_parts); $i++){
$aParams[$path_parts[$i]] = isset($path_parts[$i+1]) ? $path_parts[$i+1] : null;
$i++;
}
}
$this->params = (object)$aParams;
}
}
}
Create folder structure
Setup .htaccess & virtual hosts
Create config class to build config array
Controller
Create router class with protected non static, with getters
Create init.php with config include & autoload and include paths (lib, controlelrs,models)
Create config file with routes, default values (route, controllers, action)
Set values in router - defaults
Set uri paths, explode the uri and set route, controller, action, params ,process params.
Create app class to run the application by passing uri - (protected router obj, run func)
Create controller parent class to inherit all other controllers (protected data, model, params - non static)
set data, params in constructor.
Create controller and extend with above parent class and add default method.
Call the controller class and method in run function. method has to be with prefix.
Call the method if exisist
Views
Create a parent view class to generate views. (data, path) with default path, set controller, , render funcs to
return the full tempalte path (non static)
Create render function with ob_start(), ob_get_clean to return and send the content to browser.
Change app class to parse the data to view class. if path is returned, pass to view class too.
Layouts..layout is depend on router. re parse the layout html to view and render
Please check this:
<?php
global $conn;
require_once("../config/database.php");
require_once("../config/model.php");
$conn= new Db;
$event = isset($_GET['event']) ? $_GET['event'] : '';
if ($event == 'save') {
if($conn->insert("employee", $_POST)){
$data = array(
'success' => true,
'message' => 'Saving Successful!',
);
}
echo json_encode($data);
}
if ($event == 'update') {
if($conn->update("employee", $_POST, "id=" . $_POST['id'])){
$data = array(
'success' => true,
'message' => 'Update Successful!',
);
}
echo json_encode($data);
}
if ($event == 'delete') {
if($conn->delete("employee", "id=" . $_POST['id'])){
$data = array(
'success' => true,
'message' => 'Delete Successful!',
);
}
echo json_encode($data);
}
if ($event == 'edit') {
$data = $conn->get("select * from employee where id={$_POST['id']};")[0];
echo json_encode($data);
}
?>

Categories