En PHP, pouvez-vous instancier un objet et appeler une méthode sur la même ligne?

Ce que je voudrais faire est quelque chose comme ceci:

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

Au lieu d'avoir à faire:

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

Le résultat n'a pas vraiment d'importance pour moi, dans mon cas précis. Mais, est-il un moyen de faire cela?

99
demandé sur weotch 2009-09-10 02:38:00

8 réponses

La fonctionnalité que vous avez demandée est disponible à partir de PHP 5.4. Voici la liste des nouvelles fonctionnalités de PHP 5.4:

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

Et la partie pertinente de la liste des nouvelles fonctionnalités:

L'accès aux membres de la classe lors de l'instanciation a été ajouté, par exemple (new Foo)->bar().

132
répondu Delian Krustev 2018-09-02 00:40:53

Vous ne pouvez pas faire ce que vous demandez ; mais vous pouvez "tricher", en utilisant le fait que, en PHP, vous pouvez avoir une fonction qui a le même nom qu'une classe ; ces noms n'entre pas en conflit.

Donc, si vous avez déclaré une classe comme ceci :

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

Vous pouvez alors déclarer une fonction qui renvoie une instance de cette classe-et a exactement le même nom que la classe:

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

Et maintenant, il devient possible d'utiliser un one-liner, comme vous l'avez demandé - la seule chose est que vous appelez la fonction, ainsi, ne pas utiliser new:

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

Et ça marche : ici, je reçois:

int 20

Comme sortie.


Et, mieux, vous pouvez mettre un peu de phpdoc sur votre fonction :

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

De cette façon, vous aurez même des indices dans votre IDE - au moins, avec Eclipse PDT 2.x ; voir le screeshot :

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



Edit 2010-11-30 : Juste pour information, une nouvelle RFC a été soumis, un il y a quelques jours, cela propose d'ajouter cette fonctionnalité à L'une des futures versions de PHP.

Voir : demande de commentaires: appel D'Instance et de méthode / accès à la propriété

Donc, peut-être que faire des choses comme celles-ci sera possible en PHP 5.4 ou dans une autre version future:

(new foo())->bar()
(new $foo())->bar
(new $bar->y)->x
(new foo)[0]
37
répondu Pascal MARTIN 2010-11-30 20:13:46

Que diriez-vous de:

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

: P

19
répondu Jeff 2016-04-17 05:42:34

Vous pouvez le faire plus universellement en définissant une fonction d'identité:

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

identity(new Obj)->method();

De Cette façon, vous n'avez pas besoin de définir une fonction pour chaque classe.

18
répondu Tom Pažourek 2011-07-13 00:43:48

Non, ceci n'est pas possible.
Vous devez affecter l'instance à une variable avant de pouvoir appeler l'une de ses méthodes.

Si vous ne voulez vraiment pas faire cela, vous pouvez utiliser une usine comme le suggère ropstah:

class ObjFactory{
  public static function newObj(){
      return new Obj();
  }
}
ObjFactory::newObj()->method();
15
répondu Pim Jager 2017-06-22 13:19:55

Vous pouvez utiliser une méthode d'usine statique pour produire l'objet:

ObjectFactory::NewObj()->method();
6
répondu Ropstah 2009-09-09 22:40:05

Moi aussi, je cherchais un one-liner pour accomplir cela dans le cadre d'une seule expression pour convertir des dates d'un format à un autre. J'aime faire cela dans une seule ligne de code, parce que c'est une simple opération logique. Donc, c'est un peu cryptique, mais cela vous permet d'instancier et d'utiliser un objet date dans une seule ligne:

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

Une autre façon d'une ligne la conversion des chaînes de date d'un format à un autre est d'utiliser une fonction d'aide pour gérer les parties OO du code:

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

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

Je pense que l'approche orientée objet est cool et nécessaire, mais elle peut parfois être fastidieuse, nécessitant trop d'étapes pour accomplir des opérations simples.

3
répondu CodeCavalier 2011-09-01 15:48:08

Je vois que c'est assez vieux que les questions vont Mais voici quelque chose que je pense devrait être mentionné:

La méthode de classe spéciale appelée "_ _ call () " peut être utilisée pour créer de nouveaux éléments à l'intérieur d'une classe. Vous l'utilisez comme ceci:

<?php
class test
{

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

}

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

La sortie doit être:

I am here - new

Ainsi, vous pouvez tromper PHP en faisant une "nouvelle" commande à l'intérieur de votre classe de premier niveau (ou de n'importe quelle classe vraiment) et mettre votre commande include dans la fonction __call () pour inclure la classe que vous avez demandée. Bien sûr, vous voudriez probablement tester $func pour vous assurer qu'il s'agit d'une "nouvelle" commande qui a été envoyée à la commande __call() et (bien sûr) vous pourriez avoir d'autres commandes aussi à cause du fonctionnement de __call ().

0
répondu Mark Manning 2016-01-07 06:27:34