2009-09-09 17 views
89

Quello che vorrei fare è qualcosa di simile:In PHP, puoi creare un'istanza di un oggetto e chiamare un metodo sulla stessa linea?

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

Invece di avere a che fare:

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

Il risultato in realtà non importa a me nel mio caso specifico. Ma c'è un modo per farlo?

+3

btw, se non si utilizza 5.4 (che probabilmente non lo sono), è possibile definire una funzione di supporto che restituisce appena un oggetto alla catena di cose ... funzione con ($ obj) {return $ obj; } (ho preso il trucco da laravel: P) .. quindi puoi fare con (nuovo Obj) -> method() – kapv89

+0

Semplice come '(new Object()) -> doSomething()'. –

risposta

117

La funzione richiesta è disponibile da PHP 5.4. Ecco l'elenco delle nuove funzionalità in PHP 5.4:

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

E la parte rilevante del nuovo elenco delle caratteristiche: è stato aggiunto

accesso membri di classe su di un'istanza, per esempio (nuovo Foo) -> bar().

+7

Nota che questo significa anche che puoi fare '(new Foo) -> property' se vuoi. – dave1010

+0

Questa è una caratteristica davvero interessante di PHP 5.4, peccato che non sia disponibile su 5.3.27 (che sono). – crmpicco

+1

Nota che non è ancora possibile assegnare proprietà in questo modo. (new Foo) -> property = 'property'; – CMCDragonkai

14

No, questo non è possibile.
È necessario assegnare l'istanza a una variabile prima di poter chiamare uno dei suoi metodi.

Se davvero wan't per fare questo si potrebbe usare una fabbrica come ropstah suggerisce:

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

La risposta di Pim è corretta. In alternativa è possibile utilizzare le funzioni statiche se non si desidera creare un'istanza dell'oggetto – Mark

+1

Cos'è un objFacotry?;) – Ropstah

6

è possibile utilizzare un metodo factory statica per produrre l'oggetto:

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

Non è necessaria una fabbrica separata; un metodo statico nella stessa classe realizzerà la stessa cosa. – Brilliand

18

Come su :

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

: P

+11

Ottima risposta: P Mi ha fatto ridere. –

36

Non puoi fare ciò che stai chiedendo; ma puoi "ingannare", usando il fatto che, in PHP, puoi avere una funzione che ha lo stesso nome di una classe; quei nomi non entreranno in conflitto.

Quindi, se avete dichiarato una classe come questa:

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

È quindi possibile dichiarare una funzione che restituisce un'istanza di quella classe - e ha esattamente lo stesso nome della classe:

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

Ed ora, diventa possibile utilizzare un one-liner, come hai chiesto - unica cosa è che si sta chiamando la funzione, quindi non utilizzando il nuovo:

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

E funziona: qui, mi sto:

int 20 

come output.


E, meglio, si può mettere un po 'phpdoc sulla vostra funzione:

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

In questo modo, potrai anche avere osservazioni in vostro IDE - almeno, con Eclipse PDT 2.x; vedere la screeshot:

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



Edit 2010-11-30: Solo per informazioni, un nuovo RFC è stata presentata, pochi giorni fa, che si propone di aggiungere questa funzione per una delle future versioni di PHP.

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

Così, magari facendo le cose come queste sarà possibile in PHP 5.4 o un altro futuro versione:

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

bello! non lo sapevo, – knittl

+0

Neanche io, grazie. – Ropstah

+0

Wow, molto bello! Non lo sapevo. –

18

si può fare più universalmente definendo una funzione identità:

In questo modo non è necessario definire una funzione per ogni classe.

+10

Bella soluzione in quanto enfatizza la stupidità di questa limitazione :) – Ole

3

Anch'io stavo cercando un one-liner per realizzare questo come parte di una singola espressione per convertire le date da un formato all'altro. Mi piace farlo in una singola riga di codice perché è una singola operazione logica. Quindi, questo è un po 'criptico, ma consente di istanze e utilizzare un oggetto data all'interno di una sola riga:

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

Un altro modo per una riga la conversione di stringhe di data da un formato ad un altro è quello di utilizzare un funzione di supporto per gestire le parti OO del codice:

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

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

ritengo l'approccio object oriented è fresco e necessario, ma a volte può essere noioso, richiede troppi passaggi per eseguire operazioni semplici.

0

vedo questo è abbastanza vecchio come domande vanno ma qui è qualcosa che penso dovrebbe essere menzionato:

Il metodo di classe speciale chiamata "__call()" può essere usato per creare nuovi oggetti all'interno di una classe . Si utilizza in questo modo:

<?php 
class test 
{ 

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

} 

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

uscita dovrebbe essere:

I am here - new 

Così, si può ingannare il PHP a fare un comando "nuova" all'interno della classe di livello superiore (o qualsiasi classe davvero) e metti il ​​tuo comando include nella funzione __call() per includere la classe che hai richiesto. Ovviamente, vorrai testare $ func per assicurarti che sia un comando "nuovo" che è stato inviato al comando __call() e (ovviamente) potresti avere altri comandi anche a causa di come funziona __call().

Problemi correlati