How to set view subdirectory using MVC PHP - php

I'm currently having a problem displaying a page that's in a subfolder. The entire view of the site works fine, but for all the pages that are in a certain directory in the view folder, they are not displayed, that is, only the home page is displayed.
Controller:
class Controller {
protected function view($view, $data = []) {
if (file_exists('../app/views/' . $view . '.php')) {
include '../app/views/' . $view . '.php';
} else {
include '../app/views/404.php';
}
}
protected function loadModel($model) {
if (file_exists('../app/models/' . $model . ".php")) {
include '../app/models/' . $model . ".php";
return $model = new $model();
}
return false;
}
}
I'm almost sure that this is the problem because this code defines the display of only the files that are in the view directory, which does not include the files that will be found, for example, in the subdirectory. Can someone help me how to fix this problem? Thanks

Related

Fatal error: Uncaught Error: Call to a member function on bool

I know this answer has been answered already but it seems like I couldn't understand anything in my case (I'm still very new to web developing, learning frontend since this october and I jumped onto php at the start of this month).
My function is supposed to check if user is logged in and I couldn't understand the answers I read for my problem cause it seems like in the answers I found, the functions weren't custom? I might be wrong and I hope if I am, you can laugh about it.
So, to get a bit of context, I encounter this error when I try to call the function "check_logged_in()" in one of my controllers, this controller in question (it's called Upload) extends the main Controller from my core folder (and I triple checked if my init file has required it so I can use it globally).
Then I call a custom function from the main controller to load models if needed (in this case, I need to load my user model to get access to the "check_logged_in()" function since it's written there).
And this is where thing happen. I'll provide a bit of code so you guys can understand what I'm saying.
The Upload controller
<?php
class Upload extends Controller
{
function index()
{
header("location:" . ROOT . "upload/image");
die;
}
function image()
{
$user = $this->loadModel("user");
if(!$result = $user->check_logged_in()){
header("location:" . ROOT . "login");
die;
}
$data['page_title'] = "Upload";
$this->view("upload", $data);
}
}
The main Controller
<?php
class Controller
{
protected function view($view, $data = [])
{
if (file_exists("../app/views/" . $view . ".php")) {
include "../app/views/" . $view . ".php";
} else {
include "../app/views/404.php";
}
}
protected function loadModel($model)
{
if (file_exists("../app/model/" . $model . ".php")) {
include "../app/model/" . $model . ".php";
return $model = new $model();
}
return false;
}
}
And the bit of code from the user model that is called
<?php
class User
{
function check_logged_in()
{
$DB = new Database();
if (isset($_SESSION['user_url'])) {
$arr['user_url'] = $_SESSION['user_url'];
$query = "select * from users where url_address = :user_url limit 1";
$data = $DB->read($query, $arr);
if (is_array($data)) {
//logged in
$_SESSION['user_name'] = $data[0]->username;
$_SESSION['user_url'] = $data[0]->url_address;
return true;
}
}
return false;
}
}
Thanks in advance for your time mates, I hope my noob self is clear enough for you to understand ^^'
Checking for the correct value of the $user variable should fix the error.
...
function image()
{
$user = $this->loadModel("user");
if(!$user || !$user->check_logged_in()){ // Here
header("location:" . ROOT . "login");
die;
}
$data['page_title'] = "Upload";
...
Then on $user is false condition will be
!false || !false->check_logged_in() which will lead to true.
Otherwise on $user is User:
!(object User) || !(object User)->check_logged_in() will call User::check_logged_in() method.

How to create view data from model in basic PHP MVC System

I'm creating a simple PHP MVC system based on the "original" MVC principle, that is...
Controller instructs the model based on user input / queries and loads view
Model is a data layer is is unaware and independant from the controller or view
View creates own copy of data from Model for presentaion purposes
Everything I've done so far conforms to these principles, however, I've stumbled upon a problem as follows...
I set a default page title in the parent model
I inform the model to change its page title value using a model method based on the user page request in the correct controller method (index_controller/index)
I make a copy of models page title in the home view to b used on the template.
The problem is, the page title isnt updated because im setting the view variable in the index view constructor which happens before the model can be updated by the controller.
I can get the correct view variable by fetching and assigning it just before load the template, but the template loading is done in the parent view class which is an issue because different views require different variables.
Please let me know what I'm doing wrong! Any help is much appreciated!
It might help to see some of thecode in question...
lib/bootstrap.php
class Bootstrap {
function __construct() {
// Gets the request URL and seperate into array
$this->url = $this->getUrlArray();
// Generates the controller name based on URL array
$this->controller_name = $this->getControllerName();
// Loads controller file and creates new controller object
$this->controller = $this->getController();
// Calls requested methods based on URL array
$this->callMethods();
}
function getUrlArray() {
$url = isset($_GET['url']) ? rtrim($_GET['url'], '/') : 'index';
$url = explode('/', $url);
return $url;
}
function getControllerName() {
return $this->url[0] . '_controller';
}
function getController() {
$file = 'controllers/' . $this->controller_name . '.php';
if(file_exists($file)) {
require $file;
return new $this->controller_name($this->url[0]);
} else {
require 'controllers/error_controller.php';
return new Error_Controller('error');
}
}
function callMethods() {
if(!isset($this->url[1])) {
$this->controller->index();
} else {
$method_name = $this->url[1];
if(method_exists($this->controller, $method_name)) {
if(!isset($this->url[2])) {
$this->controller->$method_name();
} else {
$this->controller->$method_name($this->url[2]);
}
} else {
$this->controller->index();
}
}
}
}
lib/controller.php
class Controller {
protected $model;
public function __construct($name) {
$this->base_name = $name;
$this->model_name = $this->getModelName();
$this->model = $this->getModel();
$this->view_name = $this->getViewName();
$this->view = $this->getView();
//$this->creatView();
}
public function getModelName() {
return $this->base_name . '_model';
}
public function getViewName() {
return $this->base_name . '_view';
}
public function getModel() {
$file = 'models/' . $this->model_name . '.php';
if(file_exists($file)) {
require $file;
return new $this->model_name();
} else {
die('ERROR: This page is missing a model!');
}
}
public function getView() {
$file = 'views/' . $this->view_name . '.php';
if(file_exists($file)) {
require $file;
return new $this->view_name($this->model);
} else {
die('ERROR: This page is missing a view!');
}
}
}
lib/model.php
class Model {
public function __construct() {
$this->page_title = SITE_NAME;
}
public function setPageTitle($pre, $seperator) {
$this->page_title = $pre . ' ' . $seperator . ' ' . SITE_NAME;
}
}
lib/view.php
class View {
protected $model;
public function __construct(Model $model) {
$this->model = $model;
}
public function output($name, $noInclude = false) {
$file = 'templates/' . $name . '.php';
if(file_exists($file)) {
if($noInclude) {
require 'templates/' . $name . '.php';
} else {
require 'templates/header.php';
require 'templates/' . $name . '.php';
require 'templates/footer.php';
}
} else {
die('ERROR: This page is missing a template!');
}
}
}
controllers/index_controller.php
<?php
class Index_Controller extends Controller {
function __construct($name) {
parent::__construct($name);
}
function index() {
$this->model->setPageTitle('Home', '-');
var_dump($this);
$this->view->output('index/index');
}
function test($value = 'not set') {
echo 'You are in test and the value is ' . $value;
}
}
views/index_view.php
class Index_View extends View {
public function __construct(Model $model) {
parent::__construct($model);
$this->page_title = $this->model->page_title;
}
}
models/index_model.php
class Index_Model extends Model {
public function __construct() {
parent::__construct();
}
}
templates/header.php
<!DOCTYPE html>
<html>
<head>
<title><?php echo $this->page_title; ?></title>
</head>
<body>
<div id="header">
<!-- -->
</div>
<div id="content">
My var_dump in index_controller looks like this...
Cheers,
Tom

Using setParams with include

I'm trying to edit a template system so where I can use params such as [title] and it'll show my title in the included page. But I also want to be able to use php code inside of it and be able to execute that code. But I am having difficult getting them both to work at the same time.
I have tried to use include instead of file_get_Contents but when I use include, the params no longer work. However when I use file_get_contents the php doesnt work, and doesnt show.
My code:
class Template {
public function __construct($directory){
$this->dir = $directory;
}
public function setPage($pageName){
$this->directory = 'lib/' . $this->dir . '/' . $pageName . '.php';
if(file_exists($this->directory)) {
$Content = file_get_contents($this->directory);
}
}
public function newParam($trans, $val){
$this->param['[*' . $trans . '*]'] = $val;
}
public function setParams($element){
$element = str_replace(array_keys($this->param), array_values($this->param), $element);
return $element;
}
public function Create(){
die($this->setParams($Content));
}
}
Hope someone can help. Thanks

MVC bad url error handling

I´m making a tiny MVC framework for learning purpose.
I have a file and a class called load which is in my model folder. It reads the requested file name and checks if the file is in the views folder and returns the correct file.
The problem I´m having is that I´m trying to make a handling for bad urls so that if the requested file/url does not excist you are directed to the index.php page in the views folder...
I have an if statement inside the function that checks if the file exists and I thought I could just write an else statement requiring the index.php file incase the file was not found...
But this doesn´t work. All I´m getting is a white blank page when I type in an non existing page even I´f I try echo something in the else statement...
Does anyone know what´s missing or what I´m doing wrong?
UPDATE:
Added mainController class
This is what the hole load class looks like:
<?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 {
//This is where I thought I could require the index.php file...
}
}
}
And in my controller folder I have a mainController class sending the files to the load file.
This is what the mainController class looks like:
<?php
/* controller/main.php
*
*/
class mainController
{
public $load;
public $urlValues;
public function __construct()
{
$url = parse_url($_SERVER['REQUEST_URI']);
$url = explode('/', trim($url['path'], '/'));
$this->urlValues = array('controller' => $url[1]);
//Index page
if ($this->urlValues['controller'] == "index.php") {
$key = array("key" => "");
$this->load = new load();
$this->load->view('index.php', $key);
}
//Register page
if ($this->urlValues['controller'] == "register.php") {
$this->load = new load();
$this->load->view('register.php');
}
//Home page
if ($this->urlValues['controller'] == "home.php") {
$this->load = new load();
$this->load->view('home.php');
}
}
}
It looks as though you are only calling the view method when the controller matches, and therefore it never gets executed. Try something like this, and work from there:
<?php
/* controller/main.php
*
*/
class mainController
{
public $load;
public $urlValues;
public function __construct()
{
$url = parse_url($_SERVER['REQUEST_URI']);
$url = explode('/', trim($url['path'], '/'));
$this->urlValues = array('controller' => $url[1]);
// ifs go here
$this->load = new load();
$this->load->view($this->urlValues['controller']);
}
}

Call to undefined $class() in w3style blog article on PHP dynamic front controllers

All,
I am reading the following article on a lightweight PHP dynamic front controller: http://www.w3style.co.uk/a-lightweight-and-flexible-front-controller-for-php-5
Here is the code:
index.php
<?php
define("PAGE_DIR", dirname(__FILE__) . "/pages");
require_once "FrontController.php";
FrontController::createInstance()->dispatch();
FrontController.php
<?php
class FrontController {
public static function createInstance() {
if (!defined("PAGE_DIR")) {
exit("Critical error: Cannot proceed without PAGE_DIR.");
}
$instance = new self();
return $instance;
}
public function dispatch() {
$page = !empty($_GET["page"]) ? $_GET["page"] : "home";
$action = !empty($_GET["action"]) ? $_GET["action"] : "index";
//e.g. HomeActions
$class = ucfirst($page) . "Actions";
//e.g. pages/home/HomeActions.php
$file = PAGE_DIR . "/" . $page . "/" . $class . ".php";
if (!is_file($file)) {
exit("Page not found");
}
require_once $file;
$actionMethod = "do" . ucfirst($action);
$controller = new $class(); // I DON'T UNDERSTAND WHAT THIS DOES...
if (!method_exists($controller, $actionMethod)) {
exit("Page not found");
}
//e.g. $controller->doIndex();
$controller->$actionMethod();
exit(0);
}
}
pages/guestbook/GuestbookActions.php
<?php
class GuestbookActions {
public function doIndex() {
echo "Index action called...";
}
public function doCreatePost() {
echo "CreatePost action called...";
}
}
In the front controller class, could someone explain to me what $controller = new $class(); does? I don't understand it. It seems to be creating a class on the fly? In the example above, $class is a string with a value like "HomeActions". So $controller would be a new instance of a class named "HomeActions", but those are not defined anywhere. I'm confused.
Many thanks,
JDelage
$controller = new $class();
That does indeed create a new object of the type contained in $class, so it is equivalent to $controller = new HomeActions() in your example. From the manual:
If a string containing the name of a class is used with new, a new instance of that class will be created
The classes are not all present initially. However, the necessary one is loaded dynamically:
$file = PAGE_DIR . "/" . $page . "/" . $class . ".php";
if (!is_file($file)) {
exit("Page not found");
}
require_once $file;
require_once loads the file which presumably contains the class definition, so you can create the object as shown above.
The example request in the article is to http://localhost/index.php?page=guestbook&action=index, so $class would be GuestbookActions, which is defined in the third code sample.

Categories