【问题标题】:PHP MVC dialog validation flow - how to go from view´s form to controller without loosing the contextPHP MVC 对话框验证流程 - 如何在不丢失上下文的情况下从视图表单转到控制器
【发布时间】:2015-08-06 04:05:28
【问题描述】:

我正在构建一个基于 PHP MVC 的应用程序。我过去曾使用过 MVC 并且了解这些概念,尽管 PHP 对我来说是新事物。

我正在关注this tutorial here 来构建我的项目,并进行一些更改以反映我的需要...

我面临一个问题,即我从 form 提交回原始控制器的方式,保留上下文。 (我的低 PHP 技能可能解释了这种误解......)

让我们去代码:

这是我的 index.php(客户端每次调用的入口点):

if (isset($_GET['controller']) && isset($_GET['action']))
{
    $controller = $_GET['controller'];
    $action = $_GET['action'];
}
else 
{
    $controller = 'Root';
    $action = 'home';
}

require_once('/view/layout.php');

layout.php:

<!DOCTYPE html>
<html lang="en-us">


<?php require_once("library/view/header.php"); ?> // Load header

<body>
        <?php 
            require_once("library/controller/routes.php"); // Route controller/action

            require_once("library/view/footer.php"); // Load footer
        ?>
</body>

routes.php:(将路径路由到正确的控制器和动作)

    function call($controller, $action)
    {
        $filename = 'controller/class.' . $controller . 'Controller.php';

        if (!file_exists($filename))
        {
            $errorMsg = "ERROR: File not found: " . $filename . " for Controller:" . $controller . " and Action:" . $action;
            throw new Exception($errorMsg);
        }

        require_once ($filename);

        switch ($controller)
        {
            case 'Root':
                $controllerObj = new RootController();
                break;
        }

        $controllerObj->{ $action }();
    }

    call ($controller, $action);

class.RootController.php: - Root 的控制器。

public function home () 
{
    if (session_status() == PHP_SESSION_NONE)
        require_once('library/view/root/login.php');
    else
        require_once('library/view/root/home.php');
}

public function authenticate ($username, $password) 
{
    $username = trim($_POST["username"]);
    $password = trim($_POST["password"]);

    // Authenticate logic
    if ($auth == true)
    {
        ==> Go to a different controller/view.
    }
    else
    {
       $errorMsg = "Problems authenticating.";
       return $errorMsg;
     }
}

public function error($controller, $action, $errorMessage)
{
    echo "Error in " . $controller  . ' Action" . $action;
    echo $errorMessge;
}

最后是登录视图(login.php):

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
    <label>Username:</label> 
    <br> 
    <input type="text" name="username" value="<?php echo $username;?>"> <br> <br> <label>Password:</label>

    <br> 
    <input type="password" name="password"> 

    <br> <br> 

    <input type="submit" name="submit" value="Submit"> 

    <br> <br> 

    <span style="color: red"><?php echo $errorMsg;?>&nbsp</span>
</form>

我的问题是:

这样,当我单击提交按钮时,它会重定向到索引页面,但没有 $controller$action 上下文。所以没有办法路由到RootController()上的authenticate函数;

所以,这是我的问题:

  1. 如何检查输入的数据,出错时返回错误信息或成功时更改Controller和Action?

  2. 每次数据验证都需要通过index.php 吗?

  3. 是否可以直接从已经加载的RootController()中的formauthenticate函数,失败时返回错误信息?

  4. 有没有更好的方法来做这个表单验证?

我很确定我在这里遗漏了一些非常基本的东西,但我不知道什么是......

非常感谢您的帮助和帮助。

【问题讨论】:

  • header('Location: ... ); 或许。

标签: php forms model-view-controller


【解决方案1】:

首先,制作自己的 MVC 非常棒,它是学习编码的好方法。我计划有一天自己动手。

回答这些问题

1) 如何检查输入的数据,出错时返回错误信息或成功时更改Controller和Action?

这是使用标头完成的,这与您设置内容类型的标头相同,例如 ajax、html 或您所拥有的,即响应标头。这里重要的是你不能在输出后调用头部位置,任何输出甚至是空格。

 header('Location: www.yoursite.com/success?m=you failed!');
 ext;

此处的退出是必不可少的,因为您正在重定向,但页面的脚本将继续运行,通常会带来不幸的后果。

2) 每次数据验证都需要通过 index.php 吗?

这不是 MVC 框架的重点吗?它被称为前端控制器或入口点。

3) 是否可以直接从表单到已经加载的RootController()中的authenticate函数,失败时返回错误信息?

使用 AJAX 可以接近,但这值得怀疑,因为需要进行用户输入,因此无法发出另一个请求。抱歉,这就是它的工作方式。

4) 有没有更好的方法来做这个表单验证?

请参阅第 2 点。您可以弹出一个登录弹出窗口,但这应该是标准登录表单的补充。

通常它的工作方式是您将拥有一个用于登录的控制器

 www.yoursite.com/index.php/login  ( you can hide the index.php with mod rewrite )

然后在您的$_SERVER 超级全局中,您将找到请求 uri 或类似内容,其中将包含 uri(uri 是想象的,而不是真实的页面)。这通过 index.php 到路由器到控制器进行登录。显示页面。然后你的控制器中有另一个方法提交登录..等等。提交表单时运行,然后在处理后使用标题将它们定向到另一个虚构的资源。与登录有关的事情是在某处检查路径并存储他们想要的页面,当您将它们发送到登录页面时。

比如我想去这个页面

 www.yoursite.com/index.php/members

但是我没有登录所以我去这里

www.yoursite.com/index.php/login?r={www.yoursite.com/index.php/} // urlencode between the { }

然后在成功时,不要给他们一个罐头消息,而是给他们他们想要的页面,或者某种仪表板。如果他们失败了,把他们带回来/或者更好,但把他们留在登录页面上,并附上适当的消息。

我应该注意,通常路由器和 uri 会以这种方式设置,

 {domain}/index.php/{controller class}/{controller method}/ ...additional input.

所以为了可扩展性,你会想要这样的东西,

 www.yoursite.com/index.php/members/login

通过一些基本的 mod 重写,你可以做到这一点

www.yoursite.com/members/login

使用请求的 uri 部分很重要,因为它就像一种额外的方式来保留上下文,而不使用 $_POST 或 $_GET 方法。

【讨论】:

  • 标题会进入视图还是控制器?在我的情况下,标题会是什么样子?
  • 在我看来,视图中只有 html (当然使用模板语言)。但没有业务逻辑,只有显示逻辑。因此重定向将成为控制器的一部分,它控制请求的流程。服务器上的任何调用都是请求,然后服务器提供响应。真的很简单,把他们留在登录页面,或者把他们送到他们想去的地方。看看var_export( $_SERVER)里面有一堆你需要的东西。
  • 非常好的解释..我明白了,现在正在学习如何实现 - 自己动手...谢谢您的帮助...
【解决方案2】:

我在这里看到的一个问题是,当您还不知道需要什么样的输出时,您正在从前端控制器 (index.php) 调用 layout.php。例如,您应该重定向用户吗?使用 JSON 响应 AJAX 请求?如果您已经发送了 HTML,则无法执行任何这些操作。

如果可以,请查看PHP mini。这是一个在 PHP 中使用 MVC 的非常简单的框架,但它为您提供了一个可以工作甚至改进的坚实基础。它甚至与您当前的实现有一些相似之处,但有很多事情已经完成,您不必从头开始编写。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    相关资源
    最近更新 更多