Ich verwende PHP 5 und habe von einer neuen Funktion im objektorientierten Ansatz gehört, die als „Methodenverkettung“ bezeichnet wird. Was ist es genau? Wie setze ich es um?
PHP-Methodenverkettung oder fließende Schnittstelle?
Sanjay Khatri
Kristoffer Sall-Storgaard
Es ist wirklich ziemlich einfach. Sie haben eine Reihe von Mutator-Methoden die alle das ursprüngliche (oder andere) Objekt zurückgeben. Auf diese Weise können Sie weiterhin Methoden für das zurückgegebene Objekt aufrufen.
<?php
class fakeString
{
private $str;
function __construct()
{
$this->str = "";
}
function addA()
{
$this->str .= "a";
return $this;
}
function addB()
{
$this->str .= "b";
return $this;
}
function getStr()
{
return $this->str;
}
}
$a = new fakeString();
echo $a->addA()->addB()->getStr();
Dies gibt “ab” aus
-
Dies wird manchmal auch als Fluent Interface bezeichnet
– Nithesh Chandra
16. September 2010 um 6:31 Uhr
-
@Nitesh das ist falsch. Fließende Schnittstellen verwenden Methodenverkettung als ihr primärer Mechanismus, aber es ist nicht das gleiche. Die Methodenverkettung gibt einfach das Host-Objekt zurück, während eine Fluent-Schnittstelle darauf abzielt, eine zu erstellen DSL. Ex:
$foo->setBar(1)->setBaz(2)
vs$table->select()->from('foo')->where('bar = 1')->order('ASC)
. Letzteres erstreckt sich über mehrere Objekte.– Gordon
16. September 2010 um 7:32 Uhr
-
öffentliche Funktion __toString() { return $this->str; } Dies erfordert nicht die letzte Methode “getStr()”, wenn Sie die Kette bereits ausgeben.
– Schriftart
22. April 2014 um 7:01 Uhr
-
@tfont Stimmt, aber dann führen wir magische Methoden ein. Ein Konzept nach dem anderen sollte ausreichen.
– Kristoffer Sall-Storgaard
22. April 2014 um 8:49 Uhr
-
Seit PHP 5.4 ist das sogar möglich alles in einer Zeile:
$a = (new fakeString())->addA()->addB()->getStr();
– Philzen
1. Juni 2015 um 18:49 Uhr
Grundsätzlich nehmen Sie ein Objekt:
$obj = new ObjectWithChainableMethods();
Rufen Sie eine Methode auf, die a effektiv ausführt return $this;
Am Ende:
$obj->doSomething();
Da es dasselbe Objekt zurückgibt, oder besser gesagt a Hinweis für dasselbe Objekt können Sie weiterhin Methoden derselben Klasse vom Rückgabewert aufrufen, wie folgt:
$obj->doSomething()->doSomethingElse();
Das ist es wirklich. Zwei wichtige Dinge:
-
Wie Sie bemerken, ist es nur PHP 5. Es wird in PHP 4 nicht richtig funktionieren, weil es Objekte nach Wert zurückgibt und das bedeutet, dass Sie Methoden für verschiedene Kopien eines Objekts aufrufen, was Ihren Code beschädigen würde.
-
Auch hier müssen Sie das Objekt in Ihren verkettbaren Methoden zurückgeben:
public function doSomething() { // Do stuff return $this; } public function doSomethingElse() { // Do more stuff return $this; }
-
Könntest du tun
return &$this
in PHP4?– Alex
16. September 2010 um 6:18 Uhr
-
@alex: Ich habe gerade kein PHP 4 zum Testen, aber ich bin mir ziemlich sicher, dass es nicht so ist.
– BoltClock
16. September 2010 um 6:23 Uhr
-
Das dachte ich auch nicht, aber es sollte richtig funktionieren? Vielleicht, wenn PHP4 nicht so PHP4-artig wäre.
– Alex
16. September 2010 um 6:26 Uhr
mwangaben
Versuchen Sie diesen Code:
<?php
class DBManager
{
private $selectables = array();
private $table;
private $whereClause;
private $limit;
public function select() {
$this->selectables = func_get_args();
return $this;
}
public function from($table) {
$this->table = $table;
return $this;
}
public function where($where) {
$this->whereClause = $where;
return $this;
}
public function limit($limit) {
$this->limit = $limit;
return $this;
}
public function result() {
$query[] = "SELECT";
// if the selectables array is empty, select all
if (empty($this->selectables)) {
$query[] = "*";
}
// else select according to selectables
else {
$query[] = join(', ', $this->selectables);
}
$query[] = "FROM";
$query[] = $this->table;
if (!empty($this->whereClause)) {
$query[] = "WHERE";
$query[] = $this->whereClause;
}
if (!empty($this->limit)) {
$query[] = "LIMIT";
$query[] = $this->limit;
}
return join(' ', $query);
}
}
// Now to use the class and see how METHOD CHAINING works
// let us instantiate the class DBManager
$testOne = new DBManager();
$testOne->select()->from('users');
echo $testOne->result();
// OR
echo $testOne->select()->from('users')->result();
// both displays: 'SELECT * FROM users'
$testTwo = new DBManager();
$testTwo->select()->from('posts')->where('id > 200')->limit(10);
echo $testTwo->result();
// this displays: 'SELECT * FROM posts WHERE id > 200 LIMIT 10'
$testThree = new DBManager();
$testThree->select(
'firstname',
'email',
'country',
'city'
)->from('users')->where('id = 2399');
echo $testThree->result();
// this will display:
// 'SELECT firstname, email, country, city FROM users WHERE id = 2399'
?>
-
das nenne ich mal eine gute erklärung…verkettungsmethoden bescheren mir immer gänsehaut!!
– MEINE
12. Februar 2016 um 13:24 Uhr
-
Wie ich (innerhalb der Methode) die ersten und letzten Elemente (Aufrufe) in der Kette identifiziere. Denn manchmal ist dies jetzt nur eine Liste von Operationen, die der Reihe nach ausgeführt werden sollen, aber etwas, das nach dem Sammeln aller Elemente erledigt werden sollte. Als würde man hier eine SQL-Abfrage ausführen – aber Vorsicht, Sie könnten mehrere verkettete Aufrufe für ein Objekt ausführen! Erster und Letzter in jedem.
– Andrés
4. April 2018 um 22:45 Uhr
Ein weiterer Weg zur statischen Methodenverkettung:
class Maker
{
private static $result = null;
private static $delimiter=".";
private static $data = [];
public static function words($words)
{
if( !empty($words) && count($words) )
{
foreach ($words as $w)
{
self::$data[] = $w;
}
}
return new static;
}
public static function concate($delimiter)
{
self::$delimiter = $delimiter;
foreach (self::$data as $d)
{
self::$result .= $d.$delimiter;
}
return new static;
}
public static function get()
{
return rtrim(self::$result, self::$delimiter);
}
}
Berufung
echo Maker::words(['foo', 'bob', 'bar'])->concate('-')->get();
echo "<br />";
echo Maker::words(['foo', 'bob', 'bar'])->concate('>')->get();
alexn
Methodenverkettung bedeutet, dass Sie Methodenaufrufe verketten können:
$object->method1()->method2()->method3()
Das bedeutet, dass Methode1() ein Objekt zurückgeben muss und Methode2() das Ergebnis von Methode1() erhält. Method2() übergibt dann den Rückgabewert an method3().
Guter Artikel: http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html
-
Die Erklärung ist etwas daneben. Die Rückgabewerte werden nicht herumgereicht. Die Methoden geben einfach das Host-Objekt zurück.
– Gordon
16. September 2010 um 8:19 Uhr
-
@Gordon Nun, das Hostobjekt wird nicht zurückgegeben. Jedes Objekt kann zurückgegeben und verkettet werden.
– alexn
16. September 2010 um 14:38 Uhr
-
Dann würde ich argumentieren, dass es keine Methodenverkettung im Sinne von Fowler ist, z Make-Modifikatormethoden geben das Hostobjekt zurück, sodass mehrere Modifikatoren in einem einzigen Ausdruck aufgerufen werden können. – Wenn Sie andere Objekte zurückgeben, handelt es sich eher um ein Fluent Interface 🙂
– Gordon
16. September 2010 um 14:58 Uhr
-
Wow, mir ist klar, dass ich einen fast 8 Jahre alten Beitrag kommentiere. Aber Ihr Link, den Sie dort haben, leitet auf eine andere Website weiter. Nur zur Info.
– willbeeler
19. Oktober 2017 um 18:41 Uhr
-
hier ist das Original Beitrag von Fowler aus dem Jahr 2005wobei sowohl Fluent Interface als auch Method Chaining erwähnt werden:
– Matt Smith
6. Februar um 13:59 Uhr
Bärenfell
Es gibt 49 Codezeilen, mit denen Sie Methoden wie folgt über Arrays verketten können:
$fruits = new Arr(array("lemon", "orange", "banana", "apple"));
$fruits->change_key_case(CASE_UPPER)->filter()->walk(function($value,$key) {
echo $key.': '.$value."\r\n";
});
Sehen Sie sich diesen Artikel an, der Ihnen zeigt, wie Sie alle siebzig array_-Funktionen von PHP verketten.
http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html
-
Die Erklärung ist etwas daneben. Die Rückgabewerte werden nicht herumgereicht. Die Methoden geben einfach das Host-Objekt zurück.
– Gordon
16. September 2010 um 8:19 Uhr
-
@Gordon Nun, das Hostobjekt wird nicht zurückgegeben. Jedes Objekt kann zurückgegeben und verkettet werden.
– alexn
16. September 2010 um 14:38 Uhr
-
Dann würde ich argumentieren, dass es keine Methodenverkettung im Sinne von Fowler ist, z Make-Modifikatormethoden geben das Hostobjekt zurück, sodass mehrere Modifikatoren in einem einzigen Ausdruck aufgerufen werden können. – Wenn Sie andere Objekte zurückgeben, handelt es sich eher um ein Fluent Interface 🙂
– Gordon
16. September 2010 um 14:58 Uhr
-
Wow, mir ist klar, dass ich einen fast 8 Jahre alten Beitrag kommentiere. Aber Ihr Link, den Sie dort haben, leitet auf eine andere Website weiter. Nur zur Info.
– willbeeler
19. Oktober 2017 um 18:41 Uhr
-
hier ist das Original Beitrag von Fowler aus dem Jahr 2005wobei sowohl Fluent Interface als auch Method Chaining erwähnt werden:
– Matt Smith
6. Februar um 13:59 Uhr
pavelbere
Eine fließende Schnittstelle ermöglicht es Ihnen, Methodenaufrufe zu verketten, was zu weniger typisierten Zeichen führt, wenn Sie mehrere Operationen auf dasselbe Objekt anwenden.
class Bill {
public $dinner = 20;
public $desserts = 5;
public $bill;
public function dinner( $person ) {
$this->bill += $this->dinner * $person;
return $this;
}
public function dessert( $person ) {
$this->bill += $this->desserts * $person;
return $this;
}
}
$bill = new Bill();
echo $bill->dinner( 2 )->dessert( 3 )->bill;
Ich würde sagen, die meisten, wenn nicht alle dieser Fragen beziehen sich auf die technischen Aspekte der Verkettung, hier geht es genauer darum, wie man dies erreicht.
– Kristoffer Sall-Storgaard
16. September 2010 um 7:39 Uhr
@Kristoffer das OP hätte anhand dieser Fragen leicht herausfinden können, wie es erreicht wird.
– Gordon
16. September 2010 um 7:46 Uhr
@Kstoffer aber auch gesucht Methodenverkettung von PHP bei Google hätte dem OP a gegeben Lernprogramm von Salathe als allererstes Ergebnis. Es macht mir nichts aus, einfache Fragen zu beantworten, aber manche Leute sind einfach zu faul.
– Gordon
16. September 2010 um 8:00 Uhr
Ich lege Ihnen den endgültigen Entscheidungsbaum zur Verkettung von Methoden zur Durchsicht vor
– rdlowrey
15. August 2012 um 6:30 Uhr