web-dev-qa-db-fra.com

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

Ce que je voudrais faire, c'est quelque chose comme ça:

$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 spécifique. Mais, existe-t-il un moyen de le faire?

116
weotch

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 nouvelle liste de fonctionnalités:

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

154
Delian Krustev

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

Donc, si vous avez déclaré une classe comme celle-ci:

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

Vous pouvez ensuite 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, donc n'utilisez pas new:

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

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

int 20

en sortie.


Et, mieux, vous pouvez mettre du 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 l'aperçu:



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

Voir: Demande de commentaires: accès à l'instance et à la méthode/propriété

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

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

Que diriez-vous:

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

: P

19
Jeff

Vous pouvez le faire de manière plus universelle 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
Tom Pažourek

Non, ce 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 la ropstah:

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

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

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

Moi aussi, je cherchais un one-liner pour accomplir cela dans le cadre d'une expression unique pour convertir les dates d'un format à un autre. J'aime faire cela dans une seule ligne de code car c'est une seule 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 de convertir sur une ligne la conversion des chaînes de date d'un format à un autre consiste à 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
CodeCavalier

Je vois que c'est assez ancien car les questions vont, mais voici quelque chose qui, 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 pour créer une "nouvelle" commande à l'intérieur de votre classe de niveau supérieur (ou n'importe quelle classe vraiment) et mettre votre commande include dans la fonction __call () pour inclure la classe Bien sûr, vous voudrez probablement tester $ func pour vous assurer que c'est une "nouvelle" commande qui a été envoyée à la commande __call () et (bien sûr) vous pourriez également avoir d'autres commandes en raison de la façon dont __call () fonctionne.

0
Mark Manning