Loading view outside view folder with CodeIgniter
Asked Answered
D

6

7

I have the need to load a view from outside the scope of:

$this->load->view();

which appears to work from base/application/views directory. How can I access a view from outside the /application/ directory ?

I assume i will have to extend the CI_Loader class would this be the best way forward ?

I have also found the array which holds the view_paths:

// base/system/core/Loader.php 
// CI_Loader 
 /**
 * List of paths to load views from
 *
 * @var array
 * @access protected
 */
protected $_ci_view_paths       = array();

but the comment above all the declared variables has got me stuck

// All these are set automatically. Don't mess with them.

Any ideas on where to go from here would be greatly appreciated :-)

Danedanegeld answered 28/6, 2013 at 6:27 Comment(6)
application folder is meant for your application, why are you using a file outside of CodeIgniter application folder?Bartle
Its a good point, it's a third party asset that sits outside the application folder , I am trying to integrate parts of it.Danedanegeld
So why don't you integrate it? What's wrong with it?Bartle
You can use debug_backtrace() to see, what has been executed. You could add it here and see, what gets called before the view() method.Epicure
@tereško awesome the backtrace, +helpfull flagMethaemoglobin
@Bartle I could ( and should ) integrate it, but I don't have time on my side in this instance and so I decided to go down this path due to end of financial year deadlinesDanedanegeld
S
11

Don't know whether it's a correct way, but it works :)

In your application/core folder put this loader extention

<?php

class MY_Loader extends CI_Loader {

  function ext_view($folder, $view, $vars = array(), $return = FALSE) {
    $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH . $folder . '/' => TRUE));
    return $this->_ci_load(array(
                '_ci_view' => $view,
                '_ci_vars' => $this->_ci_object_to_array($vars),
                '_ci_return' => $return
            ));
  }

}

?>

Then you want a external view file, suppose its in the third_party folder

application/third_party/my_new_view.php

Hello : <?php echo $my_name; ?>

Then call your new view in the controller

ext_view is your new view loader method,

  • 1st param : the folder inside you applicaton
  • 2nd param : the view name
  • 3rd param : the variables data and so on...

test_controller.php

$view_data = array('my_name' => 'dino');
$this->load->ext_view('third_party', 'my_new_view', $view_data);

If everything fine. it will output

Hello : dino

Syndic answered 28/6, 2013 at 9:4 Comment(4)
Just to note that the APPPATH defaults to the 'application' folderDanedanegeld
I assume that you could add do APPPATH . '../' . $folder . '/' if your looking to make one that looks one level up from APPPATH.Fuzz
I have tested it and in fact you CAN do the above.Fuzz
@Dino. Thanks for such brilliant solution.Is there anyway we could load models like this (i.e outside "application/models" folder)??If so what will we need to do?I am not sure how to call model function after loading it??Turbine
E
7

Dino's solution seems very sound, and did indeed work for files in application, however, I was needing a bit deeper solution. Our CI is embedded into a subdirectory of a main directory, something like ip.ip.ip.ip/dir/sub/application/... Perhaps I was doing something wrong, but I was unable to make his solution work at all with my needs, even after trying to apply something like ../../, which still wouldn't be feasible; what if I need to go deeper into an unknown back directory count?

Thus I ended up writing my own solution, that thus far, seems to work great, tho it makes use of vanilla PHP. In this manner it seeks to grab the very base directory your files sit in and load them, pretty much the same way CI's load function works.

Same as his solution, create a file in application/core named MY_Loader.php. Then simply write in the following (or just add the method if you want to keep his solution as well):

<?php
    class MY_Loader extends CI_Loader {
        public function base_view($view, $vars = array(), $get = FALSE) {
            //  ensures leading /
            if ($view[0] != '/') $view = '/' . $view;
            //  ensures extension   
            $view .= ((strpos($view, ".", strlen($view)-5) === FALSE) ? '.php' : '');
            //  replaces \'s with /'s
            $view = str_replace('\\', '/', $view);

            if (!is_file($view)) if (is_file($_SERVER['DOCUMENT_ROOT'].$view)) $view = ($_SERVER['DOCUMENT_ROOT'].$view);

            if (is_file($view)) {
                if (!empty($vars)) extract($vars);
                ob_start();
                include($view);
                $return = ob_get_clean();
                if (!$get) echo($return);
                return $return;
            }

            return show_404($view);
        }
    }

Then, if you have a file named 'bob.php' in your inner most root directory, simply call as:

$this->load->base_view('bob');
// OR
$this->load->base_view('bob.php');
// OR if it's extension is .html
$this->load->base_view('bob.html');

And if it's in another directory at base root:

$this->load->base_view('directory/bob');
// OR
$this->load->base_view('directory\bob.htm');

Or however you please, as long as you call for a real file in a real directory!

Hope this alternate solution might help someone of similar peril.

Erleena answered 29/4, 2014 at 20:52 Comment(1)
this is good solution, but you can not pass var form controller in that partial??Shedevil
R
0

To customize models and views outside the 'application' folder, follow these easy steps,

Create My_Loader.php file in 'application/core' directory Copy the code into the custom My_Loader.php

class MY_Loader extends CI_Loader {

function mymodel($model, $folder = '',$vars = array(), $return = FALSE) {

    array_push($this->_ci_model_paths, ""); //replace "" with any other directory
    parent::model($model);
}


function myview($folder, $view, $vars = array(), $return = FALSE) {
        $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH . '../' . $folder . '/' => TRUE));
        return $this->_ci_load(array(
                '_ci_view' => $view,
                '_ci_vars' => $this->_ci_object_to_array($vars),
                '_ci_return' => $return
        ));
}

Save the file and in the controller, call and load the model (which resides outside the application folder) as,

$this->load->mymodel('folder/model');

and for the view,

$this->load->myview('views','view_dir/view-php-file', $data);
Reflectance answered 27/6, 2014 at 21:15 Comment(1)
Your answer - concerning "view" - doesn't work outside the application folder! And it is a copy of the accepted answer.Betweenwhiles
C
0

create a file MY_Loader.php in application/core/

<?php
class MY_Loader extends CI_Loader {


    function  __construct() {
        parent::__construct();
        $CI =& get_instance();
        $CI->load = $this;
    }

    public function ext_view($view, $vars = array(), $return = FALSE){

       $_ci_ext = pathinfo($view, PATHINFO_EXTENSION);
       $view = ($_ci_ext == '') ? $view.'.php' : $view;

       return $this->_ci_load(array(
               '_ci_vars' =>   $this->_ci_object_to_array($vars),
               '_ci_path' => $view, '_ci_return' => $return));

    }

}

create a file MY_Controller.php in application/core/

<?php 
class MY_Controller extends CI_Controller {
    public function __construct(){
        parent::__construct();
        $this->load =& load_class('Loader', 'core', 'MY_');
        $this->load->initialize();
        log_message('debug', "Controller Class Initialized");
    } 
}

Use MY_Controller instead of CI_Controller and you can access the ext_view method with

$this->load->ext_view(path/to/the/view/file,@param2,@param3);

ex:

class Welcome extends MY_Controller {
  public function __construct() {
    parent::__construct();
  }

  public function index() {
    $this->load->ext_view('/path/to/view');
  }
}
Christianchristiana answered 24/6, 2015 at 21:48 Comment(0)
O
0

Here is a much more straightforward answer that I found on the CodeIgniter forum at https://forum.codeigniter.com/thread-58412.html

This is my ever-so-slight deviation from the solution presented by docmattman:

class MY_Loader extends CI_Loader{
  public function __construct()
  {
    parent::__construct();
  }

  public function load_ext_view($view, $vars = array(), $return = FALSE)
  {
    $view_file = '/full/path/to/'.$view.'.php';

    if(file_exists($view_file)){
       $view_to_load = array('_ci_path'   => $view_file,
                             '_ci_view'   => $view,
                             '_ci_vars'   => $this->_ci_object_to_array($vars),
                             '_ci_return' => $return
                             );

       return $this->_ci_load($view_to_load);
    }

       return $this->view($view, $vars, $return);
    }
}
Operand answered 8/4, 2016 at 20:31 Comment(0)
C
0

Following Dino's answer and correcting the ci_vars, working as view Codeigniter's function:

Codeigniter View Function

public function view($view, $vars = array(), $return = FALSE)
    {
        return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return));
    }

Dino's View Function will be now:

function ext_view($folder, $view, $vars = array(), $return = FALSE) {
    $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH . $folder . '/' => TRUE));
    return $this->_ci_load(array(
                '_ci_view' => $view,
                '_ci_vars' => $this->_ci_prepare_view_vars($vars),
                '_ci_return' => $return
            ));
  }
Clad answered 26/1, 2019 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.