Php 错误-它们属于逻辑层还是表示层?

Php 错误-它们属于逻辑层还是表示层?,php,error-handling,separation-of-concerns,Php,Error Handling,Separation Of Concerns,关于函数调用,最好让调用方负责检查函数是否工作或失败,还是由函数本身宣布错误? 我问这个问题的原因是因为我不喜欢把陈述和逻辑混为一谈,但是如果调用者必须进行错误检查,它可能是不准确和麻烦的,例如 if(!login($username, $password) { echo 'Login failed. Please try again.'; } 调用方不知道失败的原因。是用户名/密码组合错误,还是数据库连接失败?还是其他意想不到的原因 如果我们可以在函数内部进行错误检查/抛出异常,这将

关于函数调用,最好让调用方负责检查函数是否工作或失败,还是由函数本身宣布错误?

我问这个问题的原因是因为我不喜欢把陈述和逻辑混为一谈,但是如果调用者必须进行错误检查,它可能是不准确和麻烦的,例如

if(!login($username, $password)
{
    echo 'Login failed. Please try again.';
}
调用方不知道失败的原因。是用户名/密码组合错误,还是数据库连接失败?还是其他意想不到的原因

如果我们可以在函数内部进行错误检查/抛出异常,这将不会是一个问题,因为在特定的代码点(例如数据库连接失败)会出现特定的错误……但这将是表示和逻辑的混合。这里的最佳实践是什么


谢谢。第一个。调用方应负责错误检查。 如果您想知道发生了什么样的错误,可以重写登录函数并添加第三个参数,该参数将保存对错误的引用,如下所示:

<?php
function login($user, $pass, &$error) {
    // if user or pass wrong
    $error = 'Username / pass wrong';

    // if db failed
    $error = 'unable to connect to db'
};

if(!login($user, $pass, $error)) {
    // do whatever you want with the error
}

我个人会通过在业务逻辑(模型)层抛出异常来赋予调用方责任。然后,可以在控制器中捕获异常(并在视图中为错误分配一个变量)。有些人甚至喜欢直接在表示层捕获异常,但这在web开发中并不适用。只要该异常仅用于视图中的演示目的,我不认为这是一个很大的问题。

因此,我不会像您在简单示例中所做的那样,因为调用方可能并不总是希望显示错误。通过处理对来电者的责任,他或她可以选择。此外,我不喜欢在业务逻辑中重复内容(我更喜欢抛出异常并保持模型清晰无误地显示),但您的代码很可能只是一个过于简单的示例

编辑:您可以执行以下操作:

<?php
function login($user, $pass, &$error) {
    // if user or pass wrong
    $error = 'Username / pass wrong';

    // if db failed
    $error = 'unable to connect to db'
};

if(!login($user, $pass, $error)) {
    // do whatever you want with the error
}
型号:

function login($username, $password) {
    if (login failed) {
        throw new Login_Exception();
    }

    else {
        // Set session
        return true;
    }
}
控制器:

try {
    $model->login($username, $password);
}

catch (Login_Exception $e) {
    $view->loginError = 'There was an error logging in.';
}

然后,您可以抛出不同的异常,以准确地指出出错的原因(例如,
错误的\u用户名\u异常
),并相应地进行处理。或者,您甚至可以在异常的构造函数中提供一个用户友好的原因,但在我看来,这会使表示和逻辑耦合得太多。

示例代码的问题是:

if(!login($username, $password)
{
    echo 'Login failed. Please try again.';
}
。。。就是login()函数没有返回足够的信息供调用方使用。无论调用方是Web表示层还是其他层,这都是一个问题

更好的login()函数可能会返回一个对象,以便调用者可以执行以下操作:

$response = login($username, $password);
if(! $response->isLoggedIn()) {
    echo "Login failed. " +  $response->getErrorMessage();
}
现在,您的登录方法没有与用户界面紧密耦合,但是您可以将登录失败的原因传递给用户


现在,可以说login()方法中仍然有“presentation”,因为它返回的文本被逐字引用给用户。如果您想要更松散地耦合,您可以定义一个错误代码列表,并让您的表示层将这些代码转换为消息。也可以返回指向消息表的值。了解国际化;这是相同的基本域。

但考虑到错误消息在函数中,这不是仍然是表示和逻辑的混合吗?如果有人想修改错误消息是什么,他们必须检查实际的代码。我喜欢你关于使用常量的建议,最好将它们放在一个配置文件中,这样用户就可以在一个单独的文件中定义每个场景的错误消息应该是什么样子,这比进入函数逻辑要简单得多。如果你使用错误代码,那么你就解决了表示问题身份验证失败实际上不是一个“错误”接收不正确的登录名/密码是程序正常运行过程中的常见情况。如果密码匹配,函数应该返回true,否则返回false。@cleong在本例中,是的,但我认为这只是一个普通问题的示例。他询问的是函数/过程,而不是oop@VladBalmos你是对的,他没有明确提到OOP。我只是假设OOP与层有关。但是,即使没有控制器/模型类,也可以使用这样的异常。是的,您也可以在php中混合使用异常处理和过程代码。但是有点不一致,我看不出问题所在。异常和OOP是正交的。