Also, is a view 'allowed' to talk to (eg: get data from) a controller (for example: by calling a method that controller owns)?
La best practice è no, ma a un controllore è consentito passare un dato alla vista. Scopri i motori di template come Moustache .
I'm trying to have some kind of MVC hierarchy here (I'm a student learning about programming 'best practices' in my own time), my question is: would 'index.php' be a view? Or, would the instance of the page class be the view (as it constructs the page, but it doesn't actually show it, it returns a string), or: would the 'page' class be a controller?
Normalmente index.php
diventa il front controller o il bootstrap.
Crei alcune cartelle: library
, controllers
, models
e views
, quindi li carichi tutti da index.php
.
Quindi crei una classe Route
nella cartella delle tue librerie, che dovrebbe essere in grado di analizzare PHP REQUEST_URI in controller class name
, method name
e array of parameters
.
Nel tuo index.php
, puoi creare un'istanza di un nuovo Route
con PHP REQUEST_URI ad esso, quindi chiami il metodo Route::build
, che dovrebbe essere in grado di instire un controller, quindi chiamare il suo metodo che corrisponde al parsed PHP REQUEST_URI . (Ulteriori informazioni su call_user_func_array ).
Il metodo del controller restituisce una stringa (da un file di visualizzazione o da qualsiasi altra cosa), quindi puoi semplicemente stamparlo sul browser.
Qui ti darò un esempio minimo di MVC in PHP:
core.php
<?php
class Route
{
protected $class;
protected $method;
protected $params = array();
/**
* Parse the given URI, if the URI is "site/article/10", then "site" will be
* the controller class, "article" will be the method, and "10" will be
* the parameter.
*/
function __construct($uri)
{
$segments = explode('/', $uri);
foreach ($segments as $segment)
{
if ($this->class === NULL)
{
$this->class = ucfirst($segment);
}
else if ($this->method === NULL)
{
$this->method = $segment;
}
else
{
$this->params[] = $segment;
}
}
}
/**
* Instantiate a controller class then execute the method with the parameters from
* the parsed REQUEST_URI.
*/
function call(Database $database)
{
$controller = new $this->class($database);
$response = call_user_func_array(array($controller, $this->method), $this->params);
return $response;
}
}
class Controller
{
function __construct(Database $database)
{
$this->database = $database;
}
/**
* Instantiate a model
*/
function model($name)
{
$model = new $name($this->database);
return $model;
}
}
class View
{
protected $data = array();
protected $path;
function __construct($path, array $data = array())
{
$this->path = $path;
$this->data = $data;
}
function render()
{
// Extract the data so you can access all the variables in
// the "data" array inside your included view files
ob_start(); extract($this->data);
try
{
include $this->path;
}
catch(\Exception $e)
{
ob_end_clean(); throw $e;
}
return ob_get_clean();
}
/**
* Make it able for you to write a code like this: echo new View("home.php")
*/
function __toString()
{
return $this->render();
}
}
class Model
{
protected $database;
function __construct(Database $database)
{
$this->database = $database;
}
}
class Database
{
function __construct()
{
// Connect to the database, for example: mysql_connect($host, $user, $pass, $data)
}
function query($sql)
{
// Do some database query like usual, for example: mysql_query($sql)
}
}
index.php:
<?php
require "core.php"
class Article extends Model
{
function find($id)
{
// You execute query through $this->db->query("SELECT..."), but i'll just use an array
// to simplify things.
return array("title" => "Article", "body" => "Lorem Ipsum");
}
}
class Site extends Controller
{
function article($id)
{
$article_model = $this->model("Article");
// This is how you use the view class!
$view = new View("article.php", array("article" => $article_model->find($id)));
return $view;
}
}
// This is where everything starts
$route = new Route("site/article/10");
echo $route->call(new Database());
article.php :
<h1><?php echo $article['title'] ?></h1>
<p><?php echo $article['body'] ?></p>
Inserisci article.php
, index.php
e core.php
in una cartella, quindi esegui index.php
dal tuo browser.