IT TIP

새로 생성 된 개체에 메서드를 연결하는 방법은 무엇입니까?

itqueen 2021. 1. 5. 20:49
반응형

새로 생성 된 개체에 메서드를 연결하는 방법은 무엇입니까?


PHP에서 새로 생성 된 개체에 메서드를 연결하는 방법이 있는지 알고 싶습니다.

다음과 같은 것 :

class Foo {
    public function xyz() { ... return $this; }
}

$my_foo = new Foo()->xyz();

누구든지 이것을 달성하는 방법을 알고 있습니까?


PHP 5.4 이상에서는 파서가 수정되어 다음과 같이 할 수 있습니다.

(new Foo())->xyz();

인스턴스화를 괄호로 감싸고 연결합니다.

PHP 5.4 이전에는

new Classname();

구문을 사용하면 인스턴스화에서 메서드 호출을 연결할 수 없습니다. PHP 5.3 구문의 한계입니다. 개체가 인스턴스화되면 연결을 끊을 수 있습니다.

이 문제를 해결하는 데 사용한 한 가지 방법은 일종의 정적 인스턴스화 방법입니다.

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }

    static public function instantiate()
    {
        return new self();
    }
}


$a = Foo::instantiate()->xyz();

new에 대한 호출을 정적 메서드로 래핑하면 메서드 호출로 클래스를 인스턴스화 할 수 있으며 자유롭게 연결할 수 있습니다.


다음과 같이 전역 함수를 정의하십시오.

function with($object){ return $object; }

그러면 다음과 같이 전화 할 수 있습니다.

with(new Foo)->xyz();

PHP 5.4에서는 새로 인스턴스화 된 객체를 연결할 수 있습니다.

http://docs.php.net/manual/en/migration54.new-features.php

이전 버전의 PHP의 경우 Alan Storm의 솔루션을 사용할 수 있습니다.


이 답변은 구식이므로 수정하고 싶습니다.

PHP 5.4.x에서는 메소드를 new-call에 연결할 수 있습니다. 이 클래스를 예로 들어 보겠습니다.

<?php class a {
    public function __construct() { echo "Constructed\n"; }
    public function foo() { echo "Foobar'd!\n"; }
}

이제 이것을 사용할 수 있습니다. $b = (new a())->foo();

출력은 다음과 같습니다.

Constructed
Foobar'd!

자세한 정보는 매뉴얼에서 찾을 수 있습니다 : http://www.php.net/manual/en/migration54.new-features.php


글쎄, 이것은 오래된 질문 일 수 있지만 프로그래밍의 많은 것들과 마찬가지로 결국 대답이 바뀝니다.

PHP 5.3의 경우 생성자에서 직접 연결할 수 없습니다. 그러나 수락 된 답변을 확장하려면 상속을 적절하게 수용하려면 다음을 수행하십시오.

abstract class Foo 
{    
    public static function create() 
    {
        return new static;
    }
}

class Bar extends Foo
{
    public function chain1()
    {
        return $this;
    }

    public function chain2()
    {
        return $this;
    }
}

$bar = Bar::create()->chain1()->chain2();

잘 작동하고 새로운 Bar () 인스턴스를 반환합니다.

In PHP 5.4, however, you can simply do:

$bar = (new Bar)->chain1()->chain2();

Hopefully this helps someone stumbling across the question like I have!


It would be really helpful if they 'fix this' in a future release. I really appreciate the ability to chain (especially when populating collections):

I added a method to the base class of my framework called create() that can be chained off of. Should work with all descendant classes automatically.

class baseClass
{
    ...
    public final static function create()
    {
        $class = new \ReflectionClass(get_called_class());
        return $class->newInstance(func_get_args());
    }
    ...
    public function __call($method, $args)
    {
        $matches = array();
        if (preg_match('/^(?:Add|Set)(?<prop>.+)/', $method, $matches) > 0)
        {
            //  Magic chaining method
            if (property_exists($this, $matches['prop']) && count($args) > 0)
            {
                $this->$matches['prop'] = $args[0];
                return $this;
            }
        }
    }
    ...
}

Class::create()->SetName('Kris')->SetAge(36);


Just for the sake of completeness (and for the fun of it...), since nobody seems to have mentioned the solution with the shortest (and least sophisticated) code.

For frequently used short-lived objects, especially when writing test cases, where you typically do lots of object creation, you may want to optimize for typing convenience (rather than purity), and sorta' combine Alan Storm's Foo::instantiate() factory method and Kenaniah's with() global function technique.

Simply make the factory method a global function with the same name as the class!. ;-o (Either add it as a convenience wrapper around the proper static Foo::instantiate() or just move it out there while nobody is looking.)

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }
}

function Foo()
{
    return new Foo();
}

$a = Foo()->xyz();

NOTE:

  • I WOULDN'T DO THIS on production code. While kinda' sexy, this is an abuse on basic coding principles (like "principle of least surprise" (although this is actually rather intuitive syntax), or "don't repeat yourself", esp. if wrapping a real factory method with some parameters, which itself, BTW, is already an abuse of DRY...), plus PHP may change in he future to break code like this in funny ways.

ReferenceURL : https://stackoverflow.com/questions/2188629/how-to-chain-method-on-a-newly-created-object

반응형