Direct link to a subfolder view returns 404

2019-07-19 02:39发布

问题:

I cannot directly load a view that is in a subfolder in my CodeIgniter views folder with a direct link.

Here is the folder structure:

my_project/
    application/
        views/
            pages/
                about.php
                about/
                    organization.php
                    history.php

I need to access organization.php and history.php through a link such as:

<div id="container">
    <ul>
        <li>
            <a href='<?php echo base_url('about'); ?>'>About</a>
        </li>
        <li>
            <a href='<?php echo base_url('about/organization'); ?>'>About/Organization</a>
        </li>
        <li>
            <a href='<?php echo base_url('about/history'); ?>'>About/History</a>
        </li>
    </ul>
</div>

However I get a 404.

My htaccess:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /my_project/

# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /my_project/$1$2 [R=301,NE,L]

# Directs all EE web requests through the site index file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /my_project/index.php/$1 [L]
</IfModule>

Here is my routes.php that directs to my default view controller Pages::view(path/to/file):

$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;

$route['pages/(:any)/(:any)'] = 'pages/view/$1/$2';
$route['(:any)'] = 'pages/view/$1';

Here is my controller:

<?php
class Pages extends CI_Controller
{
    function __construct()
    {
        parent::__construct();
    }

    public function view($page = 'home')
    {
        if(!file_exists(APPPATH.'views/pages/'.$page.'.php'))
        {
            show_404();
        }

        $data['title'] = strtoupper(str_replace(["-", "–"], ' ', $page));
        $this->load->view('templates/header', $data);
        $this->load->view('pages/'.$page, $data);
        $this->load->view('templates/footer', $data);
    }
}

NOTE whenever I directly use

$this->load->view('pages/views/about/organization');

it is okay. Same with printing:

file_exists(APPPATH.'views/pages/about/organization.php');

I don't know what could have messed this up.

Do I have to make a custom controller just for these subfolders? This is the only solution I can think of right now.


NOTE I also set this subfolder's (the entire project's actually) permissions to 777 and the direct link still did not work.


NOTE My only solution right now is to make separate controllers for each of these subfolders just to view them! Is this really impossible to do with just one controller?

Like the url pattern my_app/controller/method is strict and my_app/folder/view is not allowed unless folder and view corresponds to a controller and method respectively?


SOLUTION

Zeeshan did that!

Shantay, you stay! Thank you.

You are correct, I was going for a generic method to catch all my static page view requests. We can close this issue now (I will award the bounty in 20 hours).

You were the only one who understood the assignment.

回答1:

After going through your question,i found that you are trying to write some generic function that will take care of loading your views.Please refer below as you can handle any structure in codeigniter.

Controller function will go like this

public function view($folder='',$page = 'home')
{       
    $path = $folder!=""?$folder.'/':'';
    $path = $page!=""?$path.$page:$page;

    $this->load->view('templates/header', $data);
    **$this->load->view($path, $data);**
    $this->load->view('templates/footer', $data);
}

Now in your views the link will go like this:

<div id="container">
<ul>
    <li>
        <a href='<?php echo base_url."about/"; ?>'>About</a>
    </li>
    <li>
        <a href='<?php echo base_url."about/organization" ?>'>About/Organization</a>
    </li>
    <li>
        <a href='<?php echo base_url."about/history" ?>'>About/History</a>
    </li>
</ul>

Also please note in Codeigniter you don't need to handle 404 manually.Just add following to show your custom

$route['404_override'] = 'mycustom404';//mycustom404 is controller for 404

Let me know if you have any doubts or queries.

Regards, Zeeshan.



回答2:

I think CodeIgniter's URI pattern is strictly controller/method and no love for subfolder/view_file.

I just made a controller for About with methods organization and history that will show the page.

<?php
class About extends CI_Controller
{
    function __construct()
    {
        parent::__construct();
        $this->load->helper('url');
    }

    function organization($page = 'organization')
    {
        if(!file_exists(APPPATH.'views/pages/about/'.$page.'.php'))
        {
            show_404();
        }

        $data['title'] = strtoupper(str_replace(["-", "–"], ' ', $page));
        $this->load->view('templates/header', $data);
        $this->load->view('pages/about/'.$page, $data);
        $this->load->view('templates/footer', $data);
    }

    function history($page = 'history')
    {
        if(!file_exists(APPPATH.'views/pages/about/'.$page.'.php'))
        {
            show_404();
        }

        $data['title'] = strtoupper(str_replace(["-", "–"], ' ', $page));
        $this->load->view('templates/header', $data);
        $this->load->view('pages/about/'.$page, $data);
        $this->load->view('templates/footer', $data);
    }
}

I will probably do this for Contact Us, FAQs...

Apparently this is the correct answer. Use controllers and methods to show a page with the form subfolder/view. WIG.



回答3:

I modified the Pages::view() to not have a default parameter:

<?php
class Pages extends CI_Controller
{
    function __construct()
    {
        parent::__construct();
    }

    public function view()
    {
        $page = $this->uri->segment(1);
        if(!empty($this->uri->segment(2))) {
            $page .= '/'.$this->uri->segment(2);
        }

        if(!file_exists(APPPATH.'views/pages/'.$page.'.php'))
        {
            show_404();
        }

        $data = "";
        $this->load->view('templates/header', $data);
        $this->load->view('pages/'.$page, $data);
        $this->load->view('templates/footer', $data);
    }
}

The pages in my site so far have one level of subfolder so I hardcoded the following:

$page = $this->uri->segment(1);
if(!empty($this->uri->segment(2))) {
    $page .= '/'.$this->uri->segment(2);
}

Given my link http://localhost:8080/practice/item-2/subitem-2, the value of the URI segments are as follows:

$this->uri->segment(1) == 'item-2'
$this->uri->segment(2) == 'subitem-1'

I updated the routes.php with hardcoded catchers as well:

$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;

$route['pages/(:any)'] = 'pages/view/$1';
$route['pages/(:any)/(:any)'] = 'pages/view/$1/$2';
$route['pages/view/(:any)'] = 'pages/view/$1';
$route['pages/view/(:any)/(:any)'] = 'pages/view/$1/$2';
$route['(:any)'] = 'pages/view/$1';
$route['(:any)/(:any)'] = 'pages/view/$1/$2';