使用 php 不强制新关键字的链方法能力
Chain methods ability without force to new keyword using php
我正在编写一个脚本,必须这样调用:
$father = Father::firstName('Esaaro')->lastName('Ozaaraa')->age(42);
Person::firstName("Soobaasaa")->lastName( "Ozaaraa")->age(17)
->setFather( $father )-> toArray();
所以我们有两个 类 名为 Person
和 Father
。
firstName
两个方法类是static
方法,其他方法是public
.
这是我的文件结构
<?php
class Person
{
protected static $name;
protected $lastName, $age, $father, $result;
public static function firstName($name = null)
{
self::$name = $name;
}
public function lastName($lastName = null)
{
$this->lastName = $lastName;
}
public function age($age = null)
{
$this->age = $age;
}
public function toArray()
{
}
public function setFather(Father $father)
{
}
}
/*
* Father Class
*/
class Father
{
protected static $name;
protected $family, $age, $result;
public static function firstName($name = null)
{
self::$name = $name;
}
public function lastName($lastName = null)
{
$this->family = $lastName;
}
public function age($age = null)
{
$this->age = $age;
}
public function toArray()
{
( (isset(static::$name) && static::$name !== null) ? $this->result['firsName'] = self::$name : '' );
( (isset($this->family) && $this->family !== null) ? $this->result['lastName'] = $this->family : '' );
return $this->result;
}
}
上面的代码只是结构,我刚刚开始编写脚本。文件结构无法更改,因为这是一个挑战。
我应该如何操作我可以调用我之前提到的方法的脚本?
提前致谢
您真正需要的只是静态 firstName
方法来创建 class 和 return 的新实例。
其他 setter 只需要 return $this
提供所谓的 fluent interface.
如果创建实例的唯一方法是通过静态 firstName
方法,您还需要添加一个私有/受保护的构造函数。
例如
class Person
{
private $firstName;
private $lastName;
private $age;
private $father;
private function __construct(string $firstName) {
$this->firstName = $firstName;
}
public static function firstName(string $name) {
return new Person($name);
}
public function lastName(string $lastName) {
$this->lastName = $lastName;
return $this;
}
public function age(int $age) {
$this->age = $age;
return $this;
}
public function setFather(Father $father) {
$this->father = $father;
return $this;
}
public function toArray() {
// just an example
return [
'firstName' => $this->firstName,
'lastName' => $this->lastName,
'age' => $this->age,
'father' => $this->father->toArray(),
];
}
}
我强烈建议不要将 $name
属性 保持为静态。您不想更改一个实例的 $name
并让它更改所有其他实例。这就是我在上面的示例中将其更改为 private $firstName
的原因。
我知道这是一个挑战,因此您可能必须使用特定的 class 结构。但还有另一种方法可以做到这一点:
class Father
{
protected static $instance;
protected $firstName = '';
protected $lastName = '';
public function __call($name, $arguments)
{
if (property_exists($this, $name)) {
$this->$name = array_shift($arguments);
}
return $this;
}
public static function __callStatic($name, $arguments)
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance->$name(...$arguments);
}
public function toArray()
{
return [
'firstName' => $this->firstName,
'lastName' => $this->lastName
];
}
}
在此版本中,您可以以静态或非静态方式调用以受保护变量命名的函数。因此,您可以执行 Father::firstName('dad')->lastName('saray')
,反之亦然 Father::lastName('saray')->firstName('dad')
。为简洁起见,我省略了其他方法,如年龄。
根据评论中的要求,情况如下:
当你调用firstName()
或lastName()
作为静态时,魔术方法__callStatic()
是运行。如果它检测到没有实例,它将创建一个实例,调用该方法并 return 该实例。所有未来的调用都将由魔术方法 __call()
处理。这将设置 属性 和 return 相同的实例。现在,这意味着您可以先将 firstName()
或 lastName()
作为静态调用,然后所有后续调用都将是非静态的。
我正在编写一个脚本,必须这样调用:
$father = Father::firstName('Esaaro')->lastName('Ozaaraa')->age(42);
Person::firstName("Soobaasaa")->lastName( "Ozaaraa")->age(17)
->setFather( $father )-> toArray();
所以我们有两个 类 名为 Person
和 Father
。
firstName
两个方法类是static
方法,其他方法是public
.
这是我的文件结构
<?php
class Person
{
protected static $name;
protected $lastName, $age, $father, $result;
public static function firstName($name = null)
{
self::$name = $name;
}
public function lastName($lastName = null)
{
$this->lastName = $lastName;
}
public function age($age = null)
{
$this->age = $age;
}
public function toArray()
{
}
public function setFather(Father $father)
{
}
}
/*
* Father Class
*/
class Father
{
protected static $name;
protected $family, $age, $result;
public static function firstName($name = null)
{
self::$name = $name;
}
public function lastName($lastName = null)
{
$this->family = $lastName;
}
public function age($age = null)
{
$this->age = $age;
}
public function toArray()
{
( (isset(static::$name) && static::$name !== null) ? $this->result['firsName'] = self::$name : '' );
( (isset($this->family) && $this->family !== null) ? $this->result['lastName'] = $this->family : '' );
return $this->result;
}
}
上面的代码只是结构,我刚刚开始编写脚本。文件结构无法更改,因为这是一个挑战。
我应该如何操作我可以调用我之前提到的方法的脚本?
提前致谢
您真正需要的只是静态 firstName
方法来创建 class 和 return 的新实例。
其他 setter 只需要 return $this
提供所谓的 fluent interface.
如果创建实例的唯一方法是通过静态 firstName
方法,您还需要添加一个私有/受保护的构造函数。
例如
class Person
{
private $firstName;
private $lastName;
private $age;
private $father;
private function __construct(string $firstName) {
$this->firstName = $firstName;
}
public static function firstName(string $name) {
return new Person($name);
}
public function lastName(string $lastName) {
$this->lastName = $lastName;
return $this;
}
public function age(int $age) {
$this->age = $age;
return $this;
}
public function setFather(Father $father) {
$this->father = $father;
return $this;
}
public function toArray() {
// just an example
return [
'firstName' => $this->firstName,
'lastName' => $this->lastName,
'age' => $this->age,
'father' => $this->father->toArray(),
];
}
}
我强烈建议不要将 $name
属性 保持为静态。您不想更改一个实例的 $name
并让它更改所有其他实例。这就是我在上面的示例中将其更改为 private $firstName
的原因。
我知道这是一个挑战,因此您可能必须使用特定的 class 结构。但还有另一种方法可以做到这一点:
class Father
{
protected static $instance;
protected $firstName = '';
protected $lastName = '';
public function __call($name, $arguments)
{
if (property_exists($this, $name)) {
$this->$name = array_shift($arguments);
}
return $this;
}
public static function __callStatic($name, $arguments)
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance->$name(...$arguments);
}
public function toArray()
{
return [
'firstName' => $this->firstName,
'lastName' => $this->lastName
];
}
}
在此版本中,您可以以静态或非静态方式调用以受保护变量命名的函数。因此,您可以执行 Father::firstName('dad')->lastName('saray')
,反之亦然 Father::lastName('saray')->firstName('dad')
。为简洁起见,我省略了其他方法,如年龄。
根据评论中的要求,情况如下:
当你调用firstName()
或lastName()
作为静态时,魔术方法__callStatic()
是运行。如果它检测到没有实例,它将创建一个实例,调用该方法并 return 该实例。所有未来的调用都将由魔术方法 __call()
处理。这将设置 属性 和 return 相同的实例。现在,这意味着您可以先将 firstName()
或 lastName()
作为静态调用,然后所有后续调用都将是非静态的。