I am new to MVC and just started practicing with it. I am creating a small to medium size corporate website and did not want to use any big frameworks so I found this and so far it is working pretty well. The only thing that I don't seem to understand is how to render a view in a subfolder.
I have 3 medicines I need to display info for and they are structured like this:
views
--medicines
----medicine1
------info.php
------forms
--------male.php
--------female.php
Here is the medicine controller:
<?php
class MedicinesController extends Controller
{
/**
* Construct this object by extending the basic Controller class
*/
public function __construct()
{
parent::__construct();
Auth::checkAuthentication();
}
/**
* Handles what happens when user moves to URL/medicines/index
**/
public function index()
{
$this->View->render('medicines/index');
}
/**
* Handles what happens when user moves to URL/medicines/medicine1
**/
public function medicine1()
{
$this->View->render('medicines/medicine/info', array(
'files' => FilesModel::getMedicineFiles())
);
}
/**
* Handles what happens when user moves to URL/medicines/medicine1/forms/male
**/
public function male()
{
$this->View->render('medicines/imnovid/forms/male');
}
}
This is the class that handles controllers:
/**
* Class Application
* The heart of the application
*/
class Application
{
/** @var mixed Instance of the controller */
private $controller;
/** @var array URL parameters, will be passed to used controller-method */
private $parameters = array();
/** @var string Just the name of the controller, useful for checks inside the view ("where am I ?") */
private $controller_name;
/** @var string Just the name of the controller's method, useful for checks inside the view ("where am I ?") */
private $action_name;
/**
* Start the application, analyze URL elements, call according controller/method or relocate to fallback location
*/
public function __construct()
{
// create array with URL parts in $url
$this->splitUrl();
// creates controller and action names (from URL input)
$this->createControllerAndActionNames();
// does such a controller exist ?
if (file_exists(Config::get('PATH_CONTROLLER') . $this->controller_name . '.php')) {
// load this file and create this controller
// example: if controller would be "car", then this line would translate into: $this->car = new car();
require Config::get('PATH_CONTROLLER') . $this->controller_name . '.php';
$this->controller = new $this->controller_name();
// check for method: does such a method exist in the controller ?
if (method_exists($this->controller, $this->action_name)) {
if (!empty($this->parameters)) {
// call the method and pass arguments to it
call_user_func_array(array($this->controller, $this->action_name), $this->parameters);
} else {
// if no parameters are given, just call the method without parameters, like $this->index->index();
$this->controller->{$this->action_name}();
}
} else {
// load 404 error page
require Config::get('PATH_CONTROLLER') . 'ErrorController.php';
$this->controller = new ErrorController;
$this->controller->error404();
}
} else {
// load 404 error page
require Config::get('PATH_CONTROLLER') . 'ErrorController.php';
$this->controller = new ErrorController;
$this->controller->error404();
}
}
/**
* Get and split the URL
*/
private function splitUrl()
{
if (Request::get('url')) {
// split URL
$url = trim(Request::get('url'), '/');
$url = filter_var($url, FILTER_SANITIZE_URL);
$url = explode('/', $url);
// put URL parts into according properties
$this->controller_name = isset($url[0]) ? $url[0] : null;
$this->action_name = isset($url[1]) ? $url[1] : null;
// remove controller name and action name from the split URL
unset($url[0], $url[1]);
// rebase array keys and store the URL parameters
$this->parameters = array_values($url);
}
}
/**
* Checks if controller and action names are given. If not, default values are put into the properties.
* Also renames controller to usable name.
*/
private function createControllerAndActionNames()
{
// check for controller: no controller given ? then make controller = default controller (from config)
if (!$this->controller_name) {
$this->controller_name = Config::get('DEFAULT_CONTROLLER');
}
// check for action: no action given ? then make action = default action (from config)
if (!$this->action_name or (strlen($this->action_name) == 0)) {
$this->action_name = Config::get('DEFAULT_ACTION');
}
// rename controller name to real controller class/file name ("index" to "IndexController")
$this->controller_name = ucwords($this->controller_name) . 'Controller';
}
}
Config
/**
* Configuration for: Folders
* Usually there's no reason to change this.
*/
'PATH_CONTROLLER' => realpath(dirname(__FILE__).'/../../') . '/application/controller/',
'PATH_VIEW' => realpath(dirname(__FILE__).'/../../') . '/application/view/',
/**
* Configuration for: Default controller and action
*/
'DEFAULT_CONTROLLER' => 'index',
'DEFAULT_ACTION' => 'index',
And the render
public function render($filename, $data = null)
{
if ($data) {
foreach ($data as $key => $value) {
$this->{$key} = $value;
}
}
require Config::get('PATH_VIEW') . '_templates/header.php';
require Config::get('PATH_VIEW') . $filename . '.php';
require Config::get('PATH_VIEW') . '_templates/footer.php';
}
If I do var_dump();
I get this output:
D:\Programs\wamp64\www\ermp.ee\application\core\Application.php:84:
object(Application)[3]
private 'controller' => null
private 'parameters' =>
array (size=2)
0 => string 'forms' (length=5)
1 => string 'male' (length=4)
private 'controller_name' => string 'medicines' (length=9)
private 'action_name' => string 'imnovid' (length=7)
Simple urls
When you access http://ermp.ee/medicines/
, it renders application/view/medicines/index.php
file due to the following line:
$this->View->render('medicines/index');
When you access http://ermp.ee/medicines/medicine1/forms/male
it renders application/view/medicines/info.php
file with files
param due to
$this->View->render('medicines/medicine/info'...
You pass the view filename directly to View
. forms
and male
are stored in Application
's private property parameters
.
In this case controller_name
is MedicinesController
, action_name
is medicine1
.
URLs with male
When you access http://ermp.ee/medicines/male
, controller_name
is MedicinesController
, action_name
is male
, but the view rendered is medicines/imnovid/forms/male.php
because of the following line:
$this->View->render('medicines/imnovid/forms/male');
No matter what is the path to a view, action_name
is got from URI. It is just a convention to use path according to action name, you are free to render whatever you want.
From what I read in the Github repository you linked to, if you want to render a view that is stored in a subdirectory, you should be able to do so by using forward slashes in the filename passed to render()
.
In the controller, to render info.php
, you could call
$this->View->render('medicines/medicine1/info');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With