我意识到这个话题已经被反复询问和解决,尽管我已经阅读了无数类似的问题并阅读了无数文章,但我仍然无法抓住一些关键问题......我正在尝试构建自己的 MVC用于学习目的和更好地熟悉 OOP 的框架。这是供个人私人使用的,并不是暗示这是懒惰的借口,而是我不太关心拥有更强大框架的所有花里胡哨。
我的目录结构如下:
public
- index.php
private
- framework
- controllers
- models
- views
- FrontController.php
- ModelFactory.php
- Router.php
- View.php
- bootstrap.php
我有一个 .htaccess 文件,其中将所有请求定向到 index.php,该文件包含基本配置设置,例如时区和全局常量,然后加载 bootstrap.php 文件。引导程序包含我的类自动加载器,启动会话,定义要在整个项目中使用的全局函数,然后调用路由器。路由器从 URL 中挑选出请求,使用 ReflectionClass 对其进行验证,并以 example.com/controller/method/params 的形式执行请求。
我所有的控制器都扩展了 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() {}
}
这个前端控制器加载 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) {}
}
和基础视图:
<?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() {}
}
最后,这是一个示例控制器来演示当前如何处理请求:
<?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);
}
}
据我所知,我的逻辑是错误的,原因如下:
- 验证应该在模型中完成,而不是在控制器中。但是,模型不应该访问 $_POST 变量,所以我不完全确定我是否正确地完成了这部分?我觉得这就是他们所说的“胖控制器”,这很糟糕,但我不确定需要改变什么......
- 控制器不应向视图发送数据;相反,视图应该有权访问模型来请求自己的数据。那么将
$data
属性从 FrontController 移到 ModelFactory 中,然后在不传递数据的情况下从 Controller 调用 View 可以解决这个问题吗?从技术上讲,它会遵循 MVC 流程图,但所提议的解决方案似乎是一个微不足道甚至微不足道的细节,假设它很简单,它可能不是...... - 让我质疑我的整个实现的部分是我有一个用户对象,该对象是用用户相应的角色和权限实例化的,我一直在试图弄清楚如何或更具体地在哪里创建一个
isAllowed()
可以调用的方法控制器和视图。那么将这个方法放在模型中是否有意义,因为控制器和视图都应该可以访问模型?
总体而言,我是否走在正确的轨道上,或者我需要解决哪些明显的问题才能走上正确的轨道?我真的希望针对我的示例做出个人回应,而不是“去阅读这个”。我感谢任何诚实的反馈和帮助。