私がWordPressをよりカスタマイズするほど、このファイルを整理するのか、それとも分割するのかを考え始めます。
より具体的に言うと、管理領域にのみ適用されるカスタム機能や、私の公開Webサイトにのみ適用される他のカスタム機能がある場合、すべての管理機能を独自のファイルに含めるか、グループ化する必要があります。
それらを別々のファイルに分割したり、一緒にグループ化したりすると、WordPress Webサイトの速度が上がる可能性がありますか。それとも、is_adminコードプレフィックスを持つ関数を自動的にスキップするのですか
大きな関数ファイルを処理するための最良の方法は何ですか(私のものは1370行の長さです)。
テーマのfunctions.php
のコードが圧倒し始めているところまで来たら、間違いなく、複数のファイルに分割することを検討する準備ができていると思います。私はこの時点でほとんど第二の性質によってそれをする傾向があります。
functions.php
ファイルでインクルードファイルを使用するテーマディレクトリの下に"includes"というサブディレクトリを作成し、その時点で理にかなった方法で整理されたインクルードファイルにコードを分割します(つまり、常にコードをリファクタリングして移動します)また、functions.php
;に実際のコードを入れることはめったにありません。すべてがインクルードファイルに含まれます。ただ私の好み。
ここに例を示すために、ここの質問への回答をWordPress Answersでテストするために使用するテストインストールを示します。質問に答えるたびに、再び必要になったときに備えてコードを保持しています。これは実際のサイトで行うこととは異なりますが、コードを分割するメカニズムを示しています。
<?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');
別のオプションは、コードを機能ごとにグループ化して独自のプラグインを作成することです。私にとっては、テーマのfunctions.php
ファイルでコーディングを開始し、コードが完成するまでに、ほとんどのコードをプラグインに移動しました。
一方、PHPファイルの構造化は、順序と保守性の作成については99%、パフォーマンスについては1%です(HTTP経由でブラウザーによって呼び出される.js
および.css
ファイルの整理)ただし、サーバー上でPHPコードを整理する方法は、パフォーマンスの観点からは重要ではありません。
最後になりましたが、コードの構成は個人的な好みです。一部の人々は、私がコードを整理する方法を嫌うかもしれません。好きなものを見つけてそれを使い続けますが、学習するにつれて戦略が徐々に進化し、それに慣れることができます。
フォルダ内のファイルに関数を使うのが好きです。この方法では、新しいファイルを追加するときに新しい機能を簡単に追加できます。しかし、私は常にクラスで、または名前空間を使って書いています - 関数、メソッドなどの名前空間についてより多くの制御を与えます。
小さな例の下に。クラス* .phpについての同意を得て使用することもできません。
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;
}
テーマでは、私はしばしば他のシナリオを使います。 externelファイルの機能はサポートIDで定義します。例を見てください。外部ファイルの取得を簡単に無効にするのであれば、それは役に立ちます。私はWPコア関数require_if_theme_supports()
を使い、サポートIDがアクティブな場合にのみロードします。次の例では、ファイルをロードする前に、このサポートIDを行に定義しました。
/**
* 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'
);
あなたはこのテーマの レポ でこのことをもっと見ることができます。
分割するという点では、私の定型文では、私はカスタムディレクトリを使ってテーマディレクトリの中のfunctionsという名前のフォルダを探しています。次に、そのフォルダ内で見つかったすべての.phpファイルの配列(存在する場合)を作成し、include()を実行します。それぞれに。
こうすれば、新しい機能を書くたびにPHPファイルをfunctionsフォルダに追加するだけで済み、サイトにコーディングする必要はありません。
<?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);
}
}
}
ネットワークインストールを介して、さまざまな言語で約50種類のカスタムページタイプを使用してサイトを管理しています。プラグインのトンと一緒に。
我々はどこかでそれを全部分割することを余儀なくされた。 20〜30k行のコードを持つfunctionsファイルはまったく面白くありません。
コードベースをよりよく管理するために、すべてのコードを完全にリファクタリングすることにしました。デフォルトのワードプレスのテーマ構造は小さなサイトには適していますが、大きなサイトには適していません。
私たちの新しいfunctions.phpはサイトを開始するのに必要なものだけを含んでいますが、特定のページに属するものは何も含んでいません。
現在使用しているテーマレイアウトはMCVデザインパターンと似ていますが、手続き型コーディングスタイルです。
例えば、私たちの メンバーページ:
page-member.php 。ページの初期化を担当します。正しいajax関数などを呼び出す。 MCVスタイルのコントローラー部分と同等の可能性があります。
functions-member.php 。このページに関連するすべての機能が含まれています。これは私達のメンバーのために機能を必要とするいくつかの他のページにも含まれています。
content-member.php 。 HTML用のデータを準備するMCVのモデルと同等の可能性があります。
layout-member.php 。 HTML部分.
これらの変更を行った後、開発時間は50%簡単に短縮され、今では製品所有者は私たちに新しいタスクを提供するのに苦労しています。 :)
子テーマのfunctions.phpファイルから:
require_once( get_stylesheet_directory() . '/inc/custom.php' );
Functions.phpでは、必要なファイルを呼び出すためのよりエレガントな方法は次のようになります。
require_once locate_template( '/ inc/functions/shortcodes.php');
@kaiser と @mikeschinkel の回答を組み合わせました。
私のテーマに対するカスタマイズはすべて/includes
フォルダーにあり、そのフォルダー内にすべてのサブフォルダーがあります。
true === is_admin()
のときだけ/includes/admin
とそのサブコンテンツを含めるようにしたい
false
を返してフォルダがiterator_check_traversal_callback
から除外された場合、そのサブディレクトリは反復されません(またはiterator_check_traversal_callback
に渡されます)。
/**
* 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();
}