Welcome Guest, Not a member yet? Register   Sign In
Modules and Views
#1

(This post was last modified: 03-29-2021, 02:20 PM by [email protected].)

CodeIgniter 4.1.1  PHP7.4.4

Cannot get module views to work:

http://localhost/Airports/moduleTest  results in:
viewException:
Invalid file: Bobk\airports\views\moduleTest.php


This is the setup.

I've created my namespace called 'Bobk' in app/Config/Autoload.php
Code:
// app/Config/Autoload.php

public $psr4 = [
APP_NAMESPACE => APPPATH, // For custom app namespace
'Config'      => APPPATH . 'Config',
'Bobk'          => ROOTPATH.'Bobk'
];

In folder ROOTPATH/Bobk I have a module folder called 'airports'
airports/controllers/Airports.php
airports/models/Airport_model.php (not used to show problem)
airports/views/moduleTest.php

My airports/controllers/Airports.php file:
Code:
<?php namespace Bobk\Airports\controllers;

use App\Controllers\BaseController;
use Bobk\Airports\models\Airport_Model;

class Airports extends BaseController
{

.......

    public function moduleTest()
    {
        $data['title']="Module View";
        echo view('Bobk\airports\views\moduleTest', $data);
    }
}

// app\Config\routes.php
Code:
/*
* --------------------------------------------------------------------
* Route Definitions
* --------------------------------------------------------------------
*/
$routes->get('/', 'Home::index');

$routes->get('Airports/moduleTest', '\Bobk\airports\Controllers\Airports::moduleTest');


// ROOTPATH/Bobk/airports/views/moduleTest.php
Code:
<html>
<head>
</head>
<body>
<h2><?= esc($title) ?></h2>
<h3>Hello</h3>
</body>
</html>


THE PROBLEM
// system/View/View.php LINE:195
Code:
if (! is_file($this->renderVars['file']))
{
     $this->renderVars['file'] = $this->loader->locateFile($this->renderVars['view'], 'Views', empty($fileExt) ? 'php' : $fileExt);

This call to locateFile() has the $folder argument set to the literal string 'Views'
This results in the resolved view path being:

ROUTEPATH\Bobk\/Views/airports/views/moduleTest.php"

(I've used ROUTEPATH to avoid having to type the complete path)

Notice that this call to locateFile has placed </Views/> (the $folder argument) in between
Bobk\ and airports. This is obviously an incorrect path and results in 
ViewException:
Invalid file: Bobk\airports\views\moduleTest.php

Note:
locateFile() returns false if it can't locate the view file, NOT the offending path which
is probably why the invalid file displayed on screen doesn't match.

WHAT APPEARS TO WORK (but for how long ?)
Edit system/View/View.php LINE:197 and replace 'Views' argument with an empty string ''
Code:
197 $this->renderVars['file'] = $this->loader->locateFile($this->renderVars['view'], '', empty($fileExt) ? 'php' : $fileExt);

Not advocating this as a real fix but haven't yet managed to find out why the
'Views' argument is there and what it is meant
to achieve. Testing this modification with modules and with normal app controllers
and views works.
Must be a reason for 'Views' argument and I look forward to finding out from those
wiser (more informed) than me.
Reply
#2

After all that I seem to have found the solution.


Code:
// Airports Controller

    public function moduleTest()
    {
        $data['title']="Module View";
    echo view('Bobk\airports\Views\moduleTest', $data);
    }
The word 'Views' must start with a capital V.
Previously had it set to:
echo view('Bobk\airports\views\moduleTest', $data);

This is regardless of how the folder names are actually written in the file system.
Mine are all lower case (windows) after the namespace prefix
 Bobk/airports/controllers
 Bobk/airports/models
 Bobk/airports/views

This is where 'Views' must be capitalized first letter
system/AutoLoader/FileLocator::locateFile
Code:
    // If we have a folder name, then the calling function
    // expects this file to be within that folder, like 'Views',
    // or 'libraries'.
    if (! empty($folder) && strpos($path . $filename, '/' . $folder . '/') === false)
    {
                $path .= trim($folder, '/') . '/';
    }
The PHP function strpos() is case sensitive.
If $folder is set to 'views' (lowercase first letter) strpos() returns false and "Views/" is added to $path
resulting in a $path which is incorrect.

If $folder is set to 'Views' (capital first letter) strpos() returns a positive number (position) and 
the If block is NOT executed so $path is not modified and subsequently the correct full pathname
is returned.
Reply
#3

When calling views in modules you need to pass the full namespace to the view.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#4

Thanks InsiteFX for replying although I'm not sure what contribution you are trying to make.
Is this just a generic comment not directly related to my post
Where in my code do I not use a fully qualified namespace when I call the view function ?

As it turned out, the main thing to surface from this was that you MUST use a capital 'V' in
the word 'Views' in the FQ namespace when calling a module view. Regardless of how you have spelt it in the filesystem.
Using a lowercase 'v' will result in a ViewException.
Try it.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB