I'm try to moving some website from CI 2.x to CI 3.1.2,
but after I moving my old website to new CI I get 404 error when I'm access that page.
this is my CI structure :
Applications
- controller
-- back
-- front
--- Home.php
- libraries
-- front.php
- model
-- home_models.php
- views
-- back
-- front
--- elems
---- head.php
---- foot.php
--- pages
---- home.php
--- display
---- pages.php
Controller
Home.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Home extends CI_Controller {
var $data;
public function __construct(){
parent::__construct();
}
public function index(){
$data = array();
$this->front->pages('home',$data);
}
}
/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */
Libraries front.php
<?php
class Front {
protected $_ci;
function __construct(){
$this->_ci = &get_instance();
}
function pages($page, $data=null){
$data['head'] = $this->_ci->load->view('front/elems/head', $data, TRUE);
$data['content'] = $this->_ci->load->view('front/pages/'.$page, $data, TRUE);
$data['foot'] = $this->_ci->load->view('front/elems/foot', $data, TRUE);
$this->_ci->load->view('front/display/pages', $data);
}
}
?>
in my route :
$route['default_controller'] = 'front/home';
and in my autoload :
$autoload['libraries'] = array('front');
In old CI that's structure is work, but after I'm trying to implement that structure in 3.1.2 I can't access that page. What's wrong with this.
Read Upgrading from 2.2.x to 3.0.x
Update your CodeIgniter files
Update your classes file names
Replace config/mimes.php
Remove $autoload[‘core’] from your config/autoload.php
Update Database and Routes files.
etc ....
I found this way
Change my system core Router.php into
protected function _set_default_controller()
{
if (empty($this->default_controller))
{
show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
// Is the method being specified?
if (!sscanf($this->default_controller, '%[^/]/%[^/]/%s', $directory, $class, $method) !== 2)
{
$method = 'index';
}
if ( ! file_exists(APPPATH.'controllers'. DIRECTORY_SEPARATOR . $directory. DIRECTORY_SEPARATOR .ucfirst($class).'.php'))
{
// This will trigger 404 later
return;
}
$this->set_directory($directory);
$this->set_class($class);
$this->set_method($method);
// Assign routed segments, index starting from 1
$this->uri->rsegments = array(
1 => $class,
2 => $method
);
log_message('debug', 'No URI present. Default controller set.');
}
And it works, but if this is safe?
Related
In codeigniter 3 application i have directory structure like this:
-Myproject
-application
-controllers
-home
Welcome.php //This is my controller inside home directory
How to set Welcome controller as default controller?
I use below code
$route['default_controller'] = 'home/Welcome';
This routing works for previous versions of codeigniter.
By default, you are not allowed to do that. To get around this, you need to hack your system Router.php:
codeigniter/system/core/Router.php
Edit a few lines of code so that it becomes like this:
line 1. if (!sscanf($this->default_controller, '%[^/]/%[^/]/%s', $directory, $class, $method) !== 2)
line 2. if ( ! file_exists(APPPATH.'controllers'. DIRECTORY_SEPARATOR . $directory. DIRECTORY_SEPARATOR .ucfirst($class).'.php'))
line 3. $this->set_directory($directory);
Once you've done, you can call the default controller under directory.
$route['default_controller'] = 'home/Welcome';
You need not to change anything from files inside CODEIGNITER system folder. Codeigniter allows developer to extend their feature. You can create a file named as MY_Router.php.
<?php
class MY_Router extends CI_Router {
protected function _set_default_controller() {
if (empty($this->default_controller)) {
show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2) {
$method = 'index';
}
if( is_dir(APPPATH.'controllers/'.$class) ) {
$this->set_directory($class);
$class = $method;
if (sscanf($method, '%[^/]/%s', $class, $method) !== 2) {
$method = 'index';
}
}
if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php')) {
return;
}
$this->set_class($class);
$this->set_method($method);
$this->uri->rsegments = array(
1 => $class,
2 => $method
);
log_message('debug', 'No URI present. Default controller set.');
}
}
Note: Do not change the file name.
Try This in routes.php
$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
I´m making a "very" simple MVC framework in order to learn, however I have trouble getting other pages than the index page to show. In views folder I have 2 files one index.php and one register.php that I´m trying on.
I have tried various ways but can´t get my head around it. I know it is probably best to put different controller classes in different files and maybe a loader controller page but I´m a beginner with php so would like to make it as simple as possible for me...
Any help appriciated!
I have a index.php as a landing file in the root folder to bind everything together:
<?php
/* index.php
*
*/
require_once 'model/load.php';
require_once 'controller/main.php';
new mainController();
In the controller folder i have a file called main.php:
<?php
/* controller/main.php
*
*/
class mainController
{
public $load;
public function __construct()
{
$urlValues = $_SERVER['REQUEST_URI'];
$this->urlValues = $_GET;
//index page
if ($this->urlValues['controller'] == "") {
$indexPage = array("key" => "Hello");
$this->load = new load();
$this->load->view('index.php', $indexPage);
}
//register page
if ($this->urlValues['controller'] == "register.php") {
$registerPage = array("key" => "Register");
$this->load = new load();
$this->load->view('register.php', $registerPage);
}
}
}
And then I have a file called load.php in the model folder:
<?php
/* model/load.php
*
*/
class load
{
/* This function takes parameter
* $file_name and match with file in views.
*/
function view($file_name, $data = null)
{
if (is_readable('views/' . $file_name)) {
if (is_array($data)) {
extract($data);
}
require 'views/' . $file_name;
} else {
echo $this->file;
die ('404 Not Found');
}
}
}
In your mainController class you don't have property with the name urlValues, but you use it: $this->urlValues = $_GET;. And what is more you have local variable with the same name, that you don't use: $urlValues = $_SERVER['REQUEST_URI'];
And how you URL for register.php looks like?
Hi I am having an issue
Say I have a folder structure in CodeIgniter
application/
controllers/
models/
views/
gmail_library/
Now I have written a controller
class invite_friends extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->gmail_library('Config'); // this line is giving me error
session_start();
}
}
How can I set this thing like this?
First of all, note that CodeIgniter doesn't use overloading by __call() to implement dynamic methods. Thus there is no way to get such a gmail_library() methods to work.
The conventional method
From the User Guide:
Your library classes should be placed within your
application/libraries folder, as this is where CodeIgniter will look
for them when they are initialized.
If you're using CI Loader class to load a library or helper, you should follow CI's conventions.
application/libraries/Myclass.php
$this->load->library('myclass');
$this->myclass->my_method();
Using relative paths
1) You put your library files in sub-directories within the main libraries folder:
application/libraries/gmail/Gmail_config.php
I renamed your Config.php file name to prevent the occurrence of conflict with CI config core class.
$this->load->library('gmail/gmail_config');
2) Also you can use relative path within the Loader::library() method to load the library file from the outside of the library folder, as follows:
The path to the file is relative. So you can use ../ to go one UP level in path.
Again: I renamed your Config.php file name to prevent the occurrence of conflict with CI config core class.
$this->load->library('../gmail_library/Gmail_config');
An old question, I know, but I came across this looking for a way to use classes (libraries) from outside the application folder and I liked to keep it in 'the CI way of doing this'. I ended up extending the CI_Loaderclass:
I basically copied the _ci_load_class function and added an absolute path
<? if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Loader extends CI_Loader {
protected $absPath = '/home/xxxxx/[any-path-you-like]/common/';
/**
* Load class
*
* This function loads the requested class.
*
* #param string the item that is being loaded
* #param mixed any additional parameters
* #param string an optional object name
* #return void
*/
public function commonLibrary($class, $params = NULL, $object_name = NULL)
{
// Get the class name, and while we're at it trim any slashes.
// The directory path can be included as part of the class name,
// but we don't want a leading slash
$class = str_replace('.php', '', trim($class, '/'));
// Was the path included with the class name?
// We look for a slash to determine this
$subdir = '';
if (($last_slash = strrpos($class, '/')) !== FALSE)
{
// Extract the path
$subdir = substr($class, 0, $last_slash + 1);
// Get the filename from the path
$class = substr($class, $last_slash + 1);
}
// We'll test for both lowercase and capitalized versions of the file name
foreach (array(ucfirst($class), strtolower($class)) as $class)
{
$subclass = $this->absPath.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
// Is this a class extension request?
if (file_exists($subclass))
{
$baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';
if ( ! file_exists($baseclass))
{
log_message('error', "Unable to load the requested class: ".$class);
show_error("Unable to load the requested class: ".$class);
}
// Safety: Was the class already loaded by a previous call?
if (in_array($subclass, $this->_ci_loaded_files))
{
// Before we deem this to be a duplicate request, let's see
// if a custom object name is being supplied. If so, we'll
// return a new instance of the object
if ( ! is_null($object_name))
{
$CI =& get_instance();
if ( ! isset($CI->$object_name))
{
return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
}
$is_duplicate = TRUE;
log_message('debug', $class." class already loaded. Second attempt ignored.");
return;
}
include_once($baseclass);
include_once($subclass);
$this->_ci_loaded_files[] = $subclass;
return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
// Lets search for the requested library file and load it.
$is_duplicate = FALSE;
foreach ($this->_ci_library_paths as $path)
{
$filepath = $this->absPath.'libraries/'.$subdir.$class.'.php';
// Does the file exist? No? Bummer...
if ( ! file_exists($filepath))
{
continue;
}
// Safety: Was the class already loaded by a previous call?
if (in_array($filepath, $this->_ci_loaded_files))
{
// Before we deem this to be a duplicate request, let's see
// if a custom object name is being supplied. If so, we'll
// return a new instance of the object
if ( ! is_null($object_name))
{
$CI =& get_instance();
if ( ! isset($CI->$object_name))
{
return $this->_ci_init_class($class, '', $params, $object_name);
}
}
$is_duplicate = TRUE;
log_message('debug', $class." class already loaded. Second attempt ignored.");
return;
}
include_once($filepath);
$this->_ci_loaded_files[] = $filepath;
return $this->_ci_init_class($class, '', $params, $object_name);
}
} // END FOREACH
// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
if ($subdir == '')
{
$path = strtolower($class).'/'.$class;
return $this->_ci_load_class($path, $params);
}
// If we got this far we were unable to find the requested class.
// We do not issue errors if the load call failed due to a duplicate request
if ($is_duplicate == FALSE)
{
log_message('error', "Unable to load the requested class: ".$class);
show_error("Unable to load the requested class: ".$class);
}
}
}
Put the file MY_Loader.php in the application/core folder and load your libs with:
$this->load->commonLibrary('optional_subfolders/classname', 'classname');
$this->classname->awesome_method();
Ok I have a controller class in Yii that I want to use a different view folder aside from using its default view folder.
The natural behavior is when a $this->render("<view file>"); you would use the following to navigate your view file in the project...
"//" navigates project default view folder
"/" navigates current theme view folder
or do not use anything to select a view automatically in the
controller's default view folder
but my problem is i'm not rendering a view file but a STATIC PAGE that resides in /pages folder of a certain view folder. The static page I want to navigate is a static page the resides in my current theme folder views but the default is the controller navigates the static page inside the /protected/view folder
I tried also this override to modify the controller's view folder. I put this code in my controller that I want to render static pages in a theme folder
public function init(){
$this->layout = "//layouts/script";
$this->viewPath = "/js";
}
but the problem is the viewPath is readOnly variable.
Now my question is how I can render static pages that resides in my current theme's view folders?
NOTE: please if you don't understand my question, please don't down vote. I'm open to change and explain my problem for you as possible as I can
When you're overriding the actions method in your SiteController, somehow, you need to change the CViewAction's basePath property. It defaults to pages, as the documentation says.
Could you try something like this?
public function actions()
{
return array(
'page'=>array(
'class'=>'CViewAction',
'basePath'=>'path/to/your/theme/folder'
),
);
}
create a helper class for yourself and declare this method (change filepaths and other stuff):
public static function renderInternal($_viewFile_, $_data_ = null, $_return_ = false) {
// we use special variable names here to avoid conflict when extracting data
if (is_array($_data_)) {
extract($_data_, EXTR_PREFIX_SAME, 'data');
} else {
$data = $_data_;
}
$viewsDir = '/protected/views/internals/';
if ($_return_) {
ob_start();
ob_implicit_flush(false);
require(getcwd() . $viewsDir . $_viewFile_ . '.php');
return ob_get_clean();
} else {
require(getcwd() . $viewsDir . $_viewFile_ . '.php');
}
}
Use it/call it:
MyHelperClass::renderInternal( 'myviewfile', array( /* YOUR DATA */ ), /* RETURN CONTENTS OR NOT */ )
NOTE: Change $viewsDir to your desired directory.
try this in your any site controller or any controller..
public function actions()
{
return array(
'page'=>array(
'class'=>'CViewAction',
),
);
}
or refer this link...
http://www.yiiframework.com/wiki/22/how-to-display-static-pages-in-yii/
dir:
application
-controllers
-models
-views
-mobile_views
How do I auto load templates at mobile_views when I use $this->load->view and view by iphone or other mobile phone?
Check this
You can do it in two way.
Way 1: Its very simple. In the above answer (the link I have given) add following line in the end of MyController function
$this->load->_ci_view_path . = $this->view_type .'/';
You are done. You can simply load view like normal view load.
Way 2:
To autoload a view based on user agent, I think you can implement it using hooks. To implement this hooks you need to follow the following steps
Autoload user agent library in autoload.php
$autoload['libraries'] = array('user_agent');
Enable hooks in config.php
$config['enable_hooks'] = TRUE;
Not implement hooks on post_controller_constructor. Add following codes to hooks.php
$hook['post_controller_constructor'][] = array('class' => 'Loadview',
'function' => 'load',
'filename' => 'loadview.php',
'filepath' => 'hooks'
);
Now create a page named loadview.php under hooks directory having following code
class Loadview
{
public static $MOBILE_PLATFORM = 'mobile';
public static $DEFAULT_PLATFORM = 'default';
public function load(){
$this->CI =& get_instance();
$view_type = $this->CI->agent->is_mobile() ? self::$MOBILE_PLATFORM : self::$DEFAULT_PLATFORM;
$this->CI->load->_ci_view_path = $this->CI->load->_ci_view_path . $view_type .'/';
}
}
You are done now. You can simply load view like normal view load.
to load views from another dir aside from "views", i found this forum topic to be helpful
http://codeigniter.com/forums/viewthread/132960/
function external_view($path, $view, $vars = array(), $return = FALSE)
{
$full_path = $path.$view.'.php';
if (file_exists($full_path))
{
return $this->_ci_load(array('_ci_path' => $full_path, '_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
else
{
show_error('Unable to load the requested module template file: '.$view);
}
}
and you can work the rest from the controller.
I do this in my controller:
public function index()
{
if($this->agent->is_mobile())
{
$this->load_mobile();
}
else
{
$this->load_web();
}
}
public function load_mobile()
{
$this->load->view('mobile/home');
}
public function load_web()
{
$this->load->view('web/home');
}
In this way I can add different data to mobile and to web pages.
I also extend the default controller and add some useful extra features:
Enables the usage of master page/templates.
Can add css and javascript files.
Uses the _output method for controlling the controllers output.
Can load relative content with in the form of modules (views)
So I can manage better the different pages.
Bye!!