Wie verkettet man eine Methode auf einem neu erstellten Objekt?

Lesezeit: 6 Minuten

Wie verkettet man eine Methode auf einem neu erstellten Objekt
aefxx

Ich würde gerne wissen, ob es eine Möglichkeit gibt, Methoden für ein neu erstelltes Objekt in PHP zu verketten?

Etwas wie:

class Foo {
    public function xyz() { ... return $this; }
}

$my_foo = new Foo()->xyz();

Kennt jemand eine Möglichkeit, dies zu erreichen?

Wie verkettet man eine Methode auf einem neu erstellten Objekt
Alan Sturm

In PHP 5.4+ wurde der Parser modifiziert, sodass Sie so etwas tun können

(new Foo())->xyz();

Schließen Sie die Instanziierung in Klammern ein und verketten Sie sie.

Vor PHP 5.4, wenn Sie die verwenden

new Classname();

-Syntax können Sie einen Methodenaufruf nicht mit der Instanziierung verketten. Es ist eine Einschränkung der Syntax von PHP 5.3. Sobald ein Objekt instanziiert ist, können Sie es verketten.

Eine Methode, die ich gesehen habe, um dies zu umgehen, ist eine Art statische Instanziierungsmethode.

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }

    static public function instantiate()
    {
        return new self();
    }
}


$a = Foo::instantiate()->xyz();

Indem Sie den Aufruf von new in eine statische Methode einschließen, können Sie eine Klasse mit Methodenaufruf instanziieren, und Sie können das dann frei verketten.

  • +1 Ja, ich wollte antworten “Verwenden Sie eine Fabrikmethode”, und das ist im Grunde das, was Sie zeigen.

    – Bill Karwin

    3. Februar 2010 um 0:38 Uhr

  • Ich ziehe es vor, den OO-Jargon aus der Antwort zu lassen, wenn der Fragesteller nicht von der CS-Kultur durchdrungen zu sein scheint. Besser sie lernen das Konzept und identifizieren es später mit seinem “richtigen” Namen, als sich von neuen Begriffen abschrecken zu lassen.

    – Alan Sturm

    3. Februar 2010 um 3:09 Uhr

  • -1 Dies löst nicht das Konstruktorproblem, außerdem werden Sie Probleme mit der Vererbung haben.

    – Kenania

    12. Juli 2011 um 18:35 Uhr


  • Ähm, ja, tut es das? “Das Konstruktorproblem”, über das ich gesprochen habe, war die Unfähigkeit, ein Objekt zu instanziieren und sofort zu verketten, und ja, es gibt Kompromisse in Bezug auf die Vererbung und welche Version von PHP Sie mit statischer Bindung verwenden.

    – Alan Sturm

    12. Juli 2011 um 19:26 Uhr

  • Wenn Sie die statische Instantiierungsmethode verwenden, sollten Sie sie “new static” anstelle von “new self” aufrufen lassen. Auf diese Weise wird, wenn Sie es für eine Unterklasse von Foo aufrufen, eine Instanz der Unterklasse und nicht von Foo selbst erstellt.

    – JW.

    15. Dezember 2014 um 18:44 Uhr

Definieren Sie eine globale Funktion wie folgt:

function with($object){ return $object; }

Sie können dann anrufen:

with(new Foo)->xyz();

  • Ich persönlich ziehe diese Antwort der von Alan vor, sie kann einfach in der Basisklasse eines Frameworks implementiert werden und löst daher das Problem einmal an einem Ort, anstatt Alans Antwort in jeder Klasse implementieren zu müssen! Ich mag DRY-Programmierung!!

    – Chris

    21. August 2012 um 9:21 Uhr

  • Dies wird auch genannt Identitätsfunktioneinige Bibliotheken haben es als id(). Aufgrund seiner Syntax und seines Parsers wird es in PHP häufig verwendet.

    – hakre

    1. Januar 2014 um 10:40 Uhr


  • Das wäre nett, aber was wäre das PHPDoc für diese Methode? PHPStorm verlässt sich auf PHPDoc, um ihm mitzuteilen, welche Datentypen eine Funktion empfängt und zurückgibt; dies ist nicht Java, daher sind keine Generika verfügbar. Ich kann es gerne schreiben @param object $object + @return objectaber dann wird der richtige Datentyp nicht erkannt und die automatische Vervollständigung/Vorschläge funktionieren nicht.

    – Jurchiks

    21. November 2014 um 15:50 Uhr


  • Wirklich eine schlechte Idee, den globalen Namensraum mit einer Benutzerfunktion namens “with” zu verschmutzen. Sie wissen nie, wann das ein reserviertes Schlüsselwort wird oder ob es auch von anderen Bibliotheken verwendet wird. Verwenden Sie stattdessen etwas Einzigartiges.

    – TheStoryCoder

    30. Mai 2016 um 13:29 Uhr

In PHP 5.4 können Sie ein neu instanziiertes Objekt verketten:

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

Für ältere Versionen von PHP können Sie die Lösung von Alan Storm verwenden.

Diese Antwort ist veraltet – möchte sie daher korrigieren.

In PHP 5.4.x können Sie eine Methode mit einem neuen Aufruf verketten. Nehmen wir diese Klasse als Beispiel:

<?php class a {
    public function __construct() { echo "Constructed\n"; }
    public function foo() { echo "Foobar'd!\n"; }
}

Jetzt können wir das verwenden: $b = (new a())->foo();

Und die Ausgabe ist:

Constructed
Foobar'd!

Weitere Informationen finden Sie im Handbuch: http://www.php.net/manual/en/migration54.new-features.php

Nun, das mag eine alte Frage sein, aber wie bei vielen Dingen in der Programmierung ändert sich die Antwort irgendwann.

In Bezug auf PHP 5.3, nein, Sie können nicht direkt aus dem Konstruktor verketten. Um die akzeptierte Antwort jedoch zu erweitern, um die Vererbung angemessen zu berücksichtigen, können Sie Folgendes tun:

abstract class Foo 
{    
    public static function create() 
    {
        return new static;
    }
}

class Bar extends Foo
{
    public function chain1()
    {
        return $this;
    }

    public function chain2()
    {
        return $this;
    }
}

$bar = Bar::create()->chain1()->chain2();

Das wird gut funktionieren und Ihnen eine neue Bar()-Instanz zurückgeben.

In PHP 5.4 können Sie jedoch einfach Folgendes tun:

$bar = (new Bar)->chain1()->chain2();

Hoffentlich hilft das jemandem, der wie ich über die Frage stolpert!

Es wäre wirklich hilfreich, wenn sie dies in einer zukünftigen Version beheben würden. Ich schätze die Möglichkeit der Verkettung sehr (insbesondere beim Auffüllen von Sammlungen):

Ich habe der Basisklasse meines Frameworks namens create() eine Methode hinzugefügt, die verkettet werden kann. Sollte automatisch mit allen untergeordneten Klassen funktionieren.

class baseClass
{
    ...
    public final static function create()
    {
        $class = new \ReflectionClass(get_called_class());
        return $class->newInstance(func_get_args());
    }
    ...
    public function __call($method, $args)
    {
        $matches = array();
        if (preg_match('/^(?:Add|Set)(?<prop>.+)/', $method, $matches) > 0)
        {
            //  Magic chaining method
            if (property_exists($this, $matches['prop']) && count($args) > 0)
            {
                $this->$matches['prop'] = $args[0];
                return $this;
            }
        }
    }
    ...
}

Class::create()->SetName(‘Kris’)->SetAge(36);

Nur der Vollständigkeit halber (und aus Spaß an der Sache …), da anscheinend niemand die Lösung mit dem kürzesten (und am wenigsten ausgefeilten) Code erwähnt hat.

Bei häufig verwendeten kurzlebigen Objekten, insbesondere beim Schreiben von Testfällen, bei denen Sie normalerweise viel Objekterstellung durchführen, möchten Sie möglicherweise die Eingabefreundlichkeit (eher als die Reinheit) optimieren und die von Alan Storm kombinieren Foo::instantiate() Fabrikmethode und Kenaniahs with() globale Funktionstechnik.

Machen Sie einfach die Fabrikmethode a globale Funktion mit demselben Namen wie die Klasse!. ;-o (Fügen Sie es entweder als Convenience-Wrapper um die richtige Statik hinzu Foo::instantiate() oder bewege es einfach nach draußen, während niemand hinschaut.)

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }
}

function Foo()
{
    return new Foo();
}

$a = Foo()->xyz();

HINWEIS:

  • Ich würde dies nicht auf Produktionscode tun. Obwohl es irgendwie sexy ist, ist dies ein Missbrauch grundlegender Codierungsprinzipien (wie “Prinzip der geringsten Überraschung” (obwohl dies eigentlich eine ziemlich intuitive Syntax ist) oder “wiederholen Sie sich nicht”, insbesondere wenn Sie eine echte Fabrikmethode mit einigen verpacken Parameter, was selbst übrigens schon ein Missbrauch von DRY ist…), plus PHP könnte sich in Zukunft ändern, um Code wie diesen auf komische Weise zu brechen.

863900cookie-checkWie verkettet man eine Methode auf einem neu erstellten Objekt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy