• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Controllers in Unlimited Nested Folders

#31
[eluser]bcdennis[/eluser]
If you want to be able to keep simple functions on your default controller in your nested path add this to the Router class:

Code:
if(count($segments) > 0)
        {
            if(!is_file(APPPATH.'controllers/'.$this->directory.$segments[0].EXT))
            {
                array_unshift($segments, $this->default_controller);
            }
        }

around line 44 in the _pluck_directory function.

Basically what it does is if the top of the segment stack after the directory nesting has been handled, isn't a file, push the default controller onto the segment stack.

This gives you the ability to have urls like:
/folder/controller/method
and
/folder/method (becomes /folder/default_controller/method)

I like the nesting of controllers, I just didn't want to be forced to create a new controller for simple methods.

#32
[eluser]Wades[/eluser]
Hi Peter, your work is great, it works in the version of 1.5,
but seems not work in 1.6.1
is anybody try this on the latest version of CI?

#33
[eluser]Wades[/eluser]
Oh, got it
proman already mentioned this, tks

#34
[eluser]xwero[/eluser]
Try this overloaded _valid_request method
Code:
class MY_Router extends CI_Router
{
    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?
        $dir = '';
        $slice_offset = 0;
        // loop trough the segments until the segment is no directory
        foreach($segments as $segment)
        {
            if(strlen($dir) > 0){ $dir .= '/'; }
            if(is_dir(APPPATH.'controllers/'.$dir.$segment))
            {
                $dir .= $segment;
                $slice_offset++;
            }
            else
            {
                break;
            }
        }
        if($dir != '')
        {
            // Set the directory and remove it from the segment array
            $this->directory($dir);
            $segments = array_slice($segments, $slice_offset);
            
            if (count($segments) > 0)
            {
                // Does the requested controller exist in the sub-folder?
                if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$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]);    
    }
}

#35
[eluser]khorne[/eluser]
I'm having an issue with the OP's solution.

I have a default controller of 'home.php'

I have a structure like this

controllers/account/home.php
controllers/account/templates.php

I reference these controllers with links like

/account/ - home index (works)
/account/templates/ - templates index (works)
/account/templates/add - templates add method (works)
/account/templates/edit/1 - templates edit method with argument (works)

However, the issue I'm having is that I can only get the index page to show on the accounts home controller and not other methods it contains, eg:
/account/edit - home edit (doesnt work, gives a 404)

I presume what is happening is it's looking for a controller (or subfolder) named 'edit' and not finding it.

What I'd like it to be able to do is to fallback (ie. when all else fails, subfolder or controller not found) to the default (home) controller and access a method in there.

Can anyone help me with this?

#36
[eluser]khorne[/eluser]
I made some changes to the validate_request method and it all seems to be happy now Smile


Code:
/**
     * Validates the supplied segments.  Attempts to determine the path to
     * the controller.
     *
     * @access    private
     * @param    array
     * @return    array
     */    
    function _validate_request($segments)
    {
        $segments = $this->_pluck_directory($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
            $directory = $segments[0];
            $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))
                {
                    // Controller not found, try using the default controller
                    if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT)) {
                        show_404($this->fetch_directory().$this->default_controller);
                    }
                    
                    $new_segments = array_merge(array($this->default_controller), $segments);                    
                    return $new_segments;
                }
            }
            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]);
    }

#37
[eluser]r.tahara[/eluser]
anyone has try this with the 1.7.1 and works ?
I need this kind of library.. any help ?

ups, sorry, I think with combining all, should work... Smile
*because the code are parted, I confused which one that should i use..*

#38
[eluser]Torus[/eluser]
K, so I've been digging around learning how Peter's code works. I'm also trying to understand the original code that's being overridden, but I can't seem to find where the _set_route_mapping function is originally declared.

Any thoughts? Is it still needed? Is it part of an older version of CI? Thanks in advance.

#39
[eluser]dizzyagain[/eluser]
[quote author="r.tahara" date="1237820675"]anyone has try this with the 1.7.1 and works ?
I need this kind of library.. any help ?

ups, sorry, I think with combining all, should work... Smile
*because the code are parted, I confused which one that should i use..*[/quote]


I am also confused as to which code to make this work - and where to implement it.

I tried extending the native library of Router.php with MY_Router.php and using the code from the first post on this thread - no avail.

Any help would be appreciated - multi-sub-folders will be EXTREMELY useful for me!

Best,
dizzy

#40
[eluser]Jagar[/eluser]
Here is a working solution for CI 1.7.1

http://ellislab.com/forums/viewthread/107451/#541043

It's working for me with no modification to the code at all. Finally I can remove all those routings.


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.