如何在 PHP MVC 框架中实现控制器操作?
我正在尝试用 PHP 创建自己的 MVC 框架来了解它们,但我目前在实现控制器的操作时遇到困难。
问题在于,某些控制器有一个或多个参数,例如 actionView($id),而其他控制器则没有参数,例如 actionCreate()。我如何以不同的方式处理这些?
例如:
$action; //contains my action
$params; //array containing my arguments
在我的控制器中,我会调用...
$this->$action(); //for no parameters
$this->$action($params[0]); //for one parameter
$this->$action($params[0], $params[1]); //for two parameters
... and so on
处理这样的所有可能情况是不可行的。也许我实施的行动是错误的。有人可以引导我走向正确的方向吗?
编辑:MVC 框架如何使处理多个参数成为可能?
I'm trying to create my own MVC framework in PHP to learn about them but I'm currently having trouble implementing the action of the controller.
The problem is that some controllers have one or multiple arguments such as actionView($id), while others have no arguments like actionCreate(). How do I handle these differently?
For example:
$action; //contains my action
$params; //array containing my arguments
In my controller I would call...
$this->$action(); //for no parameters
$this->$action($params[0]); //for one parameter
$this->$action($params[0], $params[1]); //for two parameters
... and so on
It wouldn't be feasible to handle every possible situation like this. Perhaps I am implementing the actions wrong. Can someone guide me in the right direction?
EDIT: How do the MVC frameworks out there make handling multiple arguments possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我只是将参数数组作为每个操作的唯一参数传递。让我们知道您的框架的约定包括以这种方式将参数传递给操作。这允许实现代码选择他们想要如何处理它;可能使用
func_get_args()
或在方法签名中提供参数:需要注意的事项但问题是,尽管您的操作可能需要参数,但用户实际上可能不会提供参数。如果您的方法签名设置为要求传递一个值,并且您没有足够的值来插入,那么您可能会收到各种错误。这是我选择简单地传递参数数组并始终传递数组的部分原因,即使它是空的。
或者,部分影响 BrNathanH 答案,您可以以某种方式将对象绑定到给定的操作,然后将该数组注入到对象的构造函数中。该对象可以负责提供操作所需的数据并提供适当的默认值/检查值是否存在。如果您想双重确保他们正在获取适当的数据,那么您可以将对象签名添加到您的操作中。我不确定您将如何在自己的代码中实现这一点,主要问题是将controller::action 映射到适当的“ParamObject”。但是将数组包装成对象可能是一个好主意,并且可以解决不知道要传递多少参数的问题。它始终是一个,即与该操作关联的“ParamObject”。
I would simply pass the array of arguments as the only argument to every action. Let it be known that your framework's convention includes passing arguments to actions in this way. This allows the implementing code to choose how they want to deal with it; use
func_get_args()
maybe or provide a paramater in the method signature:Something to be wary of though is that although your action may require a parameter the user may not actually provide one. If your method signature is setup to require a value be passed and you don't have enough values to plug in then you may get all kinds of errors. This is part of the reason I would choose to simply pass in the array of parameters and always pass an array, even if it is empty.
Alternatively, partly influence off of BrNathanH answer, you could somehow tie an object to a given action and then inject that array into the object's constructor. That object can be responsible for providing the data needed for the action and giving suitable defaults/checking for the values to exist. You could then just add an object signature to your actions, if you wanted to be doubly sure that they are getting the appropriate data. I'm not sure exactly how you would implement this in your own code, the primary problem being the mapping of controller::action to the appropriate "ParamObject". But wrapping the array into objects might be a good idea and would solve the problem of not knowing how many parameters to pass. It's always one, the "ParamObject" associated with that action.
我知道如何解释这一点的最好方法是使用示例,因此这里是我自己的 PHP-MVC 应用程序实现的示例。请务必密切注意
Hook::run
函数,该函数处理加载控件的参数。index.php:
system/home.php:
.htaccess:
通过这个 htaccess 文件,我们可以使用 localhost/home/main 加载 home.php 控件。如果没有它,我们的网址将类似于
localhost/index?args=home/main
。演示截图1(localhost/simple_mvc/home/main/args1/args2/args3):
您并不总是知道特定控制方法需要多少个参数,这就是我相信的原因最好传递一个由斜杠分隔的参数。如果控制方法需要多个参数,则可以使用提供的
Hook::param
函数进一步评估。演示截图2(localhost/simple_mvc/home/other/args1/args2/args3):
回答您的问题:
这里真正有助于回答您的问题的关键文件是
.htaccess
文件,它透明地将localhost/这些/types/of/urls
转换为类似localhost /index.php?args=这些/types/of/urls
。然后,您可以使用explode($_GET['args'], '/');
拆分参数。关于此主题的精彩视频教程位于此处。这确实有助于解释很多事情。
我使用最新的编辑内容对 home.php 和 index.php 进行了一些更改
The best way I know how to explain this is with examples, so here is an example of my own implementation for a PHP-MVC application. Make sure to pay close attention to the
Hook::run
function, which handles the arguments for loading the control.index.php:
system/home.php:
.htaccess:
With this htaccess file, we are able to load the home.php control using
localhost/home/main
. Without it, our urls would look likelocalhost/index?args=home/main
.Demonstration screenshot 1 (localhost/simple_mvc/home/main/args1/args2/args3):
You don't always know how many arguments an particular control method is going to expect, which is why I believe it is best to pass a single argument delimited by slashes. If the control method expects more than one argument, you can then use the provided
Hook::param
function to further evaluate.Demonstration screenshot 2 (localhost/simple_mvc/home/other/args1/args2/args3):
To answer your question:
The key file here that really helps to answer your question is the
.htaccess
file, which transparently turnslocalhost/these/types/of/urls
into something likelocalhost/index.php?args=these/types/of/urls
. That then allows you to split the arguments usingexplode($_GET['args'], '/');
.A GREAT video tutorial on this subject is here. It really helps to explain a lot.
I've made some changes to home.php and index.php with the latest edit
你可以只传递整个数组。问题是每个控制器都必须进行错误检查以查看是否存在正确的值。另一种解决方案是创建一个保存参数的数据对象。您拥有控制器访问权限(它会为您进行所有错误检查)。
You could just pass the whole array. The problem is that each controller has to do error checking to see if the correct values are there. Another solution would be to create a data object that holds the parameters. You have the controller access that (which does all the error checking for you).
对于参数,您始终可以将某些参数设置为可选。像这样:
这意味着
$argument
和$argument2
是可选的。如果在调用函数时设置了这些参数...这些参数将具有值。不过,对于某些函数来说,传递
array()
(然后使用isset()
检查设置的数组键或项)会更容易。For arguments, you can always set some arguments to be optional. Like this:
This means that
$argument
and$argument2
are optional. If those arguments are set when the function is called... those arguments will have values.Although, passing an
array()
(and then usingisset()
to check for set array keys or items,) would be easier for some functions.