it-swarm.asia

WordPress Temanızın İşlev.php Dosyasında Kod Düzenleme?

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).

91

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.

Temanızın 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');  

Veya Eklenti Oluştur

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.

Ancak PHP Kod Düzenlemesinden HAYIR Önemli Performans Kazancı

Ö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 Kod Organizasyonu Kişisel Tercihtir

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.

117
MikeSchinkel

Geç cevap

Dosyalarınızı doğru şekilde nasıl dahil edersiniz:

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.

Doğru yol veya URi nasıl alını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()
  • vb.

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;

Düzenleme: OOP/SPL yaklaşımı

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.

Özetlenmiş

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 namespaced 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ıç .

50
kaiser

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.

5
bueltge

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);
    }
  }

}
5
Mild Fuzz

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. :)

4

Alt temalardan functions.php dosyası:

    require_once( get_stylesheet_directory() . '/inc/custom.php' );
3
Brad Dalton

Functions.php dosyasında gerekli bir dosyayı çağırmanın daha şık bir yolu olacaktır:

request_once locate_template ('/ inc/functions/shortcodes.php');

0

@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();
}
0
seangwright