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 implementiere ich es?
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 implementiere ich es?
Antworten:
Es ist wirklich ziemlich einfach, Sie haben eine Reihe von Mutator-Methoden , die alle die ursprünglichen (oder andere) Objekte 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
$foo->setBar(1)->setBaz(2)
vs $table->select()->from('foo')->where('bar = 1')->order('ASC)
. Letzteres umfasst mehrere Objekte.
$a = (new fakeString())->addA()->addB()->getStr();
Grundsätzlich nehmen Sie ein Objekt:
$obj = new ObjectWithChainableMethods();
Rufen Sie eine Methode auf, die return $this;
am Ende effektiv a ausführt:
$obj->doSomething();
Da es dasselbe Objekt oder vielmehr einen Verweis auf dasselbe Objekt zurückgibt , können Sie weiterhin Methoden derselben Klasse vom Rückgabewert aufrufen, wie folgt:
$obj->doSomething()->doSomethingElse();
Das war's wirklich. Zwei wichtige Dinge:
Wie Sie bemerken, ist es nur PHP 5. In PHP 4 funktioniert es nicht richtig, da Objekte nach Wert zurückgegeben werden. Dies bedeutet, dass Sie Methoden für verschiedene Kopien eines Objekts aufrufen, wodurch Ihr Code beschädigt wird.
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;
}
return &$this
in PHP4 tun ?
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'
?>
Methodenverkettung bedeutet, dass Sie Methodenaufrufe verketten können:
$object->method1()->method2()->method3()
Dies bedeutet, dass method1 () ein Objekt zurückgeben muss und method2 () das Ergebnis von method1 () erhält. Methode2 () übergibt dann den Rückgabewert an Methode3 ().
Guter Artikel: http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html
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);
}
}
echo Maker::words(['foo', 'bob', 'bar'])->concate('-')->get();
echo "<br />";
echo Maker::words(['foo', 'bob', 'bar'])->concate('>')->get();
Es gibt 49 Codezeilen, mit denen Sie Methoden über Arrays wie folgt 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";
});
In diesem Artikel erfahren Sie, wie Sie alle siebzig array_-Funktionen des PHP verketten.
http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html
Wenn Sie Methodenverkettung wie in JavaScript meinen (oder einige Leute denken an jQuery), warum nicht einfach eine Bibliothek nehmen, die diesen Entwickler bringt? Erfahrung in PHP? Zum Beispiel Extras - https://dsheiko.github.io/extras/ Dieser erweitert PHP-Typen mit JavaScript- und Unterstreichungsmethoden und bietet Verkettung:
Sie können einen bestimmten Typ verketten:
<?php
use \Dsheiko\Extras\Arrays;
// Chain of calls
$res = Arrays::chain([1, 2, 3])
->map(function($num){ return $num + 1; })
->filter(function($num){ return $num > 1; })
->reduce(function($carry, $num){ return $carry + $num; }, 0)
->value();
oder
<?php
use \Dsheiko\Extras\Strings;
$res = Strings::from( " 12345 " )
->replace("/1/", "5")
->replace("/2/", "5")
->trim()
->substr(1, 3)
->get();
echo $res; // "534"
Alternativ können Sie polymorph gehen:
<?php
use \Dsheiko\Extras\Any;
$res = Any::chain(new \ArrayObject([1,2,3]))
->toArray() // value is [1,2,3]
->map(function($num){ return [ "num" => $num ]; })
// value is [[ "num" => 1, ..]]
->reduce(function($carry, $arr){
$carry .= $arr["num"];
return $carry;
}, "") // value is "123"
->replace("/2/", "") // value is "13"
->then(function($value){
if (empty($value)) {
throw new \Exception("Empty value");
}
return $value;
})
->value();
echo $res; // "13"
Unten ist mein Modell, das anhand der ID in der Datenbank gefunden werden kann. Die with ($ data) -Methode ist mein zusätzlicher Parameter für die Beziehung, daher gebe ich das $ this zurück, das das Objekt selbst ist. Auf meinem Controller kann ich es verketten.
class JobModel implements JobInterface{
protected $job;
public function __construct(Model $job){
$this->job = $job;
}
public function find($id){
return $this->job->find($id);
}
public function with($data=[]){
$this->job = $this->job->with($params);
return $this;
}
}
class JobController{
protected $job;
public function __construct(JobModel $job){
$this->job = $job;
}
public function index(){
// chaining must be in order
$this->job->with(['data'])->find(1);
}
}