严格的标准注意View/Layout类


Strict standards notices View/Layout class

我很头疼php类中的"严格标准"通知:

父类:

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";
    }
}

儿童班:

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);
    }
}

我读过这个主题,现在很清楚原因是子类方法中缺少参数。方法声明应与PHP 中的父方法兼容

有没有一种方法可以在不禁用错误报告的情况下消除这些通知,或者有更好的方法?

提前谢谢。

更好的方法是以干净合理的方式编写类。就OOP实践而言,需要扩展父方法的子类应该以相同的格式重新定义它们(因此PHP发出了警告)。

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

  1. 父类有一个带有文件夹和文件名的exists方法
  2. 子类偷工减料,因为它已经知道自己的文件夹,并且只接受文件名
  3. 子类将预定义的变量传递给父方法

如果你客观地看待这一点,你的目标是视图应该能够在Layout类上调用exists()方法,并且只传递一个参数,所以你会问"我如何删除传递文件夹的要求?"

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

# 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:根本不传入文件夹,而是在子文件夹中使用类属性,并利用后期静态绑定:

# 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;
}

这里需要注意的是,您也可以使用函数来代替常量,无论是否在View类中抽象,例如:

# 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);
    }
}

老实说,常量选项稍微短一点,它们本质上都做着相同的事情,除了如果你使用函数而不是常量,如果需要的话,你可以定义操作逻辑。


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