TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
Calling a view from somewhere other than the view folder in K03 KO3
  • I'm building a system which I want to have a themes folder outside of the usual application/views folder

    I read the thread here http://forum.kohanaframework.org/comments.php?DiscussionID=5187&page=1#Item_0 and I have to admit the solution from xenakis didn't really make much sense to me due to my lack of knowledge.

    I've devised an alternative way to determine overrides using something a bit like this:
    if(file_get_contents($my_theme_folder.'aview'){
    //use this template
    }elseif(file_get_contents($default_kohana_view_folder.'aview'){
    etc...

    All I need is a way to do something like this:

    $template_folder = url::base().'any/folder/I/want';
    $this->template = new View($template_folder.'/template');

    Is this at all possible?
  • Oops, I meant file_exists() rather than file_get_contents()
  • Sounds like a basic theme implementation?

    So lets say you have a folder called 'themes' inside your DOCROOT next to 'application' and 'system'. Within this folder you have a number of themes in different sub folders. Now you will need to register one of these themes as a module for the Kohana::find_file() to pick up any views within it.


    Kohana::modules(array(
    // ... All enabled modules
    'my_theme' => DOCROOT.'themes/my_theme'
    ));


    Replacing 'my_theme' with the name of your theme. Now you add views to that theme by adding a folder called 'views' to the theme sub-folder and adding view files just as you would with any module. Technically speaking you could also add configurations and classes to the theme folder but considering you're keeping this strictly as a presentation layer you won't have to, but it all works the same way.

    Now lets say if you add a view called 'template.php', you can then use View::factory('template') to load that view file. To switch themes just change the 'my_theme' value in the Kohana::modules() call in your boostrap (mentioned earlier). Make sure that both themes contain the same view names, just different contents, otherwise your code may throw errors as it wont be able to find the view file.

    Hope this helps.
  • Many thanks Oli, this is a great explanation and clears it up nicely.

    I can't switch themes the way you suggest as I need to be able to do it dynamically within controllers for different pages and sub views in my system (which is a CMS). However, I think you've given me everything I need.

    The way I'm going to try is to have the module as 'themes' => DOCROOT.'themes' instead then pick the theme in the controller like View::factory($theme_name.'/template')
    Is there any way I can do this without a 'views' folder within 'themes/' so it's just 'themes/theme_name/'?

    I picked up in the other thread that if there are any views in the 'application/views' folder, these will override the ones in the 'my_theme' module you're suggesting. Is this correct? I was going to put a default theme that remains unchanged in 'application/views' that would then be overridden on a file by file basis by anything in the 'themes' folder but I'm assuming this won't work in kohana as it works the other way round?
  • What you can do is give the theme module a single key name, which will allow you to switch it later on.


    Kohana::modules(Kohana::modules() + array(
    'theme' => DOCROOT.'themes/my_new_theme'
    ));


    Obviously to store that information persistently you would use the Database for all users or Sessions for individual users.

    You place the views folder within the theme sub-folder, such as: 'themes/my_new_theme/views' and you have to have it like this for the find_file() method to work normally.
  • Thanks a lot Olly, appreciate the help
  • Sorry to keep coming back to this,

    I've done everything as it should be but it's failing to find the view file. I'm using the template controller, could that have anything to do with it?
  • I'm using the template controller, could that have anything to do with it?

    I doubt it.

    What Olly described above still requires you to to put your views within a folder called 'views' inside the theme folder. The theme folder here is just a kohana module (ie. can contain classes, views, configs etc).

    So your view files should be like

    themes/my_new_theme/views/template.php
    
  • Yeah I did that and it still didn't work. Must be something I'm doing wrong. As far as I can tell I've followed it to the letter but will have another look with fresh eyes soon and see if there's anything I'm doing wrong
  • Hi

    I never really liked making a theme a module; I don't want my app looking for classes in the theme folder. Also it seems a bit hackish to run Kohana::modules() after the bootstrap just to get the theme path at the top of the cascade. This also means all the modules init.php files would be run twice.

    (You could also implement something like a Kohana::add_module() to achieve this, but still with the classes issue. I'd like to be able to create "downloadable themes" scenario without the risk of classes overriding my app.)

    I over-ride the View set_filename() method as below. nb. my themes are activated in the config and can be switched per user session, if authorised.

    class View extends Kohana_View {
    
    
        public function set_filename($file)
        {
            $session = Session::instance();
    
            if ($theme = $session->get('theme'))
            {
                $theme_file = Kohana::config('theme.path').$theme.'/views/'.$file.EXT;
    
                if (is_file($theme_file))
                {
                    $this->_file = $theme_file;
                    return $this;
                }
            }
    
            try
            {
                return parent::set_filename($file);
            }
            catch (Kohana_View_Exception $exception)
            {
                throw $exception;
            }
        }
    
    }
    

    I do similar (cascade) within my Assets class for js, css, images etc..

  • @nick can u show what u mean with ur Assets class?
  • @gregsmith - You can have default views in a module that you load before your theme module. Your application has no views. This is one way of doing it.
  • Haven't checked this for a while - thanks for the new suggestions.

    I like the suggestion Xenakis

    I think I've devised a way to have my theme decided in a controller:

    Say I've got it setup with the themes in themes/views/my_theme
    I can load themes as

    Kohana::modules(array(
    // ... All enabled modules
    'themes' => DOCROOT.'themes'
    ));

    Then I can set the theme for my page in a controller action function, something like this:



    $theme_name = 'my_theme'; //This would be grabbed from the database

    if( kohana::find_file('views', $theme_name.'/view_name') ){

    // Load from my_theme as file exists
    $this->template = new View($theme_name.'/view_name');

    }else{

    $this->template = new View('default/view_name');

    }



    I didn't realise I could call Kohana::find_file() in this way, which was a lightbulb moment.
    This way in the application and modules folders I can put the view files in the 'views/default' folder and they will be loaded by default if the chosen theme doesn't contain them. Or as Xenakis proposes, I could put the defaults in a module loaded before 'themes' called 'default_theme' or something.

    My method is possibly a bit clunky but it does allow me to dynamically switch themes several times in one controller function, for each view file that is loaded, which is something I need to be able to do.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion