2009-09-09 25 views
89

Lo que me gustaría hacer es algo como esto:En PHP, ¿puedes instanciar un objeto y llamar a un método en la misma línea?

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

En lugar de tener que hacer:

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

El resultado en realidad no me importa en mi caso específico. Pero, ¿hay alguna manera de hacer esto?

+3

Por cierto, si no está utilizando 5.4 (que probablemente no sea), puede definir una función de ayuda que simplemente devuelve un objeto para encadenar cosas ... función con ($ obj) {return $ obj; } (recogió el truco desde laravel: P) .. luego puede hacer con (nuevo Obj) -> método() – kapv89

+0

Tan simple como '(new Object()) -> doSomething()'. –

Respuesta

117

La función que ha solicitado está disponible en PHP 5.4. Esta es la lista de las nuevas características de PHP 5.4:

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

y la parte pertinente de la nueva lista de características: se ha añadido

acceso de los miembros de la clase de instancias, por ejemplo, (nuevo Foo) -> barra().

+7

Tenga en cuenta que esto también significa que puede hacer '(nuevo Foo) -> propiedad' si lo desea. – dave1010

+0

Esta es una muy buena característica de PHP 5.4, lástima que no está disponible en 5.3.27 (que estoy en). – crmpicco

+1

Tenga en cuenta que no puede asignar propiedades de esta manera todavía. (nuevo Foo) -> propiedad = 'propiedad'; – CMCDragonkai

14

No, esto no es posible.
Debe asignar la instancia a una variable antes de poder llamar a cualquiera de sus métodos.

Si realmente wa no para hacer esto se podría utilizar como una fábrica ropstah sugiere:

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

La respuesta de Pim es correcta. Alternativamente, podría usar funciones estáticas si no desea crear una instancia del objeto – Mark

+1

¿Qué es un objFacotry?;) – Ropstah

6

Se puede usar un método de fábrica estática para producir el objeto:

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

No hay necesidad de una fábrica separada; un método estático en la misma clase logrará lo mismo. – Brilliand

18

¿Qué tal :

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

: P

+11

Gran respuesta: P me hizo reír. –

36

No puede hacer lo que está pidiendo; pero puede "engañar", usando el hecho de que, en PHP, puede tener una función que tiene el mismo nombre que una clase; esos nombres no entrarán en conflicto.

lo tanto, si usted declaró una clase como esta:

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

Luego, puede declarar una función que devuelve una instancia de esa clase - y tiene exactamente el mismo nombre que la clase:

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

Y ahora, se hace posible usar una sola línea, como lo pediste - lo único que se está llamando a la función, por tanto, no con nuevas:

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

Y funciona: aquí, yo estoy haciendo:

int 20 

como salida.


Y, mejor, puede poner un poco de phpdoc en su función:

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

De esta manera, podrás incluso tienen indicios en su IDE - al menos, con Eclipse PDT 2.x; ver el Screeshot:

http://extern.pascal-martin.fr/so/class-and-function.png



Editar 2010-11-30: Sólo a título informativo, un nuevo RFC se ha presentado, hace unos días, que propone añadir esta característica a una de las versiones futuras de PHP.

Ver: Request for Comments: Instance and method call/property access

Así, tal vez haciendo cosas como éstas será posible en PHP 5.4 u otra versión futura:

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

¡agradable! No sabía que – knittl

+0

Yo tampoco, gracias. – Ropstah

+0

¡Guau, muy agradable! No lo sabía. –

18

Usted puede hacer que sea más universalmente mediante la definición de una función de la identidad:

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

identity(new Obj)->method(); 

De esta forma no es necesario definir una función para cada clase.

+10

Buena solución ya que enfatiza la estupidez de esta limitación :) – Ole

3

Yo también estaba buscando una línea para lograr esto como parte de una expresión única para convertir fechas de un formato a otro. Me gusta hacer esto en una sola línea de código porque es una operación lógica única. Por lo tanto, esto es un poco críptico, pero permite crear instancias y utilizar un objeto de fecha dentro de una sola línea:

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

Otra manera de una sola línea de la conversión de las cadenas de fecha de un formato a otro es utilizar una función auxiliar para gestionar las partes del código OO:

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

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

creo que el enfoque orientado a objetos es fresco y necesario, pero a veces puede ser tedioso, que requiere demasiados pasos para llevar a cabo operaciones simples.

0

Veo esto es bastante viejo como preguntas van, pero aquí es algo que creo que debe ser mencionado:

El método de clase especial llamada "__call()" se puede utilizar para crear nuevos elementos dentro de una clase . Se utiliza de esta manera:

<?php 
class test 
{ 

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

} 

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

de salida debe ser:

I am here - new 

Por lo tanto, se puede engañar a PHP en la fabricación de un comando "nuevo" dentro de su clase de nivel superior (o cualquier clase de verdad) y ponga su comando include en la función __call() para incluir la clase que ha solicitado. Por supuesto, es probable que desee probar $ func para asegurarse de que es un comando "nuevo" que se envió al comando __call() y (por supuesto) también podría tener otros comandos debido a cómo funciona __call().

Cuestiones relacionadas