PHP - 使用MVC构建一个Slim3 Web应用程序,并了解了该模型的作用

问题描述 投票:1回答:2

我试图用树枝模板系统沿着Slim3框架PHP创建的认证系统,并为数据库我使用MySQL与PDO。我也试图使用模型视图控制器设计模式来实现它。但是我有困难,了解如何使用MVC结构的Web应用程序。我看网络上的解释过多和似乎没有成为一个明确的答案。很多人说要使用PHP框架,如Laravel,Symfony的或笨,因为他们显然是采用了MVC结构。但是我宁愿让事情变得简单,并编写代码手动而不是使用的框架。

目前,有MVC的两种解释,我看到。第一个在该图中所描绘的被:

enter image description here

我见过的其他解释是这样的:(从this YouTube video拍摄)

enter image description here

我已经做了我的研究。问题和答案,如thisthis是有帮助的。但我仍然不知道我怎么可能构建自己的应用,特别是蔡作馨和理解MVC模型方面。现在我来解释我的身份验证的应用程序的注册过程。所以,你有一个想法,我的代码是如何工作。

首先我有仅仅把一系列的SQL语句到功能的SQLQueries类。然后我有了可以例如存储在数据库中一个新用户的详细信息功能的SQLWrapper类。这个类还要求从SQLQueries类的功能。我也有具有清洁的用户输入以及检查是否用户输入是在形式有效功能的ValidateSanitize类。这三个班,我认为是MVC模型方面的一部分,但我不知道。我看到很多使用“用户模型类的其他教程,但我无法找到一个在我的应用程序的需要。

我的观点是仅仅是显示HTML嫩枝模板,如网页,注册,登录等,然后我有控制器。我打算有多个控制器,做不同的事情。现在我只实施了AuthController负责注册和登入的用户。

所以AuthController做的第一件事是要显示在一个名为getRegisterForm功能寄存器形式。一旦用户提交表单的postRegisterForm函数接受用户的输入,并将其分配给被感染的变量。

public function postRegisterForm($request, $response)  
{
   $arr_tainted_params = $request->getParsedBody(); 

   $tainted_email = $arr_tainted_params['email'];  it a variable
   $tainted_username = $arr_tainted_params['username'];
   $tainted_password = $arr_tainted_params['password'];
   $tainted_password_confirm = $arr_tainted_params['password_confirm'];

接着前面三个类的所有以及数据库的细节被实例化因此其功能可以在AuthController使用:

$sanitizer_validator = $this->container->ValidateSanitize;
$sql_wrapper = $this->container->SQLWrapper;
$sql_queries = $this->container->SQLQueries;
$db_handle = $this->container->get('dbase');

被感染的用户详细信息,然后与sanitize_input功能清洗。清洁的用户详细信息,然后送入验证功能,以确保他们不会触发任何验证违规。该密码也是在这里散列:

$cleaned_email = $sanitizer_validator->sanitize_input($tainted_email, FILTER_SANITIZE_EMAIL); 
$cleaned_username = $sanitizer_validator->sanitize_input($tainted_username, FILTER_SANITIZE_STRING);
$cleaned_password = $sanitizer_validator->sanitize_input($tainted_password, FILTER_SANITIZE_STRING);
$cleaned_password_confirm = $sanitizer_validator->sanitize_input($tainted_password_confirm, FILTER_SANITIZE_STRING);

$hashed_cleaned_password = password_hash($cleaned_password, PASSWORD_DEFAULT); 

$sanitizer_validator->check_email_exists($cleaned_email);
$sanitizer_validator->validate_email($cleaned_email);
$sanitizer_validator->validate_username($cleaned_username);
$sanitizer_validator->validate_password($cleaned_password);
$sanitizer_validator→validate_password_confirm($cleaned_password_confirm);

最后,有一个if语句来检查,看看是否所有验证错误消息是空的。如果他们是我们提供的SQLWrapper类与数据库的详细信息,以及一个SQLQueries类对象。然后,我们通过调用SQLWrapper类商店的细节功能,插入用户的详细信息到数据库中。最后,我们将用户引导到登录页面,这样用户就可以登录到自己新注册的账号。

if ($sanitizer_validator->get_validate_messages('email_error') == ' ' && $sanitizer_validator->get_validate_messages('username_error') == ' '
    && $sanitizer_validator->get_validate_messages('password_error') == ' ' && $sanitizer_validator->check_passwords_match($cleaned_password, $cleaned_password_confirm ) == true
    && $sanitizer_validator->check_email_exists($cleaned_email) == false)
{   

    $sql_wrapper->set_db_handle($db_handle); 
    $sql_wrapper->set_sql_queries($sql_queries); 

     $sql_wrapper->store_details($cleaned_email, $cleaned_username, $hashed_cleaned_password);
     return $response→withRedirect($this→container→router→pathFor('login'));

}

但是,如果任何验证错误消息不为空,那么我们呼吁寄存器树枝模板要显示的SanitiseValidate display_validate_messages这只是设置的消息到会话。然后,我们重定向回注册页面,使用户可以看到验证错误消息。

else
  {
      $sanitizer_validator->display_validate_messages();
      return $response->withRedirect($this->container->router->pathFor('register'));
  }
}

因此,基于注册一个帐户的用户的这种结构。这是否坚持一个干净简单的MVC结构还是需要作出一些改变?做任何我的班采取示范的作用?所有关于我的结构建议和提示将不胜感激。

full application can be seen on my GitHub如果这将是有益的。请注意,这个版本比我在这个问题上使用的样例代码稍微大一点。

php model-view-controller design-patterns model slim-3
2个回答
5
投票

事实上,有关于如何MVC模式应在Web应用程序可以应用多种方法。变种这是大量的简单事实的结果,原来的MVC模式 - 桌面应用程序开发(由特里夫·林斯卡格,1979年) - 为的是Web应用程序无法使用。 Here是一个小的说明。但是,从这套方法,你可以选择一个最符合你的要求符合。也许你会尝试更多的人面前,你会让你的头脑。虽然,在某些时候,你就会知道哪一个适合于你的视野。

在下图中我试图把在网络上MVC工作流程我选择的方法 - 主要是启发Robert Martin的演讲Keynote: Architecture the Lost Years(一Creative Commons Attribution ShareAlike 3.0下许可)。


enter image description here


enter image description here


enter image description here


在一般情况下,你能想象的那样由以下几个部分的Web MVC应用程序的:

  1. 域模型(例如模型,例如模型层);
  2. 服务层(可选);
  3. 交付机制;
  4. 其他组件(如自己的库等)。

1)域模型应包括以下几个部分组成:

  • 实体(例如域对象)和值对象。他们的属性和行为,是独立于应用程序方面的业务规则进行建模,可以由多个使用(类型的)应用程序。
  • (Data) mappers和,可选的,repositories。这些组件负责与持久性逻辑。
  • 外部服务。它们被用来执行涉及使用外部/自定义的库(如发送电子邮件,解析文件等)不同的任务。

另外,领域模型可以分为两个部分:

一)领域模型的抽象。这将是通过该交接机构的组成部分访问的模型层的唯一空间,或由服务层的服务 - 如果一个实现:

  • 实体和值对象;
  • (数据)映射器的抽象和,可选的,储存库抽象;
  • 外部服务的抽象。 注意:抽象我的意思是接口和抽象类。

B)的领域模型实现。该空间将是其中不同的域模型抽象(见A)的实施方式将驻留在一个。依赖注入容器(作为递送机制的一部分)将负责与通过这些混凝土类的实例作为依赖 - 作为构造参数,例如 - 到应用程序的其它部件(如控制器,视图,服务等)。

2)服务层(可选):从技术上讲,输送机构的部件可以直接与域模型中的元素相互作用。虽然这种相互作用涉及(很多)操作,只有特定的模式,而不是交付机制。因此,最好是把这些操作服务类(如服务)的执行推迟作为所谓service layer的一部分。然后递送机制组件将只使用这些服务来访问域模型组件。

注意:服务层,实际上,被看作是模型层的一部分。在我的图娄我优选以将其显示为驻留在模型之外的层。但是,在文件系统中的例子,我把相应的文件夹中的域空间。

3)递送机制总结了用于确保用户和模型层的组件之间的交互的构建体。通过用户我并不是指一个人,而是与一个人交互的界面 - 就像一个浏览器,控制台(例如CLI),桌面图形用户界面等。

  • Web服务器:通过解析条目(的index.php)的单点用户请求。
  • 依赖注入容器:提供适当的依赖关系的应用的不同的组件。
  • HTTP消息(例如HTTP请求和HTTP响应)抽象(见PSR-7: HTTP message interfaces)。
  • 路由器:匹配针对路线的预定义列表中的每个路径(HTTP方法和图案)的各组件的请求组件(HTTP方法和URI路径),并返回匹配的路由,如果找到。
  • 前端控制器:匹配针对路线的用户请求,并且将分派到一定控制器和/或视图的动作。
  • 控制器。他们写(例如执行创建,更新和删除操作)的模型层(应该)预期没有结果。这可以通过在域模型,或,优选地定义的组件直接交互,通过仅与服务类相互作用发生。
  • 视图。他们应该是类,而不是模板文件。他们可以得到一个模板引擎的依赖。它们只从模型层中获取数据(例如,执行读取操作)。要么在领域模型中定义的部件通过直接相互作用,或优选地,通过只与服务类交互。此外,他们决定哪种结果(如字符串),或模板文件的内容,将被显示给用户。视图动作应该总是返回一个HTTP响应对象(可能如由PSR-7规范中定义),其主体将前手与提到的结果或模板文件的内容进行更新。
  • 模板文件。应尽可能保持简单。整个演示文稿逻辑应该在视图情况下才会发生。因此,模板文件应该只包含变量(不论是纯PHP的,或与所使用的模板引擎的语法提出)和,也许,一些简单的条件语句,或循环。
  • 响应发射器:读出由视图并将其打印返回的HTTP响应实例的主体。

4)其它部件。正如所愿。例如,通过自己开发的一些库。像PSR-7抽象的实现。


我该如何选择派遣用户请求:

正如在上面的图中看到,前端控制器分派用户请求不仅给控制器动作(为了更新域模型),也给一个视图动作(以读取和显示从所述更新的状态/数据模型层)。一个分裂调度类。这可以相对容易地通过分配控制器动作和视图动作到每个路由(如波纹管),以及告知前端控制器连续地调用它们来实现的:

<?php

use MyApp\UI\Web\Application\View;
use MyApp\UI\Web\Application\Controller;

// Note: $this specifies a RouteCollection to which the route is added. 
$this->post('/upload', [
    'controller' => [Controller\Upload::class, 'uploadFiles'],
    'view' => [View\Upload::class, 'uploadFiles'],
]);

这种方法提供了灵活性在考虑到用户请求调度。例如,视图操作的名称可以是从控制器操作的名称不同。或者,为了仅提取模型层的数据,你不需要派遣用户请求到控制器,而只是一个视图。所以你并不需要在所有分配在路由控制器动作:

<?php

use MyApp\UI\Web\Application\View;

$this->get('/upload', [View\Upload::class, 'listFiles']);

文件系统结构示例:

enter image description here

MYAPP /域:包含域模型类和服务文件夹。这个目录可以成为“MYAPP /网络/ src目录”文件夹,但它不应该,因为模型层和服务层都没有交付机制的一部分。

domain folder

的myapp /卷筒纸:包含递送机制的类文件夹。它的名字描述应用程序的类型 - 可以是一个Web应用程序,一个CLI应用程序,等等。

web folder

MYAPP /网络/ src目录:

web-src folder


资源:

鸡舍我的一个older answer上市。

亚历杭德罗·杰瓦西奥提供的教程:

斯利姆3页的示例:Action-Domain-Responder with Slim


0
投票

有你在哪里得到通过制定MVC与纤薄3.不适链接在这里走了一门课程:https://codecourse.com/courses/slim-3-authentication。希望这有助于,它的一个非常简单的跟随当然,你学到了很多东西。

© www.soinside.com 2019 - 2024. All rights reserved.