unrequire a php file - php

Im working on a website - just learning to improve my coding.
I have a routing system which works like this:
/config/routes.php:
$route->add('/' , function() {
require_once("/application/pages/index.php");
});
$route->add('/register', function() {
require_once("/application/pages/register.php");
});
$route->add('/login', function() {
require_once("/application/pages/login.php");
});
$route->add('/logout', function() {
require_once("/application/pages/logout.php");
});
$route->add('/panel', function() {
require_once('/application/pages/panel/index.php');
});
And in my index.php:
require_once('application/pages/header.php');
include('config/routes.php');
require_once('application/pages/footer.php');
Everything works fine but I need a different header.php and footer.php for when the user goes into the panel. file: /application/pages/panel/index.php
When I require_once a new header file in the panel/index.php then both the new and old header file is loaded. How can I unrequire the header and footer files in the /panel/index.php so I can require different ones? Any suggestions?

Note: Routing comes from an MVC design pattern, you should keep your controllers separate from your views.
Templates and Views could be kept separate, also. This meaning our directory set-up can look something like this:
- Templates
- header_one.php
- footer_one.php
- header_two.php
- footer_two.php
- Views
- index.php
- someOtherBody.php
Here is a simple, but unfinished (that is your challenge) example of an Object that could do what I am explaining:
class Page {
private $template_path = dirname(dirname(__FILE__)) . '/templates/';
private $view_path = dirname(dirname(__FILE__)) . '/views/';
protected $header;
protected $footer;
protected $body;
public function setHeader($file_name)
{
if(is_readable($this->template_path . $file_name))
{
$this->header = $this->template_path . $file_name;
return $this;
}
// add an exception
}
/* TODO: */
public function setFooter() {}
public function setBody() {}
/* Render page */
public function render()
{
$page = [$this->header,$this->body,$this->footer];
foreach($page as $file)
{
require_once($file);
}
}
}
The idea here is that we can set our page layout, using the above object, within the route method closure, then render / require all the files after the logic.
$route->add('/', function() {
$page = new Page();
$page->setHeader('header_one.php')
->setBody('index.php')
->setFooter('footer_one.php');
/* todo: add your logic here */
$page->render();
});
Each route can now have its own header, footer and body.
Hope this helped.

At your place, I will do something like that :
Use out buffer and check if the file is already required. I give you an quick example but adapt the code for you.
And check the function : http://php.net/manual/en/function.get-included-files.php
$route->add('/panel', function() {
include_once('YOUR_SPECIFIC_PATH/header.php');
require_once('/application/pages/panel/index.php');
include_once('YOUR_SPECIFIC_PATH_header/footer.php');
});
And :
ob_start();
include_once('config/routes.php');
$mainContent = ob_get_contents();
ob_end_clean();
include_once('application/pages/header.php');
echo $mainContent;
include_once('application/pages/footer.php');
I've not the time for help more sorry but I can explain later if you need

This solution requires you to have a header.php and footer.php in each folder where your sub-controllers (application/<module name>/index.php) are.
index.php only call your sub-controllers via routing:
// require not include, because "no routing" = "no web site" ;)
require_once('config/routes.php');
application/pages/index.php include appropriate header/footer w/ relative path
require_once('header.php');
// page code
require_once('footer.php');
application/register/index.php include appropriate header/footer w/ relative path
require_once('header.php');
// page code
require_once('footer.php');
etc

#KDOT , thanks you for your help but using your code I was getting an error that I could not fix:
Call to a member function setBody() on null
but thanks to your code, I managed to rewrite the class my way and now it works ;)
Thanks again #KDOT !
If anyone needs it:
class Page {
private $TEMPLATE_PATH = '/application/templates/';
private $VIEW_PATH = '/application/views/';
protected $header;
protected $footer;
protected $body;
public function __construct($header_file, $body_file, $footer_file) {
$this->header = $this->TEMPLATE_PATH . $header_file;
$this->body = $this->VIEW_PATH . $body_file;
$this->footer = $this->TEMPLATE_PATH . $footer_file;
}
public function render(){
$page = [$this->header, $this->body, $this->footer];
foreach($page as $file) {
require_once($file);
}
}
}
and:
$route->add('/', function() {
$page = new Page('header.php', 'home.php', 'footer.php');
$page->render();
});

Related

Getting Undefined index error and Method name must be a string in ..error in PHP

While upgrading to PHP7, I encountered these problem.
The issue is am trying to create codes that I can reuse like a mini-framework and the RUN function where the problem is used to load the relevant template and supplying the variables. It complains about
undefined index
of these 2 variables
$controller = $routes[$this->route][$this->method]['controller'];
$action = $routes[$this->route][$this->method]['action'];
and it also complained about this line
$page = $controller->$action();
which displayed
Fatal error: Uncaught Error: Method name must be a string in...
public function run() {
$routes = $this->routes->getRoutes();
$authentication = $this->routes->getAuthentication();
if (isset($routes[$this->route]['login']) && !$authentication->isLoggedIn()) {
header('location: /login/error');
}
else if (isset($routes[$this->route]['permissions']) && !$this->routes->checkPermission($routes[$this->route]['permissions'])) {
header('location: /login/permissionserror');
}
else {
$controller = $routes[$this->route][$this->method]['controller'];
$action = $routes[$this->route][$this->method]['action'];
$page = $controller->$action();
$title = $page['title'];
if (isset($page['variables'])) {
$output = $this->loadTemplate($page['template'], $page['variables']);
}
else {
$output = $this->loadTemplate($page['template']);
}
echo $this->loadTemplate('layout.html.php', ['loggedIn' => $authentication->isLoggedIn(),
'output' => $output,
'title' => $title
]);
}
This is the index.php
try {
include __DIR__ . '/../includes/autoload.php';
$route = ltrim(strtok($_SERVER['REQUEST_URI'], '?'), '/');
$entryPoint = new \Ninja\EntryPoint($route, $_SERVER['REQUEST_METHOD'], new \Ijdb\IjdbRoutes());
$entryPoint->run();
}
catch (PDOException $e) {
$title = 'An error has occurred';
$output = 'Database error: ' . $e->getMessage() . ' in ' .
$e->getFile() . ':' . $e->getLine();
include __DIR__ . '/../templates/layout.html.php';
}
The code is much, so, I can't display the whole code here since am using MVC pattern, but if there is anything you still want to know, I will gladly post it here
This code is runnable in php 7.2.7 (MAMP and LAMP), your way of dynamic function calling is invalid and your two variables are empty. This is not exact as yours but you can take logic form this demo.
Ok i am just providing a very simple example of reflection with mapping url to class along with functions. I make folder structure like below-
Here .htaccess is used to redirect all the url to index.php (if no file exists).
index.php include all code that could initialize code(for now only three files were there - uri.php, urlMapping.php and actions.php)
URI.php - have function that provide values like basepath, baseurl, uri
urlMappig.php - that allows you to provide which url hit which class along with method
actions.php will call dynamic class and function (reflection)
now look into code of index.php
<?php
include_once('URI.php');
include_once('urlMapping.php');
include_once('actions.php');
?>
aNow code insise uri.php file -
<?php
// all function should be accessible to all file loaded now
// return full url
function full_url (){
return (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
}
// returns current directory
function directory() {
$parts = explode("/", __DIR__);
return $parts[count($parts)-1];
}
// return base url
function base_url(){
$dir = directory();
return substr(full_url(), 0, strpos(full_url(), $dir)+strlen($dir));
}
// return uri
function uri() {
return substr(full_url(), strlen(base_url())+1);
}
?>
Now code in urlMapping.php
Note - file name and name of the class must be same as you map url in
this file so that you can make call to dynamic classes and function on actions.php. If don't this will not work
<?php
// this $urlMap will be accessed in actions.php
$urlMap = [
// here we use only uri so .. https://example.com/login hit LoginController class along with login function, this is just only the mapping
'login' => ['class'=>'LoginController',
'function'=>'login'],
];
?>
Now actions.php code
<?php
// if call is not like example.com/ means no uri is there
if(uri()!='')
{
// if your uri exists in route collection or urlmapping collection then make call to your dynamic class and methods
if(array_key_exists(uri(), $urlMap))
{
// include the class file dynamically from controllers folder
include_once('controllers/'.$urlMap[uri()]['class'].'.php');
// making references for dynamic class
$controlerObject = new $urlMap[uri()]['class']();
// call function dynaically from the referece
$controlerObject->{$urlMap[uri()]['function']}();
}
else
{
// you can make 404 page not
echo 'No routing found';
}
}
// call for home page
else
{
include_once('index.html.php');
}
?>
Now controllres/LoginController.php class,
Note - As mentioned above file name and name of the class as in urlMapping.php
<?php
class LoginController{
public function login()
{
// .... something your code goes here
echo 'hello from the login function of login controller';
}
//...... other function you can define
}
?>
Before calling $page = $controller->$action(); check if controller and action are exists:
if (isset($routes[$this->route][$this->method]['controller'])
&& isset($routes[$this->route][$this->method]['action'])) {
$controller = $routes[$this->route][$this->method]['controller'];
$action = $routes[$this->route][$this->method]['action'];
$page = $controller->$action();
// ...
} else {
// return 404 Page not found
}

How To Use MVC PHP With Case Sensitive?

I am creating website in PHP. I am using MVC in PHP. My website works like this, if user go to example.com/about then it it will load About class and index() function. If user will go to localhost/about/founder then it will load founder() function from About class. but the thing is that if I go to localhost/About or localhost/AbOut or anything like that it is loading default index() function from About class file. So what to do with case sensitivity? I mean I want my script to load index() function from class file if it is localhost/about or localhost/terms. If anything is in uppercase, then it should load 404 error function. 404 error function is already set in my site.
Please help me friends.
here is my Bootstrap.php class file
<?php
/*
Bootstrap class to run functions by URL
*/
class Bootstrap {
public $_req;
public $_body;
public $_file;
public $_error;
function __construct(){
if(empty($_GET['req'])){
require 'classes/home.php';
$this->_body = new Home();
$this->hdr($this->_body->head());
$this->_body->index();
$this->ftr();
exit();
}
$this->_req = rtrim($_GET['req'], '/');
$this->_req = explode('/', $this->_req );
$_file = 'classes/'.$this->_req[0].'.php';
if(file_exists($_file)){
require $_file;
}
else {
$this->error(404);
}
$this->_body = new $this->_req[0];
$this->hdr($this->_body->head());
if(isset($this->_req[2])){
if(method_exists($this->_req[0], $this->_req[1])){
$this->_body->{$this->_req[1]}($this->_req[2]);
}else {
$this->error(404);
}
}else {
if(isset($this->_req[1])){
if(method_exists($this->_req[0], $this->_req[1])){
$this->_body->{$this->_req[1]}();
}else {
$this->error(404);
}
}else {
$this->_body->index();
}
$this->ftr();
}
}
//this function is to set header in html code
public function hdr($var = false){
echo '<!DOCTYPE HTML><html><head>'.$var.'</head><body>';
}
//this function is tp set footer in html code
public function ftr($var = false){
echo $var.'</body></html>';
}
//error handler
public function error($var){
require 'classes/er_pg.php';
$this->_error = new Error();
$this->_error->index($var);
}
}
You shouldn't use anything to load non-lowercase URLs because of the duplicate content, and that's a good thing you're doing. The wrong URLs should fail automatically in such cases.
However, since you didn't show how are you making those calls, then only thing I can suggest at this point is to check if the called method exists (case-sensitive), and if not, throw/redirect to a 404 page (header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");).
UPDATE
After all the chat in the comments, seems like file_exists is not case-sensitive in your case, which is really weird. Hopefully someone will be able to figure it out so I can delete this (keeping it because of the info in the comments).
I solved the problem. I used this
if(ctype_lower($this->_req[0])){
$_file = 'classes/'.$this->_req[0].'.php';
and now its working. Thanx anyways friends.

Header & Footer not showing up

So with a little help I was able to get my first mvc framework up and running locally. Now that I've put it up on the server I'm not having any luck. I believe it's a configuration issue but I can't seem to figure it out.
Here's a Gif of what it should look like on the server but this is running it locally.
Why is nothing showing up when I go directly to the remote path? ie:
This does not work:
http://tomcat.cit.iupui.edu/alecory/Spring-2014/CIT-31300/Assignment%202/
Unless I set the 'URI' constant directly to '/register' which is it's output when running on localhost as seen in the notes below
This works but isn't what I want & doesn't include the header + footer:
http://tomcat.cit.iupui.edu/alecory/Spring-2014/CIT-31300/Assignment%202/views/register.php
config.php
<?php
include_once 'load.php';
// Local
// define ('URL_ROOT', 'http://localhost/');
// Remote
define ('URL_ROOT', 'http://tomcat.cit.ipui.edu/alecory/Spring-2014/Assignment%202/');
// define ('URI', $_SERVER['REQUEST_URI']);
// Outputs for:
// Local = /register
// Remote = /alecory/Spring-2014/CIT-31300/Assignment%202/views/register.php
define('URI', '/register'); // <= this is where I could set it myself and
# it would reroute the URL from
# /Assignment%202/views/register.php To
# /Assignment%202/
# (only showing /Assignment%202/ in the URL)
define ('DOC_ROOT', $_SERVER['DOCUMENT_ROOT']);
// Local = /Applications/MAMP/htdocs/CIT-31300/Assignment 2
// Remote = /var/www/
?>
controller.php
<?php
/**
* Controller
*
* Description: Basically tells the system what to do and in what order
*/
class Controller
{
public $load;
public $model;
function __construct()
{
// Make
$this->load = new Load();
$this->model = new Model();
// Set the $page = current view/page
$page = ltrim(URI, '/');
// Set default page to index
if (empty($page))
{
$page = 'index';
}
// Load the Pages
if (method_exists($this, $page))
{
// die(get_include_path());
require_once DOC_ROOT . '/views/inc/header.php';
$this->$page();
require_once DOC_ROOT . '/views/inc/footer.php';
}
else
{
require_once DOC_ROOT . '/views/inc/header.php';
$this->notFound();
require_once DOC_ROOT . '/views/inc/footer.php';
}
}
// Functions to load the various views
function index()
{
// $data = $this->model->my_user_info();
$this->load->view('myview.php', $data);
}
// function header()
// {
// $this->load->view('header.php', $data);
// }
// function footer()
// {
// $this->load->view('footer.php' $data);
// }
function login()
{
$this->load->view('login.php', $data);
}
function register()
{
$this->load->view('register.php', $data);
}
function notFound()
{
die('not found');
}
}
?>

Get correct url / page to load in simple MVC

I´m making a "very" simple MVC framework in order to learn, however I have trouble getting other pages than the index page to show. In views folder I have 2 files one index.php and one register.php that I´m trying on.
I have tried various ways but can´t get my head around it. I know it is probably best to put different controller classes in different files and maybe a loader controller page but I´m a beginner with php so would like to make it as simple as possible for me...
Any help appriciated!
I have a index.php as a landing file in the root folder to bind everything together:
<?php
/* index.php
*
*/
require_once 'model/load.php';
require_once 'controller/main.php';
new mainController();
In the controller folder i have a file called main.php:
<?php
/* controller/main.php
*
*/
class mainController
{
public $load;
public function __construct()
{
$urlValues = $_SERVER['REQUEST_URI'];
$this->urlValues = $_GET;
//index page
if ($this->urlValues['controller'] == "") {
$indexPage = array("key" => "Hello");
$this->load = new load();
$this->load->view('index.php', $indexPage);
}
//register page
if ($this->urlValues['controller'] == "register.php") {
$registerPage = array("key" => "Register");
$this->load = new load();
$this->load->view('register.php', $registerPage);
}
}
}
And then I have a file called load.php in the model folder:
<?php
/* model/load.php
*
*/
class load
{
/* This function takes parameter
* $file_name and match with file in views.
*/
function view($file_name, $data = null)
{
if (is_readable('views/' . $file_name)) {
if (is_array($data)) {
extract($data);
}
require 'views/' . $file_name;
} else {
echo $this->file;
die ('404 Not Found');
}
}
}
In your mainController class you don't have property with the name urlValues, but you use it: $this->urlValues = $_GET;. And what is more you have local variable with the same name, that you don't use: $urlValues = $_SERVER['REQUEST_URI'];
And how you URL for register.php looks like?

Parse_url and ($_SERVER['REQUEST_URI'])

I´m trying to pick up the correct path with parse_url and $_SERVER['REQUEST_URI'] in order to show the correct page, however the problem I´m having is that only my index.php page is showing.
The url to my index.php page should be localhost/mvc-framework which is all correct, but when I take:
localhost/mvc-framework/file.php it is also showing my index.php. Basically anything I type in after somefolder also show the index.php page...
I really hope someone can help me out as I´ve been struggling with this for almost 3 hole days.
I´m probably stupid:/
I have all files in "mvc-framework" and inside I have one index.php file that ties everything together and 3 folders: "controller", "model", "views".
In controller folder I have one file called main.php which is were I´m trying to pick up the url:
<?php
/* controller/main.php
*/
class mainController
{
public $load;
public $urlValues;
public function __construct()
{
$url = parse_url($_SERVER['REQUEST_URI']);
$url = explode('/', $url['path']);
$this->urlValues = array('controller' => $url[1]);
//index page
if ($this->urlValues['controller'] == "mvc-framework") {
$text = array("key" => "Hello");
$this->load = new load();
$this->load->view('index.php', $text);
}
//register page
elseif ($this->urlValues['controller'] == "mvc-framework/test.php") {
$text = array("key" => "Test");
$this->load = new load();
$this->load->view('test.php', $text);
} else {
echo 'error';
}
}
}
In the "model" folder I have one file called load.php which will take the url and point it to the the correct file in the views folder...
<?php
/* model/load.php
*/
class load
{
/* This function takes parameter
* $file_name and match with file in views.
*/
function view($file_name, $data = null)
{
if (is_readable('views/' . $file_name)) {
if (is_array($data)) {
extract($data);
}
require 'views/' . $file_name;
} else {
echo $this->file;
die ('404 Not Found');
}
}
}
In the views folder I have 2 files, one index.php and one test.php...
And here is my bootstrap/index.php file which is in the root folder and bind everything together...
<?php
/* index.php
*/
require_once 'model/load.php';
require_once 'controller/main.php';
new mainController();
try this
$url = explode('/', trim($url['path'], '/'));
and $this->urlValues['controller'] == 'test.php' for request localhost/mvc-framework/test.php
You always get the index.php beacuse of the .htaccess file, which always redirect the request to the frontend controller, index.php. I suppose...

Categories