我很头疼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()
方法实现的一般工作流如下所示:
- 父类有一个带有文件夹和文件名的
exists
方法 - 子类偷工减料,因为它已经知道自己的文件夹,并且只接受文件名
- 子类将预定义的变量传递给父方法
如果你客观地看待这一点,你的目标是视图应该能够在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
来代替传递到load
和exists
中的参数。