PHP5.3 itibariyle size closures or functors etrafında yöntemleri geçmek için kullanabilirsiniz. Bundan önce, size create_function() ile bir anonim işlev yazabilirsiniz, ama bu oldukça garip.
Temelde, ne yapmaya çalışıyorsun Strategy Pattern ile yapılabilir.
removed example code, as it wasnt helpful anymore after the OP changed the question (see wiki)
Bunun dışında, size Fowlers yıllardan Data Source Architectural Patterns içine bakmak isteyebilirsiniz. Zend Framework (ve hemen hemen tüm diğer PHP çerçeveler) teklifi database access classes bu desen için kullanabilirsiniz ve bir paginator class da var, neden onları kontrol değil bunu nasıl yaptığını öğrenmek için.
removed EDIT 1 as it wasnt helpful anymore after the OP changed the question (see wiki)
EDIT 2
Ok, let's take a step by step approach to this (not using a Strategy Pattern though)
Ne soru soruyorlar kolayca bu kod ile çözülebilir:
class Foo
{
public function bar()
{
echo 'bar method in Foo';
}
}
class MyInvoker
{
protected $myObject;
public function __construct()
{
$this->myObject = new Foo();
}
public function __call($method, $args)
{
$invocation = array($this->myObject, $method);
return call_user_func_array($invocation, $args);
}
}
Bu kod ile sadece uygun yöntemleri çağırır. Yöntem adları yok ayarı. Hayır beceriksiz ekstra Invoke yöntemi. Yöntemler denir nasıl yok esinlenmiştir. PHP sadece, örneğin, $ myObject tüm yöntemler MyInvoker mevcut değil göndermek için öğretti __ çağrı işlevi vardır, çünkü gerek yok Foo.:
$invoker = new MyInvoker;
$invoker->bar(); // outputs 'bar method in Foo called'
Siz sadece de Foo sınıfının bir alt sınıfı olmak MyInvoker genişletilmiş olabilir, örneğin
class MyInvoker extends Foo {}
ve daha sonra aynısını yapabilirdi. Bu olsa gerek ne ve o böyle bir şey yapmak, ne kadar anlamsız göstermektedir. MyInvoker artık tek başına hiçbir şey yapmaz. Bu boş bir sınıf ve etkili Foo gibi aynı. Hatta __ çağrı yöntemini kullanarak önceki yaklaşımla bu şey yapmıyor. Ben bir paginator olduğu istenen sonucu, hakkında daha spesifik olmak istedi nedeni budur.
İlk deneyin:
class Paginator()
{
// A class holding all possible queries of our application
protected $queries;
// A class providing access to the database, like PDO_MySql
protected $dbConn;
public function __construct()
{
$this->db = new MyPdo();
$this->queries = new DbQueries();
}
public function __call($method, $args)
{
$invocation = array($this->queries, $method);
$query = call_user_func_array($invocation, $args);
return $this->dbConn->query($query);
}
}
Bu kod ile, bizim paginator sıkıca db bağlantısı sınıfını ve tüm sorguları birleştirilmesi, kendi içinde ihtiyacı olan her şeyi yaratan ve bu çağrıda sağlar, gibi pek
$paginator = new Paginator;
// assuming we have something like getImageCount() in DbQueries
echo $paginator->getImageCount();
Isimli sonra ne oluyor, paginator o (getImageCount bilmiyor tanıyacak) ve __ çağrı yöntemini çağırmak olacaktır. __ Çağrısı yöntemi DbQueries üzerine getImageCount () yöntemini çağırmak için çalışacağız. Mevcutsa bu yana, sırayla çalıştırmak için db bağlantı geçirilen sorgu dönecektir. Büyük sen derdim, ama öyle değil. Aslında, bu korkunç. Sizin paginator sorumluluğu bir tablodaki öğeleri saymak ve belirli bir aralık ve miktarda bu tablodan ürün almak için. Ama şu anda, böyle bir şey yapmıyor. Bu ne oluyor tamamen habersiz olduğunu, bu nedenle yeni bir sınıf deneyelim:
class Paginator
{
protected $dbConn;
protected $itemCount;
public function __construct($dbConn)
{
$this->dbConn = $dbConn;
}
public function countItems($query)
{
$this->itemCount = $this->dbConn->query('select count(*) from (?)', $query);
return $this->itemCount;
}
public function fetchItems($query, $offset = 0, $limit = 20)
{
$sql = sprintf('select * from (?) LIMIT %d, %d', $offset, $limit);
return $this->dbConn->query($sql, $query);
}
}
Çok daha iyi. Şimdi bizim paginator kendisi içindeki nesneleri örneğini değil yani, yerine kompozit bir toplamıdır, ancak kurucusuna ona geçirilecek bunları gerektirir. Bu değişim kolay olduğu gibi bu app çok daha rahat hale getirecek dependency injection (ve aynı zamanda bir loose coupling sağlayan, dbConn bir interface kullandığında) denir Şimdi bileşenler. Bu da zaman Unit Testing kod kullanışlı gelecektir.
Ayrıca, paginator şimdi bunu yapmak için ne gerekiyor üzerinde yoğunlaşmaktadır: sayma ve keyfi bir sorgu getiriliyor ürün. Etrafında yöntemleri geçmesine gerek yok. Karanlık yöntem çağırma gerek yok. Bu gibi kullanmak istiyorum:
$paginator = new Paginator($dbConn);
$query = $dbQueries->findImagesUploadedLastWeek(); // returns SQL query string
$images = $paginator->countItems($query);
if($images > 0) {
$images = $paginator->fetchItems($query);
}
Ve işte bu. Evet, hemen hemen. Elbette sayfalandırma işlemek olurdu. Zaten yukarıda ne uzatmak Ama bu, oldukça önemsiz olmalıdır. $ ImageCount özellik sonraki gitmek için nerede bir ipucu.
Neyse, biraz ışık tutabileceğini umuyorum.
P.S. $this->dbConn->query($sql, $query)
aramalar ders kukla kod vardır. Kopyalama ve yapıştırma onu ve çalışma elde edebilmek için beklemeyin. Buna ek olarak, emin paginator SQL eklenen sorguları kullanmak güvenli olduğundan emin olunmalıdır. Sen birisi tüm db satırları silen bir sorgu eklemek istemem. Kullanıcı girişi asla güvenme.
P.P.S. $query
, bir SQL sorgusu dize olmalıdır. PDO::prepare için PHP kılavuzuna bakın. Genel olarak, onu yürütmeden önce prepare bir açıklamaya daha iyi bir performans ve güvenlik verir. Kılavuzda sayfası, sorgu aramaları ?
ile ilgili ipuçları verecektir. Eğer PDO kullanmak istemiyorsanız, sadece sprintf()
veya str_replace()
olarak değiştirin ?
ile kullanmak $query
, örneğin $this->dbConn->query(sprintf('SELECT count(*) from (%s)', $query)
ama bu bir hazır deyimi faydaları hiçbiri vardır ve potansiyel SQL Injection güvenlik açıkları için kapıyı açar unutmayın.
P.P.P.S Evet Dependency Injection, genellikle tercih edilen bir stratejidir. Bu bile advanved konudur ve tam şu anda kavramak için çok fazla olabilir, ama bunun içine bakarak değer. Eğer kompozisyon üzerinde iyilik toplama lehine çalışırsanız şimdi, bu yeterli olmalı. Sizin sınıflar sadece sorumlu oldukları ne yapmak ve yapıcı aracılığıyla herhangi bir bağımlılıkları almalısınız.