Adding URL Variable on CodeIgniter - php

I want to add a new URL variable on CI 3.0 like site_url or base_url.
For example; I want to add an admin_url variable for administration area and assets_url variable for assets.
I checked CI 3.0 guide but couldn't find a solution.
Thanks in advance.

It's pretty straight forward.
Just go to your config.php which is located at /your_root/application/config directory
add at this line at the bottom of that file
$config["admin_url"] = "http://www.your_url.com/admin";
$config["assets_url"] = "http://www.your_url.com/assets";
To retrieve it anywhere in application use this
$your_admin_variable =$this->config->item("admin_url");
$your_assets_variable =$this->config->item("assets_url");
Your're in business :)

My solution.
Create new helper file and add this file to autoload.
So..
Create file application/helpers/global_helper.php
Inside your helper create functions for example:
<?php
function admin_url(){
return base_url() . "/admin/";
}
Now edit config/autoload.php
$autoload['helper'] = array('url','global');
Add to exists array your new helper.
And now anywhere you can use your function admin_url

in system/helpers/url_helper.php you will find
if ( ! function_exists('base_url'))
{
function base_url($uri = '')
{
$CI =& get_instance();
return $CI->config->base_url($uri);
}
}
so i guess if you create your own code like this
if ( ! function_exists('your_variable_name'))
{
function your_variable_name($uri = '')
{
$CI =& get_instance();
return $CI->config->your_variable_name($uri);
}
}
but it is better to extend the helper rather modifying it , so you can use the code above in application/helpers/MY_url_helper.php
and then you can call your custom variable as you normally do it with base_url
hope that helps

I got the answer now,
add these lines on system/helpers/url_helper.php file:
if ( ! function_exists('admin_css'))
{
/**
* Base URL
*
* Create a local URL based on your basepath.
* Segments can be passed in as a string or an array, same as site_url
* or a URL to a file can be passed in, e.g. to an image file.
*
* #param string $uri
* #param string $protocol
* #return string
*/
function admin_css($uri = '', $protocol = NULL)
{
return get_instance()->config->admin_css($uri, $protocol);
}
}
and add these lines on system/core/Config.php
public function admin_css($uri = '', $protocol = NULL)
{
$base_url = base_url('assets/staff/css').'/';
if (isset($protocol))
{
$base_url = $protocol.substr($base_url, strpos($base_url, '://'));
}
if (empty($uri))
{
return $base_url.$this->item('index_page');
}
$uri = $this->_uri_string($uri);
if ($this->item('enable_query_strings') === FALSE)
{
$suffix = isset($this->config['url_suffix']) ? $this->config['url_suffix'] : '';
if ($suffix !== '')
{
if (($offset = strpos($uri, '?')) !== FALSE)
{
$uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset);
}
else
{
$uri .= $suffix;
}
}
return $base_url.$this->slash_item('index_page').$uri;
}
elseif (strpos($uri, '?') === FALSE)
{
$uri = '?'.$uri;
}
return $base_url.$this->item('index_page').$uri;
}
don't forget to autoload url_helper. With this way, you can use admin_css variable like this: <?php echo admin_css('foo.css'); ?>
If you use the other answers on this post, you can not use like <?php echo admin_css('foo.css'); ?>
Thank you all.

Related

phpunit how to test a method which uses the browser url

I have the following methods:
public function isAdmin()
{
$adminUrl = $this->getPage(2)->httpUrl;
/*
* Remove all segments except the first in the URL path
* to detect if current page is in admin view
*/
$currentUrl = preg_replace( // https://regex101.com/r/D0mOz9/1
sprintf(
'~(?<adminUrl>%s)(?<remove>.*)$~',
addslashes($adminUrl)
),
'$1',
$this->getPage()->httpUrl
);
return $adminUrl == $currentUrl || (!$currentUrl && !$this->getPage() instanceof NullPage);
}
public function getPage($page = null)
{
$wiredPage = $this->wire('page');
if (!is_null($wiredPage) && is_null($page)) {
$baseUrl = $this->wire('page')->url;
$urlSegmentStr = $this->wire('input')->urlSegmentStr;
if (strlen($urlSegmentStr)) {
$baseUrl = rtrim($baseUrl, '/') . "/$urlSegmentStr/";
}
return $this->pages->get($baseUrl);
}
if (is_null($page)) {
return $this->pages->get(parse_url(getenv('REQUEST_URI'), PHP_URL_PATH));
}
return $this->pages->get($page);
}
I check if for an admin page by getting the url to the admin page and compare it to the current url.
Now I want to write a test for it with PHPunit but I have no idea how to test a method which result is based on urls like this.
Is it possible to write a test for a case like this? How would I be able to do this?

how to make nice rewrited urls from a router

I'm making a toolkit for php applications. I've a made a routing system based on some conventions, it works well but i would like to learn how to make mod_rewrite rules or any other stuff to finally make the url good to see and good for seo.
The route system starts from a config file that set the app and url roots.
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
The route always get start from index.php, wich makes instances of controllers#actions from GET parameters controllers=?&action=?
This is the index.php
<?php
include_once 'controller/Frontend.php';
require 'libraries/Router.php';
$params=array();
if(isset($_GET['controller'])&&isset($_GET['action'])){
$c = $_GET['controller'];
$a = $_GET['action'];
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_GET);
$queryValues = array_values($_GET);
for ($i=2;$i<count($queryParams);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
if ($_POST) {
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_POST);
$queryValues = array_values($_POST);
for ($i=0;$i<count($_POST);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
}
include_once APP_ROOT."/controller/$c.php";
$controller = new $c();
$controller->$a($params);
} else {
//attiva controller predefinito
$controller = new Frontend();
$controller->index();
}
This allow to select what controller and what action the router must call.
The router function here get the APP URL from settings.php in the root. You give im the two controllers#action params as string and it make the URL like so:
index.php?controller=X&action=Y&[params...]
<?php
require './settings.php';
function router($controller,$action,$query_data="") {
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = APP_URL."index.php?controller=$controller&action=$action&$param";
return $url;
}
function relativeRouter ($controller,$action,$query_data=""){
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = "index.php?controller=$controller&action=$action&$param";
return $url;
}
function redirectToOriginalUrl() {
$url = $_SERVER['HTTP_REQUEST_URI'];
header("location: $url");
}
function switchAction ($controller, $action) {
$r = router($controller, $action);
header("location:$r", true, 302);
}
In templates file i call router('controller,'action') to retrive url's to actions and also pass GET/POST data (collected from index.php that put's them into the method signature as array).
Don't blame me for using global POST/GET without filtering i'm still developing the thing, security things will be made after ;)
What i would like to ask if someone could share some thoughts on how to make pretty urls like site/page/action....
For example www.site.com/blog/post?id=1
(Actually the N params in the router function ($query_data) works this way, you pass array['id' => '1'] and you get ?id=1)
What are best strategies to make good urls?
Thank you so much, still learning PHP.
If there are best way to do such things just give your feedback.
I found myself an answer to the question, i post here maybe it's useful.
I've added a .htaccess file in the root:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
This will return each request to the root/index.php file.
Index file collect routes from the HTTP request, check if the route exist in the "routes.json" file.
URL are written in this way:
site.com/controller/action. GET params are written as follows
site.com/controller/action/[params]/[value]...... This output for example site.com/blog/post/id/1
That should be also fine for REST.
Here the index.php
<?php
require 'controller/Frontend.php';
require 'Class/Router.php';
//require 'libraries/Router.php';
/*
* ** ROUTING SETTINGS **
*/
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
$basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1));
$uri = substr($_SERVER['REQUEST_URI'], strlen($basepath));
//echo $uri;
if ($uri == "/") {
$frontend = new Frontend();
$frontend->index();
} else {
$root = ltrim ($uri, '/');
//$paths = explode("/", $uri);
$paths = parse_url($root, PHP_URL_PATH);
$route = explode("/",$paths);
$request = new \PlayPhp\Classes\Request();
// controller
$c = $route[0];
// action
$a = $route[1];
$reverse = Router::inverseRoute($c,$a);
$rest = $_SERVER['REQUEST_METHOD'];
switch ($rest) {
case 'PUT':
//rest_put($request);
break;
case 'POST':
if (Router::checkRoutes($reverse, "POST")) {
foreach ($_POST as $name => $value) {
$request->setPost($name,$value);
}
break;
} else {
Router::notFound($reverse,"POST");
}
case 'GET':
if (Router::checkRoutes($reverse, "GET")) {
for ($i = 2; $i < count($route); $i++) {
$request->setGet($route[$i], $route[++$i]);
}
break;
} else {
Router::notFound($reverse,"GET");
}
break;
case 'HEAD':
//rest_head($request);
break;
case 'DELETE':
//rest_delete($request);
break;
case 'OPTIONS':
//rest_options($request);
break;
default:
//rest_error($request);
break;
}
include_once APP_ROOT.'controller/'.$c.'.php';
$controller = new $c();
$controller->$a($request);
}
The Router class:
<?php
include 'config/app.php';
/*
* Copyright (C) 2015 yuri.blanc
*/
require 'Class/http/Request.php';
class Router {
protected static $routes;
private function __construct() {
Router::$routes = json_decode(file_get_contents(APP_ROOT.'config/routes.json'));
}
public static function getInstance(){
if (Router::$routes==null) {
new Router();
}
return Router::$routes;
}
public static function go($action,$params=null) {
$actions = explode("#", $action);
$c = strtolower($actions[0]);
$a = strtolower($actions[1]);
// set query sting to null
$queryString = null;
if(isset($params)) {
foreach ($params as $name => $value) {
$queryString .= '/'.$name.'//'.$value;
}
return APP_URL."$c/$a$queryString";
}
return APP_URL."$c/$a";
}
public static function checkRoutes($action,$method){
foreach (Router::getInstance()->routes as $valid) {
/* echo $valid->action . ' == ' . $action . '|||';
echo $valid->method . ' == ' . $method . '|||';*/
if ($valid->method == $method && $valid->action == $action) {
return true;
}
}
}
public static function inverseRoute($controller,$action) {
return ucfirst($controller)."#".$action;
}
public static function notFound($action,$method) {
die("Route not found:: $action with method $method");
}
}
I use the json_decode function to parse the json object in stdClass().
The json file looks like this:
{"routes":[
{"action":"Frontend#index", "method":"GET"},
{"action":"Frontend#register", "method":"GET"},
{"action":"Frontend#blog", "method":"GET"}
]}
This way i can whitelist routes with their methods and return 404 errors while not found.
System is still quite basic but gives and idea and works, hope someone will find useful.

add custom function to Codeigniter config such as site_url() & base_url()

we need to have a new function such as base_url() , named main_site_url() to being able to use it exactly as the same as site_url().
I've just added this to main config file in application/config:
$config['main_site_url'] = 'http//iksna.com/';
and this code to /system/core/config.php
/**
* Main Site URL
* Returns main_site_url . index_page [. uri_string]
*
* #access public
* #param string the URI string
* #return string
*/
function main_site_url($uri = '')
{
if ($uri == '')
{
return $this->slash_item('main_site_url').$this->item('index_page');
}
if ($this->item('enable_query_strings') == FALSE)
{
$suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix');
return $this->slash_item('main_site_url').$this->slash_item('index_page').$this->_uri_string($uri).$suffix;
}
else
{
return $this->slash_item('main_site_url').$this->item('index_page').'?'.$this->_uri_string($uri);
}
}
// -------------------------------------------------------------
but now, it is not accessible by: main_site_url();
is it accessible by: $this->config->main_site_url();
i have this error when is use main_site_url();
error:
Call to undefined function main_site_url()
You can create your own by the following way:
Step 1:
In you application/config/config.php add this, $config['main_site_url'] = 'http//iksna.com/';
Step 2:
In system/core/Config.php add a new function main_site_url() like base_url(), site_url() which are already defined there:
public function main_site_url($uri = '', $protocol = NULL)
{
$main_site_url = $this->slash_item('main_site_url');
if (isset($protocol))
{
if ($protocol === '')
{
$main_site_url = substr($main_site_url, strpos($main_site_url, '//'));
}
else
{
$main_site_url = $protocol.substr($main_site_url, strpos($main_site_url, '://'));
}
}
return $main_site_url.ltrim($this->_uri_string($uri), '/');
}
Step 3:
Now add the following code in system/helpers/url_helper.php
if ( ! function_exists('main_site_url'))
{
function main_site_url($uri = '', $protocol = NULL)
{
return get_instance()->config->main_site_url($uri, $protocol);
}
}
Now you can use main_site_url() anywhere in your controllers, libraries and views just like base_url(), site_url() etc.
Go to
/system/application/libraries
Create one file named
custom_function.php
add function main_site_url inside custom_function.php
call function in controller file using
$this->custom_function->main_site_url();

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

Codeigniter my form helper

I am using form_helper in CodeIgniter:
$current = $this->lang->mci_current();
$uri = 'contact';
$url = $this->lang->mci_make_uri($current, $uri); // output "en/contact"
echo form_open($url);
Question:
how to modify form_helper to change it to default:
echo form_open('contact');
but with functionality I defined in previous code.
I am assuming, that I can make my own form helper
(../application/helpers/MY_form_helper.php)
there for how to modify it and how to use my own helper ?
If I prefix helper with "my_" that means I override default form_helper? Do I need to extend default form_helper?
This is what I managed to do:
Note: I am new in MVC and OOP, learning with CodeIgniter
My try:
if (!function_exists('form_open')) {
function form_open($action = '', $attributes = '', $hidden = array()) {
$CI = & get_instance();
$current = $CI->lang->mci_current();
$action = $CI->lang->mci_make_uri($current, $action);
if ($attributes == '') {
$attributes = 'method="post"';
}
// If an action is not a full URL then turn it into one
if ($action && strpos($action, '://') === FALSE) {
$action = $CI->config->site_url($action);
}
// If no action is provided then set to the current url
$action OR $action = $CI->config->site_url($CI->uri->uri_string());
$form = '<form action="' . $action . '"';
$form .= _attributes_to_string($attributes, TRUE);
$form .= '>';
// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
if ($CI->config->item('csrf_protection') === TRUE AND !(strpos($action, $CI->config->base_url()) === FALSE OR strpos($form, 'method="get"'))) {
$hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash();
}
if (is_array($hidden) AND count($hidden) > 0) {
$form .= sprintf("<div style=\"display:none\">%s</div>", form_hidden($hidden));
}
return $form;
}
}
Helpers in CI are not class(es). They are simply functions. Make your own helper and save them in application/helpers. Load the helpers as usual
$this->load->helper('helperName'); #your file name should be helperName_helper.php
If you want to extend the default helper(s) just append MY_ with the default helper name and save in the application/helpers as you said. This will add / override the default functions.

Categories