我有
abstract class A{
public static function getSingle($where = []) {
$classname = get_called_class();
$record = static::turnTheWhereIntoArecordFromDB($where);
$model = new $classname($record);
return $model;
}
}
class B extends A{
}
$x = B::getSingle();
$x
没有类型提示... 我喜欢类型提示,因此我想要B
的类型提示,而不是A
如何直接为$x
启用类型提示?
我认为是什么
public function getSingle($where = []) : ?get_called_class()
这显然不起作用
有什么事吗?
根据评论请求编辑:我在原始问题上方中添加了我认为缺少的点点滴滴。
有关更多完整源代码,请参阅下文。随意发表评论,但这不是问题的一部分。我对下面代码的怀疑与使用位置的界面更相关。例如。 $where
['my_column_name' => 'my_column_val']
为my_column_name = 'my_column_val'
,最终会产生安全隐患。但是,这真的是一个糟糕的程序员ORM。
protected abstract static function get_tablename();
/**
* @param array $where
* @return static|null
*/
public static function getSingle($where = []) {
/** @var wpdb $wpdb */
global $wpdb;
$qr = static::whereToString($where);
$sql = "SELECT * FROM " .$wpdb->prefix . static::get_tablename() . " WHERE ". $qr ;
$record = $wpdb->get_row($sql);
if(!$record){
return null;
}
$classname = get_called_class();
$model = new $classname($record);
return $model;
}
/**
* @param array $where
* @return string
*/
private static function whereToString(array $where): string
{
$i = 0;
$max = sizeof($where);
$qr = '';
foreach ($where as $name => $val) {
if (is_string($val)) {
$qr .= " {$name} = '" . $val . "' ";
} else {
$qr .= " {$name} = " . $val . " ";
}
$i++;
if ($i < $max) {
$qr .= ' AND ';
}
}
return $qr;
}
答案 0 :(得分:3)
对于您提供的示例,您为什么需要工厂方法?您正在从构造函数创建一个新实例,为什么不只是$x = new B($record)
!
上面更新
abstract class A
{
/**
* @param array $where
* @return static
*/
public static function getSingle($where = [])
{
$classname = get_called_class();
$model = new $classname($record);
return $model;
}
}
@return static
将输入提示其子类。我还将你的功能改为静态功能,它是典型的工厂模式。
答案 1 :(得分:1)
将@method B getSingle
添加到B
类phpdoc。
/**
* Class B
* @method B getSingle
*/
class B extends A{
}
答案 2 :(得分:1)
我知道您指定了PHP 7.1,但是从PHP 8(将于2020年11月发布)开始可以通过添加static
返回类型提示来实现。 / p>
The RFC was approved unanimously, 54-0.
这意味着您将能够:
class Foo
public static function build(): static
{
return new static();
}
}
class Bar extends Foo {}
此外,无需混帐$classname = get_called_class(); new $classname();
。您可以简单地进行new static()
,它变得更整洁,并且效果相同。
并且Bar::build()
带有类型提示,以表示它通过后期静态绑定返回Bar
而不返回Foo
。
答案 3 :(得分:0)
让抽象类实现一个接口并输入接口的提示。孩子不必明确地实现接口。
abstract class A implements BarInterface
{
public function foo (): BarInterface
{
return new static;
}
}