Mi rendo conto che questo argomento è stato chiesto e affrontato ripetutamente e, nonostante abbia letto innumerevoli domande simili e abbia letto innumerevoli articoli, non riesco ancora a cogliere alcuni problemi chiave. Sto cercando di costruire il mio framework MVC per scopi di apprendimento e per familiarizzare meglio con OOP. Questo è per uso privato personale, non per implicare che sia una scusa per essere pigro, ma piuttosto non sono così preoccupato di avere tutti i suoni e le campane di quadri più robusti.Comprensione/miglioramento di un framework MVC barebone
La mia struttura di directory è la seguente:
public
- index.php
private
- framework
- controllers
- models
- views
- FrontController.php
- ModelFactory.php
- Router.php
- View.php
- bootstrap.php
Ho un file .htaccess con indirizza tutte le richieste di index.php, questo file contiene le impostazioni di configurazione di base, come fuso orario e globali costanti, e poi carichi il file bootstrap.php. Il bootstrap contiene il mio autoloader per le classi, avvia la sessione, definisce le funzioni globali da utilizzare nel mio progetto e quindi chiama il router. Il router seleziona la richiesta dall'URL, la convalida tramite ReflectionClass ed esegue la richiesta nel formato example.com/controller/method/params.
Tutti i miei regolatori di estendere il FrontController.php:
<?php
namespace framework;
class FrontController
{
public $model;
public $view;
public $data = [];
function __construct()
{
$this->model = new ModelFactory();
$this->view = new View();
}
// validate user input
public function validate() {}
// determines whether or not a form is being submitted
public function formSubmit() {}
// check $_SESSION for preserved input errors
public function formError() {}
}
Questo front controller carica il ModelFactory:
<?php
namespace framework;
class ModelFactory
{
private $db = null;
private $host = 'localhost';
private $username = 'dev';
private $password = '********';
private $database = 'test';
// connect to database
public function connect() {}
// instantiate a model with an optional database connection
public function build($model, $database = false) {}
}
e base Vista:
<?php
namespace framework;
class View
{
public function load($view, array $data = [])
{
// calls sanitize method for output
// loads header, view, and footer
}
// sanitize output
public function sanitize($output) {}
// outputs a success message or list of errors
// returns an array of failed input fields
public function formStatus() {}
}
Infine, ecco un controller di esempio per dimostrare come viene elaborata una richiesta attualmente:
<?php
namespace framework\controllers;
use framework\FrontController,
framework\Router;
class IndexController extends FrontController implements InterfaceController
{
public function contact()
{
// process form if submitted
if ($this->formSubmit()) {
// validate input
$name = isset($_POST['name']) && $this->validate($_POST['name'], 'raw') ? $_POST['name'] : null;
$email = isset($_POST['email']) && $this->validate($_POST['email'], 'email') ? $_POST['email'] : null;
$comments = isset($_POST['comments']) && $this->validate($_POST['comments'], 'raw') ? $_POST['comments'] : null;
// proceed if required fields were validated
if (isset($name, $email, $comments)) {
// send message
$mail = $this->model->build('mail');
$to = WEBMASTER;
$from = $email;
$subject = $_SERVER['SERVER_NAME'] . ' - Contact Form';
$body = $comments . '<br /><br />' . "\r\n\r\n";
$body .= '-' . $name;
if ($mail->send($to, $from, $subject, $body)) {
// status update
$_SESSION['success'] = 'Your message was sent successfully.';
}
} else {
// preserve input
$_SESSION['preserve'] = $_POST;
// highlight errors
if (!isset($name)) {
$_SESSION['failed']['name'] = 'Please enter your name.';
}
if (!isset($email)) {
$_SESSION['failed']['email'] = 'Please enter a valid e-mail address.';
}
if (!isset($comments)) {
$_SESSION['failed']['comments'] = 'Please enter your comments.';
}
}
Router::redirect('contact');
}
// check for preserved input
$this->data = $this->formError();
$this->view->load('contact', $this->data);
}
}
Da quello che sono in grado di capire, la mia logica è fuori per i seguenti motivi:
- di convalida dovrebbe essere fatto nel modello, non il controller. Tuttavia, un modello non dovrebbe avere accesso alle variabili $ _POST, quindi non sono completamente sicuro se sto facendo questa parte correttamente o no? Mi sembra che questo è quello che chiamano un "controller grasso" che è male, ma non sono sicuro di cosa debba cambiare ...
- Il controller non deve inviare dati alla vista; la vista dovrebbe invece avere accesso al modello per richiedere i propri dati. Quindi spostare la proprietà
$data
da FrontController e in ModelFactory e chiamare la vista dal controller senza passare i dati risolve questo problema? Tecnicamente, quindi, aderirebbe al diagramma di flusso MVC, ma la soluzione proposta sembra un dettaglio così insignificante o addirittura banale, assumendo che sia così semplice, che probabilmente non lo è. - La parte che mi ha messo in dubbio per tutta la mia implementazione è che ho un oggetto Utente che viene istanziato con ruoli e permessi degli utenti corrispondenti, e ho cercato di capire come o più specificamente dove creare un metodo
isAllowed()
che può essere chiamato sia dal Controller che dalla Vista. Avrebbe senso quindi inserire questo metodo nel Modello, poiché sia il Controller che la Vista dovrebbero avere accesso al Modello?
In generale, sono sulla buona strada qui o quali problemi evidenti devo affrontare per andare sulla giusta strada? Sto davvero sperando in una risposta personale specifica ai miei esempi piuttosto che in un "go read this" .. Apprezzo qualsiasi feedback e aiuto sincero.
Questa domanda sembra essere off-topic perché avrebbe dovuto essere in http://codereview.stackexchange.com –