Widget in CodeIgniter 3 - php

For a dashboard-app, I want to create a widget-component in my CI3-project. I found a similar question: How to create a widget system in Codeigniter, but it seems that this is either outdated or just not usable for CI3. Even the link with the "more information" results in a 404.
I googled that of course, but didn't find anything useful. One post was from 2013, which showed that example von the CI2 base.
However, maybe this plugin still works and I have an error in my setup.
I placed a file "Widget.php" in
/application/third_party/
with the following content:
class Widget
{
public $module_path;
function run($file) {
$args = func_get_args();
$module = '';
/* is module in filename? */
if (($pos = strrpos($file, '/')) !== FALSE) {
$module = substr($file, 0, $pos);
$file = substr($file, $pos + 1);
}
list($path, $file) = Modules::find($file, $module, 'widgets/');
if ($path === FALSE) {
$path = APPPATH.'widgets/';
}
Modules::load_file($file, $path);
$file = ucfirst($file);
$widget = new $file();
$widget->module_path = $path;
return call_user_func_array(array($widget, 'run'), array_slice($args, 1));
}
function render($view, $data = array()) {
extract($data);
include $this->module_path.'views/'.$view.EXT;
}
function load($object) {
$this->$object = load_class(ucfirst($object));
}
function __get($var) {
global $CI;
return $CI->$var;
}
}
In my application/widgets-folder, I have a file called News.php.
<?php
class News extends Widget
{
function run() {
die('here');
}
}
In application/libraries/ I placed a file widgetlib.php :
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class widgetlib {
function __construct() {
include(APPPATH . '/third_party/Widget.php');
}
}
and finally, in my view:
<?php widget::run("News"); ?>
Then I checked my autoloader-class in application/config/autoload.php:
$autoload['libraries'] =
'session',
'database',
'widgetlib'
);
This results in:
A PHP Error was encountered
Severity: Error
Message: Class 'Modules' not found
Filename: third_party/Widget.php
Line Number: 20
and
Severity: Runtime Notice
Message: Non-static method Widget::run() should not be called statically, assuming $this from incompatible context
Filename: views/index.php

Related

Php script into WordPress as page template

I am trying to integrate bought php script (yougrabber) into WordPress as page template.
Script works fine as standalone website. But when I try to insert it as a page template and open it I get the following error:
Warning: require_once(application/config/routes.php): failed to open
stream: No such file or directory in
/opt/lampp/htdocs/wordpress/wordpress/wp-content/themes/twentyseventeen/yougrabber/core/router.php
on line 55
Fatal error: require_once(): Failed opening required
'application/config/routes.php' (include_path='.:/opt/lampp/lib/php')
in
/opt/lampp/htdocs/wordpress/wordpress/wp-content/themes/twentyseventeen/yougrabber/core/router.php
on line 55
I think that script is expected to be loaded in root directory.
And this is how scripts index.php looks when I put it in theme directory and tell wp it is a page template.
<?php
/*
Template Name: TESTIRANJE
*/
?>
<?php
//error_reporting(E_ALL); //uncomment for development server
define("BASE_PATH", str_replace("\\", NULL, dirname($_SERVER["SCRIPT_NAME"]) == "/" ? NULL : dirname($_SERVER["SCRIPT_NAME"])) . '/');
require_once "core/router.php";
Router::init();
function __autoload($class) { Router::autoload($class); }
Router::route();
?>
Any help is appreciated. Thank you.
Edit:
router.php
<?php
class Router
{
private static $current_page;
private static $page_struct;
private static $is_router_loaded;
private function __construct()
{
self::$current_page = self::getPage();
self::$page_struct = explode("/", self::$current_page);
self::$page_struct = array_values(array_filter(self::$page_struct, 'strlen'));
}
public static function init()
{
if(self::$is_router_loaded instanceof Router) return self::$is_router_loaded;
else return self::$is_router_loaded = new Router;
}
public static function route()
{
self::loadAutoload();
if(!self::getController())
{
try {
self::loadDefaultPage();
}
catch(ConfigException $e) { return self::error404(); }
}
self::loadRewrites();
self::loadPostedPage();
}
private static function loadDefaultPage()
{
require('application/config/routes.php');
if(!is_array($routes["default_page"])) throw new ConfigException();
else
{
$controller_cname = 'application\\Controllers\\'.$routes['default_page'][0];
$controller_obj = new $controller_cname;
$controller_obj->$routes['default_page'][1]();
}
exit;
}
private static function loadAutoload()
{
require_once("application/config/routes.php");
require_once("/application/config/autoload.php");
$loader =\core\Loader::getInstance(true);
foreach($autoload['libraries'] as $library)
{
$loader->library($library);
}
foreach(array_unique($autoload['controllers']) as $controller)
{
if((strtolower(self::getController()) != strtolower($controller)) && (self::getController() != null && $routes['default_page'][0] == 'users')) $loader->controller($controller);
}
}
private static function loadRewrites()
{
require("application/config/routes.php");
foreach ($routes as $rewrittenPage => $realPage)
{
if(is_array($realPage)) continue;
if($rewrittenPage == str_replace(BASE_PATH, NULL, $_SERVER["REQUEST_URI"])) self::setPage($realPage);
else if(preg_match_all('#\[(.*)\]#U', $rewrittenPage, $param_names))
{
$getRegex = preg_replace("#\[.*\]#U", "(.*)", $rewrittenPage);
preg_match_all("#^\/?".$getRegex."$#", self::$current_page, $param_values); unset($param_values[0]);
if(in_array(null, $param_values)) continue;
else
{
$i = 0;
foreach($param_values as $p_value)
{
$realPage = str_replace('['.$param_names[1][$i].']', $param_names[1][$i].':'.$p_value[0], $realPage);
$i++;
}
self::setPage($realPage);
}
}
}
}
private static function loadPostedPage()
{
if(self::getController() != null && $controller = self::getController())
{
$controller = "application\\Controllers\\".$controller;
$controller = new $controller;
if(!self::getMethod())
{
if(method_exists($controller, 'index'))
{
$controller->index();
}
}
else
{
$method = self::getMethod();
if(!method_exists($controller, $method)) return self::error404();
$method_data = new ReflectionMethod($controller, $method);
if($method_data->isPublic() == true)
{
if(!self::getParameters())
{
if($method_data->getNumberOfRequiredParameters() == 0) $controller->$method(); else self::error404();
}
else
{
$parametersToSet = self::getParameters();
$sortParams = array();
foreach($method_data->getParameters() as $params)
{
if(!$params->isOptional() && !isset($parametersToSet[$params->getName()])) return self::error404 ();
if($params->isOptional() && !isset($parametersToSet[$params->getName()])) $sortParams[] = $params->getDefaultValue();
else $sortParams[] = $parametersToSet[$params->getName()];
}
$method_data->invokeArgs($controller, $sortParams);
}
} else return self::error404();
}
}
}
public static function error404()
{
header("HTTP/1.0 404 Not Found");
die(file_get_contents('application/errors/404.html'));
exit;
}
public static function autoload($className)
{
if(class_exists($className)) return true;
else
{
$className = strtolower(str_replace('\\', '/', $className));
if(!file_exists($className.'.php')) return self::error404();;
require_once $className .'.php';
}
}
private static function getController()
{
if(isset(self::$page_struct[0]))
return self::$page_struct[0];
}
private static function getMethod()
{
if(isset(self::$page_struct[1]))
return self::$page_struct[1];
}
private static function getParameters()
{
$parameters = array();
foreach(self::$page_struct as $place => $args)
{
if($place > 1 && strstr($args, ':'))
{
$parameter = explode(":", $args);
$parameters[$parameter[0]] = $parameter[1];
$_GET[$parameter[0]] = $parameter[1];
}
}
return $parameters;
}
public static function getPage()
{
$rpath = BASE_PATH == "/" ? NULL : BASE_PATH;
if(self::$current_page == null) self::$current_page = (
str_replace('?'.$_SERVER["QUERY_STRING"], NULL,
str_replace($rpath, NULL, $_SERVER["REQUEST_URI"])));
return self::$current_page;
}
private static function setPage($page)
{
self::$current_page = $page;
self::$page_struct = explode("/", self::$current_page);
self::$page_struct = array_filter(self::$page_struct, 'strlen');
}
}
class ConfigException Extends Exception {}
?>
After trying what #ArsalanMithani sugested, now getting:
Warning: require_once(): http:// wrapper is disabled in the server
configuration by allow_url_include=0 in
/opt/lampp/htdocs/wordpress/wordpress/wp-content/themes/twentyseventeen/core/router.php
on line 55
Warning:
require_once(http://localhost/wordpress/wordpress/wp-content/themes/twentyseventeen/application/config/routes.php):
failed to open stream: no suitable wrapper could be found in
/opt/lampp/htdocs/wordpress/wordpress/wp-content/themes/twentyseventeen/core/router.php
on line 55
Fatal error: require_once(): Failed opening required
'http://localhost/wordpress/wordpress/wp-content/themes/twentyseventeen/application/config/routes.php'
(include_path='.:/opt/lampp/lib/php') in
/opt/lampp/htdocs/wordpress/wordpress/wp-content/themes/twentyseventeen/core/router.php
on line 55
That's seems path issue, you are using it in WordPress so you have to define relevant paths in WordPress way.
Use get_template_directory_uri() to get the theme path and if you are using child theme then use get_stylesheet_directory_uri().
require( get_template_directory_uri() . '/directorypathtoscriptfiles');
if you have put your script like wp-content/yourtheme/yourscriptdir then your path should be :
require( get_template_directory_uri() . '/yourscriptdir/core/router.php');
EDIT
The warning is generated because a full URL has been used for the file that you are including, you are getting some HTML may be, this is the reason i was asking for your dir structure, although it will work if you change allow_url_include to 1 in php.ini file, but what would you do on live server? to tackle this now add ../ in your require instead of full url like below & see if that works:
do this in router.php
require( '../application/config/routes.php');

Why/Where does CodeIgniter set a 404 http status when the page is found?

I am using CodeIgniter2. I am using routing to route url segments to a controller and method.
This seems to work. My pages load as expected i.e. the url goes to the correct method to get the page info from the database, come back and display the correct page. My routes.php relevant code is:
$route['default_controller'] = "content";
$route['en/(:num)/(:any)'] = "content/en/$1";
$route['de/(:num)/(:any)'] = "content/de/$1";
$route['es/(:num)/(:any)'] = "content/es/$1";
$route['it/(:num)/(:any)'] = "content/it/$1";
$route['ar/(:num)/(:any)'] = "content/ar/$1";
$route['404_override'] = '';
HOWEVER instead of that displayed page showing a http status of 200, it shows a http status of 404 ... I have no idea why.
I suspect it is to do with a MY_Router.php file i have to give a custom error page but i can't work out what's going on.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Router extends CI_Router {
var $error_controller = 'error';
var $error_method_404 = 'error_404';
function My_Router()
{
parent::CI_Router();
}
// this is just the same method as in Router.php, with show_404() replaced by $this->error_404();
function _validate_request($segments)
{
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
{
return $segments;
}
// Is the controller in a sub-folder?
if (is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
if (count($segments) > 0)
{
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
{
return $this->error_404();
}
}
else
{
$this->set_class($this->default_controller);
$this->set_method('index');
// Does the default controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
{
$this->directory = '';
return array();
}
}
return $segments;
}
// Can't find the requested controller...
return $this->error_404();
}
function error_404()
{
$this->directory = "";
$segments = array();
$segments[] = $this->error_controller;
$segments[] = $this->error_method_404;
return $segments;
}
function fetch_class()
{
// if method doesn't exist in class, change
// class to error and method to error_404
$this->check_method();
return $this->class;
}
function check_method()
{
$ignore_remap = true;
$class = $this->class;
if (class_exists($class))
{
// methods for this class
$class_methods = array_map('strtolower', get_class_methods($class));
// ignore controllers using _remap()
if($ignore_remap && in_array('_remap', $class_methods))
{
return;
}
if (! in_array(strtolower($this->method), $class_methods))
{
$this->directory = "";
$this->class = $this->error_controller;
$this->method = $this->error_method_404;
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
}
}
}
function show_404()
{
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
call_user_func(array($this->error_controller, $this->error_method_404));
}
}
/* End of file MY_Router.php */
/* Location: ./system/application/libraries/MY_Router.php */
Solved - the wordpress blog integrated in the site was setting the 404 status for all non wordpress pages i.e. codeigniter pages
index.php of CI had the following code which needed to be commented out
/*
*---------------------------------------------------------------
* WORDPRESS INTEGRATION
*---------------------------------------------------------------
* The ci_site_url function helps to avoid collision between WP & CI.
*/
//header("HTTP/1.0 200 OK");
define('WP_USE_THEMES', false);
require_once './blog/wp-blog-header.php';
add_filter('site_url', 'ci_site_url', 1);
function ci_site_url()
{
include(APPPATH.'/config/config.php');
return $config['base_url'];
}

How To render Silex Forms in Smarty Template?

I just stuck at a point.
To render Forms in Smarty Template.
Well, smarty is well configured in my silex project.
here is the Code in my controller class.
$loginForm = $app['form.factory']
->createBuilder(new Form\UserLogin())
->getForm();
$app['smarty']->assign('loginForm', $loginForm->createView());
return $app['smarty']->render('login.tpl');
Here is the code in my tpl file
{block name="headline"}
<h1>User Login</h1>
{/block}
{block name="content"}
<div>
{form_widget(loginForm)}
</div>
{/block}
And i am getting this exception.
SmartyCompilerException:
Syntax Error in template "/home/Symfony/demo/App/View/login.tpl" on line 8
"{form_widget(loginForm)}" unknown function "form_widget"
Edit:
Ok i found the issue but not getting the solution.
Following is SmartyServiceProvider Class.
<?php
namespace App\ServiceProvider;
use Silex\Application;
use \Symfony\Component\HttpFoundation\Request;
use Silex\ServiceProviderInterface;
use App\Classes\Smarty;
use NoiseLabs\Bundle\SmartyBundle\Form\SmartyRendererInterface;
use \NoiseLabs\Bundle\SmartyBundle\Extension\AbstractExtension;
use \NoiseLabs\Bundle\SmartyBundle\Extension\FormExtension;
use \NoiseLabs\Bundle\SmartyBundle\Form;
class SmartyServiceProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$app['smarty.auto-render'] = true;
$app['smarty.extension'] = $app->protect(
function (AbstractExtension $extension, Smarty $smarty = null) use ($app) {
if ($smarty == null) {
$smarty = $app['smarty'];
}
/** #var $plugin \NoiseLabs\Bundle\SmartyBundle\Extension\Plugin\AbstractPlugin */
/** #var $filter \NoiseLabs\Bundle\SmartyBundle\Extension\Filter\AbstractFilter */
foreach ($extension->getPlugins() as $plugin) {
//print $plugin->getName() . " | " . $plugin->getType() . "<br>";
$smarty->registerPlugin($plugin->getType(), $plugin->getName(), $plugin->getCallback());
}
foreach ($extension->getFilters() as $filter) {
$smarty->registerFilter($filter->getType(), $filter->getCallback());
}
}
);
$app['smarty.extensions'] = $app->protect(
function (array $extensions, Smarty $smarty = null) use ($app) {
foreach ($extensions as $extension) {
$app['smarty.extension']($extension, $smarty);
}
}
);
$app['smarty'] = $app->share(
function () use ($app) {
$app['directory.smarty.plugins'] = $app['directory.root.app'] . '/Classes/Smarty/Plugins';
$smarty = isset($app['smarty.instance']) ? $app['smarty.instance'] : new Smarty(
$app,
isset($app['smarty.primary.template.dir'])
? $app['smarty.primary.template.dir']
: $app['directory.root.view'],
false
);
if (isset($app["smarty.options"]) && is_array($app["smarty.options"])) {
foreach ($app["smarty.options"] as $smartyOptionName => $smartyOptionValue) {
$smarty->$smartyOptionName = $smartyOptionValue;
}
}
$smarty->assign("app", $app);
if (isset($app['smarty.configure'])) {
$app['smarty.configure']($smarty);
}
$extensions = [];
//$extensions[] = new \NoiseLabs\Bundle\SmartyBundle\Extension\FormExtension();
$extensions[] = new \NoiseLabs\Bundle\SmartyBundle\Extension\RoutingExtension($app['url_generator']);
$extensions[] = new \App\Classes\Smarty\HookExtension();
$app['smarty.extensions']($extensions, $smarty);
return $smarty;
}
);
}
public function boot(Application $app)
{
}
}
Here in that class i have loaded extensions of SmartyBundle here.
Here I'll have to load FormExtensions.
$extensions = [];
$extensions[] = new \NoiseLabs\Bundle\SmartyBundle\Extension\FormExtension('Don't know how to get SmartyRendererInterface instance here');
$extensions[] = new \NoiseLabs\Bundle\SmartyBundle\Extension\RoutingExtension($app['url_generator']);
$extensions[] = new \App\Classes\Smarty\HookExtension();
$app['smarty.extensions']($extensions, $smarty);
The correct syntax for the Form Widget is:
{form_widget form=$loginForm}
From your example it's not clear the out from $loginForm->createView() and you're lacking the form tags ( ie )that normally surround the Form widget. If the createView includes these you make be not need the form widget and just need to output the entire form HTML as:
{$loginForm}

php Class calling a function inside another function error

I have the following class with few functions inside. I'm getting an error when i call the get_dir_size() inside the Diskspace() function. It's not recognizing it. What am i doing wrong. This code is for creating an expressionengine plugin.
Fatal error: Call to undefined function get_dir_size()
class DiskSpace
{
public $return_data = "";
public function Diskspace()
{
$this->EE =& get_instance();
$dir_name = $_SERVER['DOCUMENT_ROOT']."/userfiles/";
/* 1048576 bytes == 1MB */
$total_size= round((get_dir_size($dir_name) / 1048576),2) ;
$this->return_data = $total_size;
}
public function get_dir_size($dir_name){
$dir_size =0;
if (is_dir($dir_name)) {
if ($dh = opendir($dir_name)) {
while (($file = readdir($dh)) !== false) {
if($file !="." && $file != ".."){
if(is_file($dir_name."/".$file)){
$dir_size += filesize($dir_name."/".$file);
}
/* check for any new directory inside this directory */
if(is_dir($dir_name."/".$file)){
$dir_size += get_dir_size($dir_name."/".$file);
}
}
}
}
}
closedir($dh);
return $dir_size;
}
}
Change the line that calls get_dir_size($dir_name) to :-
$total_size= round(($this->get_dir_size($dir_name) / 1048576),2) ;
There are a few more issues with this code
What is this ? $this->EE = & get_instance();
and also you will get errors when you execute closedir($dh); if the if statement that it is declared in is not executed.
Remember when you call objects own function inside the object, use the $this pointer variable.
$total_size= round((get_dir_size($dir_name) / 1048576),2) ;
Change to
$total_size= round(($this->get_dir_size($dir_name) / 1048576),2) ;
Would be also good if you told us which line the error is happening at. Would be also nice to see the full error log.

Codeigniter Routes regex - using dashes in controller/method names

I'm looking for a one line route to route dashed controller and method names to the actual underscored controller and method names.
For example the URL
/controller-name/method-name-which-is-long/
would route to
/controller_name/method_name_which_is_long/
see: http://codeigniter.com/forums/viewreply/696690/ which gave me the idea to ask :)
That is exactly my requirement too and I was using routes like
$route['logued/presse-access'] = "logued/presse_access";
In my previous project I needed to create 300-400 routing rules, most of them are due to dash to underscore conversion.
For my next project I eagerly want to avoid it. I have done some quick hack and tested it, though have not used in any live server, its working for me. Do the following..
Make sure the subclass_prefix is as follows in your system/application/config/config.php
$config['subclass_prefix'] = 'MY_';
Then upload a file named MY_Router.php in system/application/libraries directory.
<?php
class MY_Router extends CI_Router {
function set_class($class)
{
//$this->class = $class;
$this->class = str_replace('-', '_', $class);
//echo 'class:'.$this->class;
}
function set_method($method)
{
// $this->method = $method;
$this->method = str_replace('-', '_', $method);
}
function _validate_request($segments)
{
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.str_replace('-', '_', $segments[0]).EXT))
{
return $segments;
}
// Is the controller in a sub-folder?
if (is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
if (count($segments) > 0)
{
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().str_replace('-', '_', $segments[0]).EXT))
{
show_404($this->fetch_directory().$segments[0]);
}
}
else
{
$this->set_class($this->default_controller);
$this->set_method('index');
// Does the default controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
{
$this->directory = '';
return array();
}
}
return $segments;
}
// Can't find the requested controller...
show_404($segments[0]);
}
}
Now you can freely use url like http://example.com/logued/presse-access and it will call the proper controller and function by automatically converting dash to underscore.
Edit:
Here is our Codeigniter 2 solution which overrides the new CI_Router functions:
<?php
class MY_Router extends CI_Router {
function set_class($class)
{
$this->class = str_replace('-', '_', $class);
}
function set_method($method)
{
$this->method = str_replace('-', '_', $method);
}
function set_directory($dir) {
$this->directory = $dir.'/';
}
function _validate_request($segments)
{
if (count($segments) == 0)
{
return $segments;
}
// Does the requested controller exist in the root folder?
if (file_exists(APPPATH.'controllers/'.str_replace('-', '_', $segments[0]).'.php'))
{
return $segments;
}
// Is the controller in a sub-folder?
if (is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
while(count($segments) > 0 && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($this->directory . $segments[0]);
$segments = array_slice($segments, 1);
}
if (count($segments) > 0)
{
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().str_replace('-', '_', $segments[0]).'.php'))
{
if ( ! empty($this->routes['404_override']))
{
$x = explode('/', $this->routes['404_override']);
$this->set_directory('');
$this->set_class($x[0]);
$this->set_method(isset($x[1]) ? $x[1] : 'index');
return $x;
}
else
{
show_404($this->fetch_directory().$segments[0]);
}
}
}
else
{
// Is the method being specified in the route?
if (strpos($this->default_controller, '/') !== FALSE)
{
$x = explode('/', $this->default_controller);
$this->set_class($x[0]);
$this->set_method($x[1]);
}
else
{
$this->set_class($this->default_controller);
$this->set_method('index');
}
// Does the default controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php'))
{
$this->directory = '';
return array();
}
}
return $segments;
}
// If we've gotten this far it means that the URI does not correlate to a valid
// controller class. We will now see if there is an override
if ( ! empty($this->routes['404_override']))
{
$x = explode('/', $this->routes['404_override']);
$this->set_class($x[0]);
$this->set_method(isset($x[1]) ? $x[1] : 'index');
return $x;
}
// Nothing else to do at this point but show a 404
show_404($segments[0]);
}
}
Now one has to place this file like application/core/MY_Router.php and make sure he has subclass_prefix is defined as $config['subclass_prefix'] = 'MY_'; in application/config/config.php
Few extra lines of code has been added in method _validate_request():
while(count($segments) > 0 && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($this->directory . $segments[0]);
$segments = array_slice($segments, 1);
}
It is used so that one can make use of multi-level subdirectory inside controllers directory, whereas normally we can use single level subdirectory inside controllers folder and can call it in url. One can remove this code if it not necessary but it has no harm on the normal flow.
Just coming back to this question after upgrading to CodeIgniter 2. Here is a solution which is more robust than the accepted answer because it will survive CodeIgniter core updates.
<?php
class MY_Router extends CI_Router
{
public function set_class($class)
{
parent::set_class($this->_repl($class));
}
public function set_method($method)
{
parent::set_method($this->_repl($method));
}
public function _validate_request($segments)
{
if (isset($segments[0]))
$segments[0] = $this->_repl($segments[0]);
if (isset($segments[1]))
$segments[1] = $this->_repl($segments[1]);
return parent::_validate_request($segments);
}
private function _repl($s)
{
return str_replace('-', '_', $s);
}
}
It should be saved as application/core/MY_Router.php. Now, you can have Controller and Method names with underscores in them such as Abc_Def (in file abc_def.php) and refer to them with the URL /abc-def.
Actually this is native now in Codeigniter 3
Just do this in routes file
$route['translate_uri_dashes'] = TRUE;
And it will do it for controllers and methods automatically .
Please vote this answer up , as it's most recent
<?php
class MY_Router extends CI_Router
{
function _set_request($segments = array()) {
parent::_set_request(str_replace('-', '_', $segments));
}
}
?>
Put this file MY_Router.php inside /application/libraries (CI1) or /application/core (CI2)
Remember that this will effect all segments, not only module, controller and method.
Alternative to this extend is to add each segment to router.php
$route['this-is-a-module-or-controler'] = 'this_is_a_module_or_controller';
As you can see the extend method would be easier to use. You can choose to make the function also to handle only the first two or three segments so that the other segments are not affected with the _ replacement.
This is an old question, but I'd like to post that e-mike had a great solution to this problem, and a lot simpler.
<?php
public function _set_request($segments){
// Fix only the first 2 segments
for($i = 0; $i < 2; ++$i){
if(isset($segments[$i])){
$segments[$i] = str_replace('-', '_', $segments[$i]);
}
}
// Run the original _set_request method now, giving it our newly replaced segments
parent::_set_request($segments);
}
?>
Hope this helps anyone else with this problem.
I believe what you are looking for is a either a pre-system or else a pre-controller hook that will take the requested URI and update it.
Overriding the Router class is a nice approach, there is also a way of replacing - with _ by registering a "pre-system" hook.
First create the hook by adding these lines to your ‘config/hooks.php’ file:
$hook['pre_system'] = array(
'class' => '',
'function' => 'prettyurls',
'filename' => 'myhooks.php',
'filepath' => 'hooks',
'params' => array()
);
Now create a ‘myhooks.php’ file within the ‘application/hooks’ folder and add this function (don’t forget to open a PHP tag if this is the first hook):
<?php
function prettyurls() {
if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') {
$newkey = str_replace('-','_',key($_GET));
$_GET[$newkey] = $_GET[key($_GET)];
unset($_GET[key($_GET)]);
}
if (isset($_SERVER['PATH_INFO'])) $_SERVER['PATH_INFO'] = str_replace('-','_',$_SERVER['PATH_INFO']);
if (isset($_SERVER['QUERY_STRING'])) $_SERVER['QUERY_STRING'] = str_replace('-','_',$_SERVER['QUERY_STRING']);
if (isset($_SERVER['ORIG_PATH_INFO'])) $_SERVER['ORIG_PATH_INFO'] = str_replace('-','_',$_SERVER['ORIG_PATH_INFO']);
if (isset($_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI'] = str_replace('-','_',$_SERVER['REQUEST_URI']);
}
You will probably need to edit your ‘config/config.php’ file to enable hooks (around line 91 for me):
$config['enable_hooks'] = TRUE;
This answer is ripped from http://codeigniter.com/forums/viewthread/124396/#644012
I'm not sure if you could do that with a route...
However, somewhere in the Codeigniter core libraries (possibly Router or URI) will be something that converts the underscored uris into a camelcase class name.
I had a quick look and couldn't find it, but if you do, just copy that library to your application/libraries folder, and modify it there.
You can use this _remap() method to handle such behavior. Place this method in your controllers or create a core controller and place it in.
public function _remap($method, $params = array()){
if(method_exists($this, $method)){
return call_user_func_array(array($this, $method), $params);
}else{
$method = str_replace("-", "_", $method);
if(method_exists($this, $method)){
return call_user_func_array(array($this, $method), $params);
}
}
show_404();
}

Categories