PHP 5 kullanıyorum ve nesne yönelimli yaklaşımda 'yöntem zincirleme' adı verilen yeni bir özellik duydum. Tam olarak nedir? Nasıl uygularım?
PHP 5 kullanıyorum ve nesne yönelimli yaklaşımda 'yöntem zincirleme' adı verilen yeni bir özellik duydum. Tam olarak nedir? Nasıl uygularım?
Yanıtlar:
Oldukça basit, tüm orijinal (veya diğer) nesneleri döndüren bir dizi mutator yönteminiz var, bu şekilde döndürülen nesne üzerinde yöntemleri çağırmaya devam edebilirsiniz.
<?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();
Bu "ab" çıktıları
$foo->setBar(1)->setBaz(2)
vs $table->select()->from('foo')->where('bar = 1')->order('ASC)
. İkincisi birden fazla nesneye yayılır.
$a = (new fakeString())->addA()->addB()->getStr();
Temel olarak, bir nesne alırsınız:
$obj = new ObjectWithChainableMethods();
return $this;
Sonunda etkili bir şekilde bir yöntem çağırabilirsiniz:
$obj->doSomething();
Aynı nesneyi veya daha ziyade aynı nesneye bir başvuru döndürdüğünden, aynı sınıfın yöntemlerini döndürülen değerden çağırmaya devam edebilirsiniz, şöyle:
$obj->doSomething()->doSomethingElse();
Gerçekten bu kadar. İki önemli şey:
Belirttiğiniz gibi, sadece PHP 5. PHP 4'te düzgün çalışmaz, çünkü nesneleri değere göre döndürür ve bu, bir nesnenin kodunu kıracak farklı kopyalarında yöntem çağırdığınız anlamına gelir.
Yine, nesneyi zincirlenebilir yöntemlerinizde döndürmeniz gerekir:
public function doSomething() {
// Do stuff
return $this;
}
public function doSomethingElse() {
// Do more stuff
return $this;
}
return &$this
PHP4 ile yapabilir misiniz ?
Bu kodu deneyin:
<?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'
?>
Yöntem zinciri, yöntem çağrılarını zincirleyebileceğiniz anlamına gelir:
$object->method1()->method2()->method3()
Bu, method1 () öğesinin bir nesneyi döndürmesi gerektiği ve method2 () yönteminin method1 () sonucunun verildiği anlamına gelir. Daha sonra Method2 (), return değerini method3 () öğesine iletir.
İyi makale: 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();
Bu gibi diziler üzerinde yöntemleri zincirlemenizi sağlayan 49 kod satırı vardır:
$fruits = new Arr(array("lemon", "orange", "banana", "apple"));
$fruits->change_key_case(CASE_UPPER)->filter()->walk(function($value,$key) {
echo $key.': '.$value."\r\n";
});
Tüm PHP'nin yetmiş dizi_ işlevinin nasıl zincirleneceğini gösteren bu makaleye bakın.
http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html
JavaScript'teki gibi zincirleme yöntemini kastediyorsanız (veya bazı insanlar jQuery'yi aklınızda tutarsanız), neden sadece bu geliştirmeyi getiren bir kütüphane almıyorsunuz? PHP deneyimi? Örneğin Ekstralar - https://dsheiko.github.io/extras/ Bu, PHP türlerini JavaScript ve Alt Çizgi yöntemleriyle genişletir ve zincirleme sağlar:
Belirli bir türü zincirleyebilirsiniz:
<?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();
veya
<?php
use \Dsheiko\Extras\Strings;
$res = Strings::from( " 12345 " )
->replace("/1/", "5")
->replace("/2/", "5")
->trim()
->substr(1, 3)
->get();
echo $res; // "534"
Alternatif olarak polimorfik olabilir:
<?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"
Veritabanında kimliğe göre bulabilen modelim aşağıdadır. İle ($ data) yöntemi ilişki için benim ek parametreler olduğunu, bu yüzden nesnenin kendisi $ bu döndürür. Denetleyicimde zincir oluşturabiliyorum.
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);
}
}