严格标准通知 View/Layout class

Strict standards notices View/Layout class

我对 php "Strict Standards" 中的 class 通知感到头疼:

Parent class:

class View {

    /**
     * 
     * @param string $viewFolder
     * @param string $viewBasename
     * @return boolean
     */
    public static function exists($viewFolder, $viewBasename){
        $exists = false;
        if(\is_string($viewFolder) && \is_string($viewBasename)){
            $exists = \is_file(\APPLICATION_PATH."View/$viewFolder/$viewBasename.phtml");
        }
        return $exists;
    }

    /**
     * 
     * @param string $viewFolder
     * @param string $viewBasename
     * @param array $viewVariables
     */
    public static function load($viewFolder, $viewBasename,array $viewVariables = []){
        extract($viewVariables);
        require \APPLICATION_PATH."View/$viewFolder/$viewBasename.phtml";
    }

}

Child class:

class Layout extends View{

    /**
     * 
     * @param string $viewBasename
     */
    public static function exists($viewBasename) {
        return parent::exists('_layout', $viewBasename);
    }

    /**
     * 
     * @param string $viewBasename
     * @param array $viewVariables
     */
    public static function load($viewBasename, array $viewVariables = array()) {
        parent::load('_layout', $viewBasename, $viewVariables);
    }

}

我读过这个主题,现在很清楚原因是 child class 方法中缺少那些参数。 Declaration of Methods should be Compatible with Parent Methods in PHP

有没有办法在不禁用错误报告的情况下摆脱这些通知,或者有更好的方法吗?

提前致谢。

更好的方法是以干净合理的方式编写您的 classes。在 OOP 实践方面,需要扩展 parent 方法的 child classes 应该以相同的格式重新定义它们(因此来自 PHP 的警告)。

在您的示例中,exists() 方法实施的一般工作流程如下所示:

  1. Parent class 有一个带有文件夹和文件名的 exists 方法
  2. Child class 偷工减料,因为它已经知道它的文件夹,只接受一个文件名
  3. Child class 将预定义变量传递给 parent 方法

如果你客观地看待这个问题,你的目标是视图应该能够在布局 class 上调用 exists() 方法并且只传递一个参数,所以你问 "how can I remove the requirement to pass the folder?" 这里有几个选项:

1: 将文件夹名称作为第二个参数传入,并使其在布局中可选 (child) class 的实现:

# Class: Layout
/**
 * @param string $viewBasename
 * @param string $viewFolder
 */
public static function exists($viewBasename, $viewFolder = '_layout') {
    return parent::exists($viewBasename, $viewFolder);
}

# Class: View
public static function exists($viewBasename, $viewFolder) {
    // essentially you swap around the order of the params
}

2:完全不传入文件夹,而是在child中使用class 属性并利用late static bindings

# Class: Layout
/**
 * Define the folder for your layouts
 * @var string
 */
const VIEW_FOLDER = '_layout';

exists() 实现与当前示例中的相同。

# Class: View
public static function exists($viewBasename) {
    // Get your folder from a child instead of an argument
    $viewFolder = static::VIEW_FOLDER;

    $exists = false;
    if(\is_string($viewFolder) && \is_string($viewBasename)){
        $exists = \is_file(\APPLICATION_PATH."View/$viewFolder/$viewBasename.phtml");
    }
    return $exists;
}

请注意,您也可以使用函数代替常量,在视图 class 中使用 abstract 或不使用,例如:

# Class: View
abstract class View {
    /**
     * This method should be defined in children to provide the layout name.
     * Using an abstract method would ensure that it is defined by children,
     * however if View is going to be used on its own then do not use this approach.
     * @return string The view's folder name
     */
    abstract protected static function getViewFolder();

    public static function exists($viewBasename) {
        // Get view folder from the children (same as the constant example)
        $viewFolder = static::getViewFolder();
        // ...
    }
}

# Class: Layout
class Layout extends View {
    protected static function getViewFolder() {
        return '_layout';
    }
    public static function exists($viewBasename) {
        return parent::exists($viewBasename);
    }
}

老实说,constant 选项有点短,它们基本上做同样的事情,除了如果你使用函数而不是常量,你可以根据需要定义操作逻辑。


如果我是你,我会为视图文件夹使用一个 class 常量并将其作为参数取出。然后,您将实现 static::VIEW_FOLDER 来代替传递给 loadexists.

的参数