Bu, @kaiser cevabına alternatif bir yaklaşımdır , oldukça iyi buldum (benden +1), ancak çekirdek WP işlevleriyle birlikte ek çalışma gerektiriyor ve şablon hiyerarşisi ile entegre edilmiş.
Paylaşmak istediğim yaklaşım, şablonlar için oluşturma verileriyle ilgilenen tek bir sınıfa (üzerinde çalıştığım bir şeyden soyulmuş bir sürüm) dayanıyor.
Bazı (IMO) ilginç özelliklere sahiptir:
- şablonlar standart WordPress şablon dosyalarıdır (single.php, page.php) biraz daha fazla güç alırlar
- mevcut şablonlar sadece çalışır, böylece var olan temalardan şablonu çaba harcamadan entegre edebilirsiniz
- @kaiser yaklaşımından farklı olarak , şablonlarda
$this
anahtar kelimeyi kullanarak değişkenlere erişirsiniz : bu, tanımlanmamış değişkenler durumunda üretimde bildirimlerden kaçınma imkanı verir
Engine
Sınıf
namespace GM\Template;
class Engine
{
private $data;
private $template;
private $debug = false;
/**
* Bootstrap rendering process. Should be called on 'template_redirect'.
*/
public static function init()
{
add_filter('template_include', new static(), 99, 1);
}
/**
* Constructor. Sets debug properties.
*/
public function __construct()
{
$this->debug =
(! defined('WP_DEBUG') || WP_DEBUG)
&& (! defined('WP_DEBUG_DISPLAY') || WP_DEBUG_DISPLAY);
}
/**
* Render a template.
* Data is set via filters (for main template) or passed to method for partials.
* @param string $template template file path
* @param array $data template data
* @param bool $partial is the template a partial?
* @return mixed|void
*/
public function __invoke($template, array $data = array(), $partial = false)
{
if ($partial || $template) {
$this->data = $partial
? $data
: $this->provide(substr(basename($template), 0, -4));
require $template;
$partial or exit;
}
return $template;
}
/**
* Render a partial.
* Partial-specific data can be passed to method.
* @param string $template template file path
* @param array $data template data
* @param bool $isolated when true partial has no access on parent template context
*/
public function partial($partial, array $data = array(), $isolated = false)
{
do_action("get_template_part_{$partial}", $partial, null);
$file = locate_template("{$partial}.php");
if ($file) {
$class = __CLASS__;
$template = new $class();
$template_data = $isolated ? $data : array_merge($this->data, $data);
$template($file, $template_data, true);
} elseif ($this->debug) {
throw new \RuntimeException("{$partial} is not a valid partial.");
}
}
/**
* Used in templates to access data.
* @param string $name
* @return string
*/
public function __get($name)
{
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
if ($this->debug) {
throw new \RuntimeException("{$name} is undefined.");
}
return '';
}
/**
* Provide data to templates using two filters hooks:
* one generic and another query type specific.
* @param string $type Template file name (without extension, e.g. "single")
* @return array
*/
private function provide($type)
{
$generic = apply_filters('gm_template_data', array(), $type);
$specific = apply_filters("gm_template_data_{$type}", array());
return array_merge(
is_array($generic) ? $generic : array(),
is_array($specific) ? $specific : array()
);
}
}
( Burada Gist olarak kullanılabilir .)
Nasıl kullanılır
Gereken tek şey Engine::init()
, muhtemelen 'template_redirect'
kancada yöntemi çağırmaktır . Bu temada functions.php
veya bir eklentiden yapılabilir.
require_once '/path/to/the/file/Engine.php';
add_action('template_redirect', array('GM\Template\Engine', 'init'), 99);
Bu kadar.
Mevcut şablonlarınız beklendiği gibi çalışacaktır. Ancak artık özel şablon verilerine erişme olanağınız var.
Özel Şablon Verileri
Özel verileri şablonlara aktarmak için iki filtre vardır:
'gm_template_data'
'gm_template_data_{$type}'
Birincisi tüm şablonlar için ateşlenir, ikincisi şablona özgüdür, aslında, dymamic kısmı {$type}
dosya uzantısı olmayan şablon dosyasının taban adıdır .
Örneğin filtre şablona 'gm_template_data_single'
veri aktarmak için kullanılabilir single.php
.
Bu kancalara iliştirilen geri çağrılar , anahtarların değişken adları olduğu bir dizi döndürmek zorundadır .
Örneğin, meta verileri şablon verilerinin beğendiği şekilde iletebilirsiniz:
add_filter('gm_template_data', function($data) {
if (is_singular()) {
$id = get_queried_object_id();
$data['extra_title'] = get_post_meta($id, "_theme_extra_title", true);
}
return $data;
};
Ve sonra, şablonun içinde şunları kullanabilirsiniz:
<?= $this->extra_title ?>
Hata ayıklama modu
Hem sabit WP_DEBUG
hem WP_DEBUG_DISPLAY
de doğru olduğunda, sınıf hata ayıklama modunda çalışır. Bir değişken tanımlanmadıysa bir istisna atılır.
Sınıf hata ayıklama modunda olmadığında (büyük olasılıkla üretimde) tanımsız bir değişkene erişim boş bir dize çıkarır.
Veri Modelleri
Verilerinizi düzenlemenin güzel ve sürdürülebilir bir yolu model sınıflarını kullanmaktır.
Bunlar, yukarıda açıklanan filtreleri kullanarak veri döndüren çok basit sınıflar olabilir. Takip edilecek özel bir arayüz yoktur, bunlar tercihinize göre organize edilebilir.
Aşağıda, sadece bir örnek var, ancak kendi tarzınızda yapmakta özgürsünüz.
class SeoModel
{
public function __invoke(array $data, $type = '')
{
switch ($type) {
case 'front-page':
case 'home':
$data['seo_title'] = 'Welcome to my site';
break;
default:
$data['seo_title'] = wp_title(' - ', false, 'right');
break;
}
return $data;
}
}
add_filter('gm_template_data', new SeoModel(), 10, 2);
__invoke()
Yöntemi (bir sınıf bir geri gibi kullanıldığını çalışır) bir dize için kullanılacak döner <title>
şablonun etiketine.
İkinci argümanın 'gm_template_data'
şablon adı olması nedeniyle, yöntem ana sayfa için özel bir başlık döndürür.
Yukarıdaki koda sahip olmak gibi bir şey kullanmak mümkündür
<title><?= $this->seo_title ?></title>
içinde <head>
sayfanın bölümüne.
partials
WordPress, kısmi ana şablona yüklemek için kullanılabilecek get_header()
veya get_template_part()
kullanılabilecek işlevlere sahiptir .
Bu işlevler, diğer tüm WordPress işlevleri gibi, Engine
sınıfı kullanırken şablonlarda kullanılabilir .
Tek sorun, çekirdek WordPress işlevleri kullanılarak yüklenen kısmi bölümlerin içinde, kullanarak özel şablon verileri alma gelişmiş özelliğini kullanmak mümkün değildir $this
.
Bu nedenle, Engine
sınıfın partial()
kısmi (tamamen alt tema ile uyumlu bir şekilde) yüklenmesine izin veren ve yine de özel şablon verilerini kısmen kullanabilen bir yöntemi vardır.
Kullanımı oldukça basit.
Theme partials/content.php
(veya alt tema) klasöründe bir dosya olduğu varsayılarak , aşağıdakiler kullanılarak dahil edilebilir:
<?php $this->partial('partials/content') ?>
Bu kısmi içinde tüm ana tema verilerine erişmek aynı şekilde mümkün olacaktır.
WordPress işlevlerinin aksine, Engine::partial()
yöntem belirli verileri kısmi olarak geçirmeye izin verir, sadece bir dizi veriyi ikinci argüman olarak geçirir.
<?php $this->partial('partials/content', array('greeting' => 'Welcome!')) ?>
Varsayılan olarak, kısmi öğeler ana temada bulunan verilere ve geçirilen veri açıklığına erişime sahiptir.
Kısmen iletilen bir değişkenin üst tema değişkeni ile aynı adı varsa, açıkça geçirilen değişken kazanır.
Bununla birlikte, bir kısmi izole edilmiş modda dahil etmek de mümkündür , yani kısmi üst tema verilerine erişemez. Bunu yapmak için, true
üçüncü argüman olarak şunu iletin partial()
:
<?php $this->partial('partials/content', array('greeting' => 'Welcome!'), true) ?>
Sonuç
Oldukça basit olsa bile, Engine
sınıf oldukça eksiksizdir, ancak kesinlikle daha da geliştirilebilir. Örneğin, bir değişkenin tanımlanıp tanımlanmadığını kontrol etmenin bir yolu yoktur.
WordPress özellikleri ve şablon hiyerarşisi ile% 100 uyumluluğu sayesinde, mevcut ve üçüncü taraf kodlarıyla sorunsuzca entegre edebilirsiniz.
Ancak, sadece kısmen test edildiğini unutmayın, bu yüzden henüz keşfetmediğim sorunlar olabilir.
Altında beş puan "Ne kazandırdı?" içinde @kaiser cevap :
- Veri yapısını değiştirmeden şablonları kolayca değiştirin
- Kolay okunan şablonlar
- Global kapsamdan kaçının
- Can Birim Testi
- Modeli / veriyi diğer bileşenlere zarar vermeden değiştirebilir
hepsi benim sınıfım için de geçerli.