How to return false from a PHP script from inside a class/function?

时间:2015-10-30 23:54:44

标签: php

How can I make the main PHP script return false from inside a class or a function? Why: this is because of the built-in webserver: If a PHP file is given on the command line when the web server is started it is treated as a "router" script. The script is run at the start of each HTTP request. If this script returns FALSE, then the requested resource is returned as-is. from the documentation about the PHP Built-in webserver In other words, you return false in your router script so that the built-in webserver can serve static files. Example from the documentation: if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) { return false; // serve the requested resource as-is. } else { echo "<p>Welcome</p>"; } The thing is that I'm trying to add that behavior to a web framework: I don't want to write that into index.php. I'd rather encapsulate that logic into a class (middleware) that will halt the script's execution if php_sapi_name() == 'cli-server' and a static asset is asked. However, I don't know how I can make the whole PHP script return false from a class or a function, since obviously return false will return from the current method/function/file and not from the main file. Is there a way to achieve the same behavior with exit() for example? I realize I don't even know what return false in the main file actually means (is that a specific exit code?).

3 个答案:

答案 0 :(得分:6)

You should have the router invoke the class method, and then, if the method returns false, you return false from your router file. Of course it can turn into a headache. There are basically only two methods to achieve what you want to achieve. There is a faster way though, you can abuse exceptions and create a specialized exception for the case: StaticFileException.php <?php class StaticFileException extends Exception {} router.php <?php try { $c = new Controller(); return $c->handleRequest(); } catch (StaticFileException $e) { return false; } Once you have this kind of code in place, just throw new StaticFileException and you're done.

答案 1 :(得分:4)

如果您的类中的方法使用exit处理静态资产,那么解决方案就像将exit替换为return false一样简单,并让该方法的调用者只返回方法在全球范围内。

所以如果你的班级看起来像这样......

class Router
{
    public function handleRequest($uri)
    {
        if (is_file($this->docRoot . $uri->path)) {
            exit; // static file found
        } else {
            // handle as normal route
        }
    }
}

只需将exit替换为return false ...

            return false; // static file found

然后,如果你的index.php有类似的功能......

$router = new Router($docRoot);
$router->handleRequest($_SERVER['REQUEST_URI']);

只需添加handleRequest方法的返回面前,就像这样......

return $router->handleRequest($_SERVER['REQUEST_URI']);

这应该对您的框架设计产生最小的副作用,因为您可以看到只需要很少的代码和重构,因为从脚本的全局作用域返回只在PHP中有一个副作用(因为它返回调用脚本的值,即如果您使用include / require作为赋值中的表达式)。在您的情况下,如果index.php是调用脚本,那么您只需在该方法的前面添加return就无需担心。

当然,一旦返回,脚本的其余部分将不会继续,因此请确保它是index.php中的最后一个语句。您甚至可以将返回值分配给临时值,如果需要逻辑,则可以稍后返回....

$router = new Router($docRoot);
if ($router->handleRequest($_SERVER['REQUEST_URI'])) {
    /* if you need to do anything else here ... */
} else {
    return false; // otherwise you can return false for static here
}

一般来说,我会说从函数/方法内部调用exit几乎永远不会。它使您的类更难以测试和调试,并且实际上没有其他选择,例如抛出异常,或者只是从方法返回,并让调用者处理失败场景优雅

答案 2 :(得分:0)

无法使用register_shutdown_function或auto_append_file设置来处理吗?不太好,但也许可以做到这一点。