WordPress için ne kadar çok kişiselleştirme yaparsam, o dosyayı düzenlemem mi yoksa bölmem mi gerektiğini düşünmeye başladım.
Daha spesifik olarak, yalnızca yönetici alanı için geçerli olan bir grup özel işlevim varsa ve sadece genel web siteme uygulanan diğerleri, tüm yönetici işlevlerini kendi dosyalarına dahil etmenin veya bunları gruplandırmanın bir nedeni olabilir mi?
Bunları ayrı dosyalara bölmek veya bir arada gruplandırmak bir WordPress web sitesini hızlandırır mı yoksa WordPress/PHP otomatik olarak is_admin kod öneki olan işlevleri atlar mı?
Büyük işlevler dosyasıyla başa çıkmanın en iyi yolu nedir (benimki 1370 satır uzunluğunda).
Eğer temanızın functions.php
içindeki kodun ezilmeye başladığı noktaya geliyorsanız, kesinlikle onu birden fazla dosyaya bölmeyi düşünmeye hazır olduğunuzu söyleyebilirim. Ben bu noktada neredeyse ikinci doğası gereği yapmak eğilimindeyim.
functions.php
Dosyasında Dosyaları İçer'i kullanın "include" adında bir alt dizin yaratıyorum ve tema dizinimin altında kodumu, o zamanlar için bana mantıklı gelen (yani bir site geliştikçe kodları sürekli olarak yeniden gözden geçiriyor ve taşıyacağım anlamına gelen) organize edilmiş dosyalara bölüyorum. ) Ayrıca nadiren functions.php
içindeki herhangi bir gerçek kodu koyarım; her şey dosya içerisine girer; sadece benim tercihim.
Sadece size bir örnek vermek gerekirse, burada WordPress Cevapları üzerindeki sorulara cevaplarımı test etmek için kullandığım test kurulumum. Bir soruya her cevap verdiğimde tekrar ihtiyacım olması durumunda kodu saklı tutuyorum. Bu, canlı bir site için tam olarak ne yapacağınız değildir, ancak kodu bölme mekanizmasını gösterir:
<?php
/*
* functions.php
*
*/
require_once( __DIR__ . '/includes/null-meta-compare.php');
require_once( __DIR__ . '/includes/older-examples.php');
require_once( __DIR__ . '/includes/wp-admin-menu-classes.php');
require_once( __DIR__ . '/includes/admin-menu-function-examples.php');
// WA: Adding a Taxonomy Filter to Admin List for a Custom Post Type?
// http://wordpress.stackexchange.com/questions/578/
require_once( __DIR__ . '/includes/cpt-filtering-in-admin.php');
require_once( __DIR__ . '/includes/category-fields.php');
require_once( __DIR__ . '/includes/post-list-shortcode.php');
require_once( __DIR__ . '/includes/car-type-urls.php');
require_once( __DIR__ . '/includes/buffer-all.php');
require_once( __DIR__ . '/includes/get-page-selector.php');
// http://wordpress.stackexchange.com/questions/907/
require_once( __DIR__ . '/includes/top-5-posts-per-category.php');
// http://wordpress.stackexchange.com/questions/951/
require_once( __DIR__ . '/includes/alternate-category-metabox.php');
// http://lists.automattic.com/pipermail/wp-hackers/2010-August/034384.html
require_once( __DIR__ . '/includes/remove-status.php');
// http://wordpress.stackexchange.com/questions/1027/removing-the-your-backup-folder-might-be-visible-to-the-public-message-generate
require_once( __DIR__ . '/includes/301-redirects.php');
Kodunuzu işleve göre gruplandırmaya başlamak ve kendi eklentilerinizi oluşturmak için başka bir seçenek. Benim için temanın functions.php
dosyasına kodlamaya başladım ve kodun kodunu çektiğimde kodumun çoğunu eklentilere taşıdım.
Öte yandan, PHP dosyalarınızı yapılandırmak, sipariş ve bakım kolaylığı konusunda% 99, performans ise% 1'dir, eğer (eğer tarayıcı tarafından HTTP üzerinden çağrılan .js
ve .css
dosyalarını düzenlemek tamamen farklı bir durumdur ve çok büyük performans etkileri.) Ancak sunucuda PHP kodunuzu nasıl düzenlediğiniz, performans açısından pek önemli değil.
Ve son fakat en az olmayan kod organizasyonu kişisel tercihtir. Bazı insanlar, kodları nasıl düzenlediğimden de nefret ediyor olabilirim. Hoşunuza giden bir şey bulun ve buna bağlı kalın, ancak daha fazla bilgi edindikçe ve daha rahat ederken stratejinizin zaman içinde gelişmesine izin verin.
Geç cevap
function wpse1403_bootstrap()
{
// Here we load from our includes directory
// This considers parent and child themes as well
locate_template( array( 'inc/foo.class.php' ), true, true );
}
add_action( 'after_setup_theme', 'wpse1403_bootstrap' );
Aynı eklentileri de çalışır.
Ayrıca aşağıdaki gibi dosya sistemi API işlevlerine de göz atın:
home_url()
plugin_dir_url()
plugin_dir_path()
admin_url()
get_template_directory()
get_template_directory_uri()
get_stylesheet_directory()
get_stylesheet_directory_uri()
include/require
sayısının azaltılmasıBir dizinden tümü dosyalarını getirmeniz gerekiyorsa,
foreach ( glob( 'path/to/folder/*.php' ) as $file )
include $file;
Bunun başarısızlıkları görmezden geldiğini (üretim kullanımı için iyi olabilir)/yüklenemez dosyaları aklınızda bulundurun.
Bu davranışı değiştirmek için geliştirme sırasında farklı bir config kullanmak isteyebilirsiniz:
$files = ( defined( 'WP_DEBUG' ) AND WP_DEBUG )
? glob( 'path/to/folder/*.php', GLOB_ERR )
: glob( 'path/to/folder/*.php' )
foreach ( $files as $file )
include $file;
Geri döndüğümde ve bu cevabın gittikçe daha fazla puan aldığını gördüğümde, bugünlerde nasıl yaptığımı gösterebileceğimi düşündüm - PHP 5.3+ dünyasında. Aşağıdaki örnek, tüm dosyaları src/
adlı bir tema alt klasöründen yükler. Burası, menüler, görüntüler vb. Gibi belirli görevleri yerine getiren kütüphanelerim var. Her bir dosya yüklenirken adı bile umursamalısınız. Bu dizinde başka alt klasörleriniz varsa, dikkate alınmazlar.
\FilesystemIterator
, \DirectoryIterator
yerine PHP 5.3+ supercedor şeklindedir. Her ikisi de PHP SPL’nin bir parçasıdır. PHP 5.2 yerleşik SPL uzantısını kapatmayı mümkün kılarken (tüm kurulumların% 1'inden azı bunu yaptı), SPL şimdi PHP çekirdeğinin bir parçası.
<?php
namespace Theme;
$files = new \FilesystemIterator( __DIR__.'/src', \FilesystemIterator::SKIP_DOTS );
foreach ( $files as $file )
{
/** @noinspection PhpIncludeInspection */
! $files->isDir() and include $files->getRealPath();
}
Önceden hala PHP 5.2.x'i desteklerken, şu çözümü kullandım: \FilterIterator
dizinindeki bir src/Filters
, yalnızca dosyaları almak (ve klasörlerin nokta işaretçileri değil) ve döngü ve yükleme yapmak için \DirectoryIterator
.
namespace Theme;
use Theme\Filters\IncludesFilter;
$files = new IncludesFilter( new \DirectoryIterator( __DIR__.'/src' ) );
foreach ( $files as $file )
{
include_once $files->current()->getRealPath();
}
\FilterIterator
bu kadar kolaydı:
<?php
namespace Theme\Filters;
class IncludesFilter extends \FilterIterator
{
public function accept()
{
return
! $this->current()->isDot()
and $this->current()->isFile()
and $this->current()->isReadable();
}
}
PHP 5.2 şu anda ölü/EOL olmasının yanı sıra (ve ayrıca 5.3), oyunda daha fazla kod ve bir dosya daha olduğu gerçeği var, bu yüzden daha sonra gidip destek olmak için bir neden yok PHP 5.2.x.
Daha derinlemesine bir makale daha bulunabilir burada WPKrauts'ta .
EDITAçıkçası doğru yol, PSR-4 için hazırlanan ve her şeyi ad alanıyla tanımlanmış uygun dizine koyarak otomatik yükleme için namespace
d kodunu kullanmaktır. O zaman bağımlılıklarını yönetmek için sadece Composer ve bir composer.json
kullanın ve PHP otomatik yükleyicinizi otomatik olarak oluşturmasına izin verin (bu sadece use \<namespace>\ClassName
dosyasını çağırarak otomatik olarak bir dosya alır). Bu, PHP dünyasındaki fiili standart, gitmenin en kolay ve daha önceden otomatikleştirilmiş ve sadeleştirilmiş hali WP Başlangıç .
Bir klasör içindeki dosyalara bir işlev kullanmayı seviyorum. Bu yaklaşım, yeni dosyalar eklerken yeni özellikler eklemeyi kolaylaştırır. Ama ben her zaman sınıfta ya da isim alanında yazıyorum - ona fonksiyonların ismi, metodu vb.
Küçük bir örneğin altında; ut ayrıca, * .php sınıfı ile ilgili anlaşmayla birlikte kullanılır.
public function __construct() {
$this->load_classes();
}
/**
* Returns array of features, also
* Scans the plugins subfolder "/classes"
*
* @since 0.1
* @return void
*/
protected function load_classes() {
// load all files with the pattern class-*.php from the directory classes
foreach( glob( dirname( __FILE__ ) . '/classes/class-*.php' ) as $class )
require_once $class;
}
Temalarda sıklıkla başka bir senaryo kullanıyorum. Externel dosyasının fonksiyonunu bir destek ID'sinde tanımlarım, örneğe bakın. Externel dosyasının getirisini kolayca devre dışı bırakacaksam, kullanışlıdır. WP core function require_if_theme_supports()
işlevini kullanıyorum ve yalnızca destek kimliği etkinse yüklenir. Takip eden örnekte, bu desteklenen kimliği dosyayı yüklemeden önceki satırda tanımladım.
/**
* Add support for Theme Customizer
*
* @since 09/06/2012
*/
add_theme_support( 'documentation_customizer', array( 'all' ) );
// Include the theme customizer for options of theme options, if theme supported
require_if_theme_supports(
'documentation_customizer',
get_template_directory() . '/inc/theme-customize.php'
);
Daha fazlasını bu temanın deposunda içinde görebilirsiniz.
ayrılma açısından, kazan tabağımda, tema dizininde fonksiyonlar adında bir klasör aramak için özel bir fonksiyon kullanıyorum, eğer orada değilse yaratıyor. Sonra bu klasörde (varsa) bulduğu tüm .php dosyalarının bir dizisini yaratır ve bir include () çalıştırır; her birinde.
Bu şekilde, her yeni işlevsellik yazmam gerektiğinde, işlevler klasörüne sadece PHP dosyasını ekliyorum ve siteye kodlama konusunda endişelenmenize gerek yok.
<?php
/*
FUNCTIONS for automatically including php documents from the functions folder.
*/
//if running on php4, make a scandir functions
if (!function_exists('scandir')) {
function scandir($directory, $sorting_order = 0) {
$dh = opendir($directory);
while (false !== ($filename = readdir($dh))) {
$files[] = $filename;
}
if ($sorting_order == 0) {
sort($files);
} else {
rsort($files);
}
return ($files);
}
}
/*
* this function returns the path to the funtions folder.
* If the folder does not exist, it creates it.
*/
function get_function_directory_extension($template_url = FALSE) {
//get template url if not passed
if (!$template_url)$template_url = get_bloginfo('template_directory');
//replace slashes with dashes for explode
$template_url_no_slash = str_replace('/', '.', $template_url);
//create array from URL
$template_url_array = explode('.', $template_url_no_slash);
//--splice array
//Calculate offset(we only need the last three levels)
//We need to do this to get the proper directory, not the one passed by the server, as scandir doesn't work when aliases get involved.
$offset = count($template_url_array) - 3;
//splice array, only keeping back to the root WP install folder (where wp-config.php lives, where the front end runs from)
$template_url_array = array_splice($template_url_array, $offset, 3);
//put back togther as string
$template_url_return_string = implode('/', $template_url_array);
fb::log($template_url_return_string, 'Template'); //firephp
//creates current working directory with template extention and functions directory
//if admin, change out of admin folder before storing working dir, then change back again.
if (is_admin()) {
$admin_directory = getcwd();
chdir("..");
$current_working_directory = getcwd();
chdir($admin_directory);
} else {
$current_working_directory = getcwd();
}
fb::log($current_working_directory, 'Directory'); //firephp
//alternate method is chdir method doesn't work on your server (some windows servers might not like it)
//if (is_admin()) $current_working_directory = str_replace('/wp-admin','',$current_working_directory);
$function_folder = $current_working_directory . '/' . $template_url_return_string . '/functions';
if (!is_dir($function_folder)) mkdir($function_folder); //make folder, if it doesn't already exist (lazy, but useful....ish)
//return path
return $function_folder;
}
//removed array elements that do not have extension .php
function only_php_files($scan_dir_list = false) {
if (!$scan_dir_list || !is_array($scan_dir_list)) return false; //if element not given, or not array, return out of function.
foreach ($scan_dir_list as $key => $value) {
if (!strpos($value, '.php')) {
unset($scan_dir_list[$key]);
}
}
return $scan_dir_list;
}
//runs the functions to create function folder, select it,
//scan it, filter only PHP docs then include them in functions
add_action('wp_head', fetch_php_docs_from_functions_folder(), 1);
function fetch_php_docs_from_functions_folder() {
//get function directory
$functions_dir = get_function_directory_extension();
//scan directory, and strip non-php docs
$all_php_docs = only_php_files(scandir($functions_dir));
//include php docs
if (is_array($all_php_docs)) {
foreach ($all_php_docs as $include) {
include($functions_dir . '/' . $include);
}
}
}
Bir ağ kurulumu üzerinden genel farklı dillerde yaklaşık 50 benzersiz özel sayfa türüne sahip bir siteyi yönetiyorum. TON eklentileri ile birlikte.
Bir noktada hepsini bölmek zorunda kaldık. 20-30k kod satırlı bir fonksiyon dosyası hiç de komik değil.
Kod tabanını daha iyi yönetmek için tüm kodları tamamlayıcıya karar vermeye karar verdik. Varsayılan wordpress tema yapısı küçük siteler için iyidir, ancak daha büyük siteler için iyidir.
Yeni fonksiyonlarımız.pp yalnızca siteyi başlatmak için neyin gerekli olduğunu, ancak belirli bir sayfaya ait hiçbir şeyi içermemektedir.
Şimdi kullandığımız tema düzeni MCV tasarım modeline benzer, ancak prosedürel kodlama tarzında.
Örneğin, üye sayfamız:
sayfa-member.php . Sayfayı başlatmaktan sorumludur. Doğru ajax fonksiyonlarını çağırmak veya benzeri. MCV tarzındaki Controller kısmına eşdeğer olabilir.
functions-member.php . Bu sayfa ile ilgili tüm fonksiyonları içerir. Bu aynı zamanda üyelerimiz için fonksiyonlara ihtiyaç duyan diğer web sayfalarına da dahil edilmiştir.
content-member.php . HTML için veri hazırlar MCV'deki modele eşit olabilir.
layout-member.php . HTML bölümü.
Bu değişiklikleri yaptıktan sonra, geliştirme süresi% 50 oranında kolayca azaldı ve şimdi ürün sahibi bize yeni görevler vermekte zorlanıyor. :)
Alt temalardan functions.php dosyası:
require_once( get_stylesheet_directory() . '/inc/custom.php' );
Functions.php dosyasında gerekli bir dosyayı çağırmanın daha şık bir yolu olacaktır:
request_once locate_template ('/ inc/functions/shortcodes.php');
@kaiser 's ve @mikeschinkel ' nin yanıtlarını birleştirdim.
Temamdaki tüm özelleştirmelerimi bir /includes
klasöründe yaptım ve bu klasör içinde her şeyi alt klasörlere böldüm.
Ben sadece /includes/admin
ve alt içeriğinin true === is_admin()
olduğunda dahil edilmesini istiyorum.
Bir klasör, false
değerini döndürerek iterator_check_traversal_callback
içinde dışlanırsa, alt dizinleri yinelenmez (veya iterator_check_traversal_callback
öğesine geçirilir)
/**
* Require all customizations under /includes
*/
$includes_import_root =
new \RecursiveDirectoryIterator( __DIR__ . '/includes', \FilesystemIterator::SKIP_DOTS );
function iterator_check_traversal_callback( $current, $key, $iterator ) {
$file_name = $current->getFilename();
// Only include *.php files
if ( ! $current->isDir() ) {
return preg_match( '/^.+\.php$/i', $file_name );
}
// Don't include the /includes/admin folder when on the public site
return 'admin' === $file_name
? is_admin()
: true;
}
$iterator_filter = new \RecursiveCallbackFilterIterator(
$includes_import_root, 'iterator_check_traversal_callback'
);
foreach ( new \RecursiveIteratorIterator( $iterator_filter ) as $file ) {
include $file->getRealPath();
}