arc/prototype

ARC:原型继承组件

3.0.1 2020-02-23 15:03 UTC

This package is auto-updated.

Last update: 2024-09-10 23:46:44 UTC


README

Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads Latest Unstable Version License

arc/prototype

此组件向PHP添加原型,包括所有JavaScript特性,如Object.extend、Object.assign、Object.freeze和Object.observe。它还支持每个属性的设置器和获取器。

创建原型对象

    $object = \arc\prototype::create();

添加属性

    $object->foo = 'Foo';

添加方法

    $object->bar = function() {
        return $this->foo.'bar';
    }

扩展对象

    $childObject = \arc\prototype::extend($object);
    $childObject->foo = 'Vue';
    echo $childObject->bar();

快速创建

    $object = \arc\prototype::create([
        'foo' => 'Foo',
        'bar' => function() {
            return $this->foo.'bar';
        }
    ]);

快速扩展

    $childObject = \arc\prototype::extend($object, [
        'foo' => 'Vue'
    ]);

设置器和获取器

    $object->guarded = [
        'set' => function($value) {
            if ( $value !== 'Foo' ) {
                $this->unguarded = $value;
            }
        },
        'get' => function() {
            return 'Foo'.$this->unguarded;
        }
    ];

如果你只有'set'函数,获取值将始终返回'null'。如果你只有'get'函数,设置值将不起作用。

对象最终化

    \arc\prototype::preventExtension($object);
    $childObject = \arc\prototype::extend($object);

这将抛出\BadMethodCallException。

    $isExtensible = \arc\prototype::isExtensible($object); // returns false

对象密封

    $object->foo = 'Foo';
    \arc\prototype::seal($object);
    $object->foo = 'Bar';

这将抛出\LogicException。

$isExtensible = \arc\prototype::isExtensible($object); // returns false
$isSealed = \arc\prototype::isSealed($object); // returns true


## Freezing objects

```php
    $object->foo = 'Foo';
    \arc\prototype::freeze($object);
    $object->foo = 'Bar';

这将抛出\LogicException。

    $isExtensible = \arc\prototype::isExtensible($object); // returns false
    $isSealed = \arc\prototype::isSealed($object); // returns true
    $isFrozen = \arc\prototype::isFrozen($object); // returns true

观察变化

    $log = [];
    \arc\prototype::observe($object, function($changes) use (&$log) {
        $log[] = $changes;
    });

或限制观察器仅针对特定类型的更改

    $log = [];
    \arc\prototype::observe($object, function($changes) use (&$log) {
        $log[] = $changes;
    }, ['add','delete']);

如果没有设置,将观察所有更改类型:'add'、'update'、'delete'、'reconfigure'。

设置器、获取器和超级私有

    function makeAFoo() {
        $superPrivate = 'Shhh...';
        $object = \arc\prototype::create();
        $object->foo = [
            'get' => function() use (&$superPrivate) {
                return $superPrivate;
            }
        ];
        $object->doFoo = function($value) use (&$superPrivate) {
            $superPrivate = 'Shhh... '.$value;
        };
        return $object;
    }            

通过使用不是原型对象属性的变量,但在多个对象方法的作用域内,你可以创建类似于私有属性的东西。但它比普通的私有属性更私密,甚至此对象中的其他方法也无法访问这个变量。这被称为javascript中的'SuperPrivate'。

将arc\prototype用作依赖注入容器

<?php
    $di = \arc\prototype::create([
         'dsn'      => 'mysql:dbname=testdb;host=127.0.0.1';
         'user'     => 'dbuser',
         'password' => 'dbpassword',
         'database' => \arc\prototype::memoize( function() {
             // this generates a single PDO object once and then returns it for each subsequent call
             return new PDO( $this->dsn, $this->user, $this->password );
         } ),
         'session'  => function() {
             // this returns a new mySession object for each call
             return new mySession();
         }
    ] );

    $diCookieSession = \arc\prototype::extend( $di, [ 
         'session'  => function() {
             return new myCookieSession();
         }
    ] );

注意:PHP有一个限制,就是你永远不能将静态函数绑定到对象上。这将导致不可捕获的致命错误。为了解决这个问题,你必须通过在名称前加":"来告诉原型该闭包是静态的。在这种情况下,该方法的第一个参数将始终是当前对象。

<?php
    class foo {
        public static function myFactory() {
            return \arc\prototype::create([
                'foo'  => 'Foo',
                ':bar' => function($self) {
                    return $self->foo;
                },
                'baz' => [
                    ':get' => function($self) {
                        return 'Baz';
                    }
                ]
            ]);
        }
    }

    $f = foo::myFactory();
    echo $f->bar(); // outputs: "Foo";

静态闭包是在静态函数中定义的所有闭包,或者明确定义为静态的。在类作用域外定义的闭包可以被绑定,不需要这个解决方案。

方法

\arc\prototype::create

(object) \arc\prototype::create( (array) $properties )

返回一个具有给定属性的新\arc\prototype\Prototype对象。属性数组可能包含闭包,这些闭包将作为新Prototype对象上的方法可用。

\arc\prototype::extend

(object) \arc\prototype::extend( (object) $prototype, (array) $properties )

这返回一个具有给定属性的新Prototype对象,就像\arc\prototype::create()一样。但除此之外,新对象还有一个原型属性,将其链接到原始对象,该对象从中扩展而来。原始对象上的任何方法或属性也将通过其原型链在新对象中可用。

你可以通过获取\arc\prototype\Prototype对象的原型属性来检查对象的原型。你不能更改此属性 - 它是只读的。你只能通过使用扩展方法来设置原型属性。

\arc\prototype::assign

(object) \arc\prototype::extend( (object) $prototype, (object) ...$objects )

这返回一个具有给定原型的新的Prototype对象。此外,传递给此方法的额外对象上的所有属性都将复制到新的Prototype对象。对于在多个对象上设置的任何属性,较晚对象上的属性值将覆盖来自其他对象的值。

\arc\prototype::freeze

(void) \arc\prototype::freeze( (object) $prototype )

这将使对给定Prototype对象的更改变得不可能。对象变为不可变的。任何尝试更改对象的操作都将静默失败。对象也被密封,不再可扩展。唯一解冻它的方法是通过克隆对象。克隆将被解冻、解密并可用于扩展。

\arc\prototype::isFrozen

(bool) \arc\prototype::isFrozen( (object) $prototype )

如果此对象被冻结且不可变,则返回true。

\arc\prototype::seal

(void) \arc\prototype::seal( (object) $prototype )

这使对象无法添加或删除属性,也无法重新配置它们。对象也不再开放扩展。唯一解封它的方法是克隆它。克隆将不受限制并开放扩展。

\arc\prototype::isSealed

(bool) \arc\prototype::isSealed( (object) $prototype )

如果此对象已密封且属性无法重新配置、添加或删除,则返回true。

\arc\prototype::preventExtensions

(void) \arc\prototype::preventExtensions( (object) $prototype )

这使对象无法添加属性或扩展它。

\arc\prototype::isExtensible

(bool) \arc\prototype::isExtensible( (object) $prototype )

如果此对象开放扩展,则返回true。

\arc\prototype::observe

(void) \arc\prototype::observe( (object) $prototype, (Closure) $f )

每次$prototype的属性发生变化时,都会调用闭包$f。闭包使用原型对象、属性名称和新值调用。如果闭包返回精确的false(其他'falsy'值将不起作用),则更改将被取消。

<?php
    \arc\prototype::observe($object, function($object, $name, $value) {
        if ( $name === 'youcanttouchthis' ) {
            return false;
        }
    });

\arc\prototype::unobserve

(void) \arc\prototype::unobserve( (object) $prototype, (Closure) $f )

从Prototype对象中删除特定的观察器函数。您必须传递完全相同的闭包才能使其工作。

\arc\prototype::getObservers

\arc\prototype::hasProperty

(bool) \arc\prototype::hasProperty( (string) $propertyName )

如果请求的属性当前原型对象本身或其任何原型中可用,则返回true。

\arc\prototype::keys

(array) \arc\prototype::keys( (object) $prototype )

\arc\prototype::values

(array) \arc\prototype::values( (object) $prototype )

\arc\prototype::entries

(array) \arc\prototype::entries( (object) $prototype )

\arc\prototype::ownKeys

(array) \arc\prototype::ownKeys( (object) $prototype )

\arc\prototype::ownValues

(array) \arc\prototype::ownValues( (object) $prototype )

\arc\prototype::ownEntries

(array) \arc\prototype::ownEntries( (object) $prototype )

\arc\prototype::hasOwnProperty

(bool) \arc\prototype::hasOwnProperty( (string) $propertyName )

如果请求的属性当前原型对象本身即可用,而无需检查其原型链,则返回true。

\arc\prototype::hasPrototype

(bool) \arc\prototype::hasPrototype( (string) $prototypeObject )

如果给定对象是当前原型对象原型链的一部分,则返回true。

\arc\prototype::getDescendants

(array) \arc\prototype::getDescendants( (object) $prototype )

\arc\prototype::getInstances

(array) \arc\prototype::getInstances( (object) $prototype )

\arc\prototype::getPrototypes

(array) \arc\prototype::getPrototypes( (object) $prototype )

\arc\prototype::memoize

(Closure) \arc\prototype::memoize( (callable) $f )

返回一个函数,该函数只会运行一次。在第一次运行后,它将返回运行返回的值,除非该值为null。这使得可以创建仅在需要时运行的延迟加载函数。您还可以在依赖注入容器中创建共享对象。

此方法不保证给定的函数永远不会运行多次 - 除非您始终通过产生的闭包间接调用它。