PHP에서 객체를 인스턴스화하고 같은 줄에서 메소드를 호출 할 수 있습니까?


126

내가하고 싶은 것은 다음과 같습니다.

$method_result = new Obj()->method();

하지 말고 :

$obj = new Obj();
$method_result = $obj->method();

특정 상황에서는 결과가 실제로 중요하지 않습니다. 그러나 이것을 할 수있는 방법이 있습니까?


4
btw, 5.4를 사용하지 않는 경우 (아마 그렇지 않은 경우) 객체를 체인으로 반환하는 도우미 함수를 정의 할 수 있습니다 ... function with ($ obj) {return $ obj; } (laravel : P)에서 트릭을 선택했습니다. 그러면 다음과 같이 할 수 있습니다. (new Obj)-> method ()
kapv89

BTW, 당신이 이것을 자주하는 것을 발견한다면, my_method대신 선언되어야 하는지 고려할 가치가 있습니다 static.
ToolmakerSteve

답변:


166

요청한 기능은 PHP 5.4에서 사용할 수 있습니다. 다음은 PHP 5.4의 새로운 기능 목록입니다.

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

그리고 새로운 기능 목록에서 관련 부분 :

인스턴스화에 대한 클래스 멤버 액세스가 추가되었습니다 ( 예 : (new Foo)-> bar ()).


9
이것은 또한 원한다면 할 수 있음을 의미합니다 (new Foo)->property.
dave1010

1
아직 이런 방식으로 속성을 할당 할 수는 없습니다. (새로운 푸)-> 속성 = '속성';
CMCDragonkai

7
논리적으로 이해되는 @CMCDragonkai; 객체는 명령문 기간 동안 만 존재합니다. 객체 (new Foo)->property는 어디에도 저장되지 않기 때문에 객체가 더 이상 존재하지 않기 때문에 저장할 값이 없습니다.
thomasrutter 1

1
@CMCDragonkai 해당 setter 를 호출하여이 방법으로 속성을 지정할 수 있습니다 return $this. setter 에 추가 하기 만하면 됩니다. 또한 세터를 연결할 수 있습니다.
iloo

질문이 있습니다. 객체를 별도의 줄에 선언하고 객체를 재사용 할 수있는 것 외에 변수에 저장하면 어떤 이점이 있습니까?
Tyler Swartzenburg

37

당신이 원하는 것을 할 수는 없습니다. 그러나 PHP에서 클래스와 동일한 이름을 가진 함수를 가질 수 있다는 사실을 사용하여 "속임수"를 사용할 수 있습니다. 그 이름은 충돌하지 않습니다.

따라서 다음과 같이 클래스를 선언하면 :

class Test {
    public function __construct($param) {
        $this->_var = $param;
    }
    public function myMethod() {
        return $this->_var * 2;
    }
    protected $_var;
}

그런 다음 해당 클래스의 인스턴스를 반환하고 클래스와 정확히 동일한 이름을 가진 함수를 선언 할 수 있습니다.

function Test($param) {
    return new Test($param);
}

이제는 요청 한대로 하나의 라이너를 사용할 수 있습니다. 단지 함수를 호출하는 것만이므로 new를 사용하지 않아도됩니다.

$a = Test(10)->myMethod();
var_dump($a);

그리고 그것은 작동합니다 : 여기, 나는 얻고 있습니다 :

int 20

출력으로.


그리고 더 나은 것은 함수에 phpdoc을 넣을 수 있다는 것입니다.

/**
 * @return Test
 */
function Test($param) {
    return new Test($param);
}

이런 식으로 IDE에 힌트를 얻을 수 있습니다. 적어도 Eclipse PDT 2.x에서는; screeshot 참조 :



편집 2010-11-30 : 며칠 전에 새로운 RFC가 제출되어 향후 PHP 버전 중 하나에이 기능을 추가 할 것을 제안합니다.

참조 : 의견 요청 : 인스턴스 및 메소드 호출 / 프로퍼티 액세스

따라서 PHP 5.4 또는 다른 향후 버전에서 이와 같은 작업을 수행 할 수 있습니다.

(new foo())->bar()
(new $foo())->bar
(new $bar->y)->x
(new foo)[0]

19

아이디 함수를 정의하여보다 보편적으로 수행 할 수 있습니다.

function identity($x) {
    return $x;
}

identity(new Obj)->method();

그렇게하면 각 클래스에 대한 함수를 정의 할 필요가 없습니다.


10
이 제한의 어리 석음을 강조하는 멋진 솔루션 :)
Ole

19

어때요?

$obj = new Obj(); $method_result = $obj->method(); // ?

:피


16

아니요, 불가능합니다.
메소드를 호출하기 전에 인스턴스를 변수에 지정해야합니다.

정말로 이것을 원하지 않으면 ropstah가 제안한 것처럼 공장을 사용할 수 있습니다.

class ObjFactory{
  public static function newObj(){
      return new Obj();
  }
}
ObjFactory::newObj()->method();

4
핌의 대답이 맞습니다. 또는 객체의 인스턴스를 생성하지 않으려는 경우 정적 함수를 사용할 수 있습니다.
Mark

이것을 사용하여 public static function대신에 사용하도록 강요합니다 public function. 정적 사용을 권장합니까?
ichimaru

6

정적 팩토리 메소드를 사용하여 오브젝트를 생성 할 수 있습니다.

ObjectFactory::NewObj()->method();

3
별도의 공장이 필요하지 않습니다. 같은 클래스의 정적 메소드는 동일한 것을 수행합니다.
Brilliand

3

나도 한 형식에서 다른 형식으로 날짜를 변환하는 단일 표현식의 일부로 이것을 달성하기 위해 하나의 라이너를 찾고있었습니다. 단일 논리 연산이기 때문에 단일 코드 행 에서이 작업을 수행하는 것이 좋습니다. 따라서 이것은 약간 비밀 스럽지만 한 줄 내에서 날짜 객체를 인스턴스화하고 사용할 수 있습니다.

$newDateString = ($d = new DateTime('2011-08-30') ? $d->format('F d, Y') : '');

날짜 문자열을 한 형식에서 다른 형식으로 변환하는 또 다른 방법은 도우미 함수를 사용하여 코드의 OO 부분을 관리하는 것입니다.

function convertDate($oldDateString,$newDateFormatString) {
    $d = new DateTime($oldDateString);
    return $d->format($newDateFormatString);
}

$myNewDate = convertDate($myOldDate,'F d, Y');

객체 지향 접근 방식이 멋지고 필요하다고 생각하지만 때로는 간단한 작업을 수행하기에는 너무 많은 단계가 필요하므로 지루할 수 있습니다.


0

나는 이것이 질문이 갈 때 꽤 오래된 것을 보았지만 여기에 언급해야 할 것이 있습니다.

"__call ()"이라는 특수 클래스 메서드를 사용하여 클래스 내부에 새 항목을 만들 수 있습니다. 다음과 같이 사용하십시오.

<?php
class test
{

function __call($func,$args)
{
    echo "I am here - $func\n";
}

}

    $a = new test();
    $a->new( "My new class" );
?>

출력은 다음과 같아야합니다.

I am here - new

따라서 PHP를 속여 최상위 클래스 (또는 다른 클래스) 내에서 "새"명령을 만들고 요청한 클래스를 포함하도록 include 명령을 __call () 함수에 넣을 수 있습니다. 물론 $ func를 테스트하여 __call () 명령으로 전송 된 "new"명령인지, 그리고 __call ()의 작동 방식으로 인해 다른 명령을 사용할 수도 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.