Code in der Datei functions.php Ihres WordPress-Themes organisieren?
8 Antworten
- Stimmen
-
- 2010-09-06
Wenn Sie aneinem Punkt angelangt sind,an dem der Codein der
functions.php
Ihres Themas Sie zu überwältigenbeginnt,würdeich definitiv sagen,dass Siebereit sind,ihnin mehrere Dateien aufzuteilen. Ichneige dazu,dies an dieser Stellefast von Natur aus zutun.Verwenden Sie Include-Dateienin der
Ihres Themasfunctions.php
-DateiIcherstelleein Unterverzeichnismit dem Namen "include" untermeinem Themenverzeichnis und segmentieremeinen Codein Include-Dateien,dienach demgeordnet sind,wasfürmich zu diesem Zeitpunkt sinnvollist (wasbedeutet,dassich ständig Code umgestalte und verschiebe während sicheine Siteentwickelt.) Ich habe auch seltenechten Codein
functions.php
eingefügt; allesgehtin die Include-Dateien;nurmeine Präferenz.Um Ihnennurein Beispiel zugeben,hieristmeine Testinstallation,mit derichmeine Antworten auf Fragen hierin WordPress Answersteste. Jedes Mal,wennicheine Fragebeantworte,behalteich den Codefür den Fall,dassichihnerneutbenötige. Diesistnichtgenau das,was Siefüreine Live-Sitetun,aberes zeigt die Mechanismen der Aufteilung des Codes:
<?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');
Oder Pluginserstellen
Eine weitere Option,um den Codenach Funktionen zugruppieren undeigene Plugins zuerstellen. Fürmichbeginne ichmit dem Codierenin der Datei
functions.php
des Themas undbisich den Code konkretisiert habe,habeich dengrößten Teilmeines Codesin Plugins verschoben.Jedoch KEIN signifikanter Leistungsgewinn durch PHP-Code-Organisation
Bei der Strukturierung Ihrer PHP-Dateiengehtes dagegen zu 99% um die Schaffung von Ordnung und Wartbarkeit und zu 1% um die Leistung,wenn dies der Fallist (Organisation der aufgerufenen
.js
- und.css
-Dateien vom Browser über HTTPistein völlig anderer Fall und hatenorme Auswirkungen auf die Leistung.) Aber wie Sie Ihren PHP-Code auf dem Server organisieren,spielt aus Sicht der Leistung keine Rolle.Und Code-Organisationistpersönliche Präferenz
Undnicht zuletztist die Organisation des Codeseine persönliche Präferenz. Einige Leute würdenes hassen,wieich Code organisiere,genauso wieiches hassen könnte,wie siees auchtun. Finden Sieetwas,das Ihnengefällt,undbleiben Sie dabei,aber lassen Sie Ihre Strategie sichim Laufe der Zeit weiterentwickeln,wenn Siemehr lernen und sich damit vertrautmachen.
If you are getting to the point where the code in your theme's
functions.php
is starting to overwhelm you I would definitely say you are ready to consider splitting it up into multiple files. I tend to do that almost by second nature at this point.Use Include Files in your Theme's
functions.php
FileI create a subdirectory called "includes" under my theme directory and segment my code into include files organized by what makes sense to me at the time (which means I'm constantly refactoring and moving code around as a site evolves.) I also rarely put any real code in
functions.php
; everything goes in the include files; just my preference.Just to give you an example here's my test install that I use to test my answers to questions here on WordPress Answers. Every time I answer a question I keep the code around in case I need it again. This isn't exactly what you'll do for a live site but it shows the mechanics of splitting up the code:
<?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');
Or Create Plugins
Another option it to start grouping your code by function and create your own plugins. For me I start coding in the theme's
functions.php
file and by the time I get the code fleshed out I've moved most of my code into plugins.However NO Significant Performance Gain From PHP Code Organization
On the other hand structuring your PHP files is 99% about creating order and maintainability and 1% about performance, if that (organizing
.js
and.css
files called by the browser via HTTP is a completely different case and has huge performance implications.) But how you organize your PHP code on the server pretty much doesn't matter from a performance perspective.And Code Organization is Personal Preference
And last but not least code organization is personal preference. Some people would hate how I organize code just as I might hate how they do it too. Find something you like and stick with it, but allow your strategy to evolve over time as you learn more and get more comfortable with it.
-
Schöne Antwort,ichbin gerade an diesem Punkt angekommen,an demich die Funktionsdateiteilenmuss.Wannistes Ihrer Meinungnachpraktisch,vonfrunctions.php zueinem Plugin zu wechseln?Sie sagtenin Ihrer Antwort: Bisich den Code konkretisiert habe,habeich dengrößten Teilmeines Codesin Plugins verschoben.Ich verstehe dasnichtganz,wasmeinst dumit konkretisiert?Nice answer, I just arrived to this point where i need to split the functions file. When do you think it's handy to move from frunctions.php to a plugin. You said in your answer: _by the time I get the code fleshed out I've moved most of my code into plugins_. I do not understand that fully, what do you mean with fleshed out.
- 0
- 2011-08-16
- Saif Bechan
-
+1für "oder Pluginserstellen".Genauergesagt "[Funktions-Plugins] (http://www.doitwithwp.com/create-functions-plugin/)"+1 for "or create plugins". More specifically, "[functionality plugins](http://www.doitwithwp.com/create-functions-plugin/)"
- 5
- 2012-04-18
- Ian Dunn
-
Die Verwendung relativer Pfadeistmöglicherweisenichtin allen Einstellungen zuverlässig. Stattdessen sollteimmer der absolute Pfad verwendet werdenusing relative paths might not be reliable in all kinds of settings, absolute path should always be used instead
- 3
- 2016-09-22
- Mark Kaplun
-
@ MarkKaplun - Dubist absolut korrekt.Seitich diese Antwortgeschrieben habe,habeich diese Lektion auf die harte Tourgelernt.Ich werdemeine Antwort aktualisieren.Vielen Dankfür den Hinweis.@MarkKaplun - You are **absolutely** correct. Since I wrote this answer I learned that lesson the hard way. I am going to update my answer. Thanks for pointing this out.
- 2
- 2016-09-23
- MikeSchinkel
-
Icherhalte "Verwendung der undefinierten Konstante __DIR__ - angenommen '__DIR__'in C: \ wamp \ www \ site \ wp-content \themes \mytheme \functions.php" - PHP v5.6.25 und PHP v7.0.10 - Ich kannnichtFormatiere dieses DIRim Kommentar richtig (underscoreunderscoreDIRunderscoreunderscore),aberesfunktioniertmit dirname (underscoreunderscoreFILEunderscoreunderscore)I get "Use of undefined constant __DIR__ - assumed '__DIR__' in C:\wamp\www\site\wp-content\themes\mytheme\functions.php" - PHP v5.6.25 and PHP v7.0.10 - I can't format properly this DIR in comment (underscoreunderscoreDIRunderscoreunderscore), but it works with dirname(underscoreunderscoreFILEunderscoreunderscore)
- 0
- 2016-11-01
- Marko
-
Achtung: Siemüssen "__DIR__" anstelle von "__DIR ___" verwenden,da sonstein interner Serverfehler (500) angezeigt wird.Caution: you'd need to use `__DIR__` instead of `__DIR___`, otherwise you'll be presented with an Internal Server Error (500).
- 0
- 2017-02-13
- robro
-
@robro - Ah,danke,dass du das verstanden hast!_ (Verdammte Tippfehler. Grrr ...) _ :-)@robro - Ah, thanks for catching that! _(Damn typos. Grrr...)_ :-)
- 0
- 2017-02-13
- MikeSchinkel
-
- 2012-10-13
Späte Antwort
Sofügen Sie Ihre Dateien richtigein:
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' );
Dasgleichefunktioniert auchin Plugins.
Soerhalten Sie den richtigen Pfad oder URi
Sehen Sie sich auch die API-Funktionen des Dateisystems an:
home_url()
plugin_dir_url()
plugin_dir_path()
admin_url()
-
get_template_directory()
get_template_directory_uri()
get_stylesheet_directory()
get_stylesheet_directory_uri()
- usw.
So reduzieren Sie die Anzahl von
include/require
Wenn Sie alle Dateien auseinem Verzeichnis abrufenmüssen,gehen Sie zu
foreach ( glob( 'path/to/folder/*.php' ) as $file ) include $file;
Beachten Sie,dass hierdurch Fehler (möglicherweisegutfür die Produktion)/nicht ladbare Dateienignoriert werden.
Um dieses Verhalten zu ändern,möchten Siemöglicherweise während der Entwicklungeine andere Konfiguration verwenden:
$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;
Bearbeiten: OOP/SPL-Ansatz
Alsichgerade zurückkam und sah,dass diese Antwortimmermehrpositive Stimmenerhält,dachteich,ich könnte zeigen,wieiches heutzutagemache -in einer PHP 5.3+ Welt. Imfolgenden Beispiel werden alle Dateien auseinem Themen-Unterordnermit dem Namen
src/
geladen. Hier habeichmeine Bibliotheken,diebestimmte Aufgaben wie Menüs,Bilder usw.erledigen. Siemüssen sichnichteinmal um den Namen kümmern,dajedeeinzelne Dateigeladen wird. Wenn Sie andere Unterordnerin diesem Verzeichnis haben,werden dieseignoriert.Der
\FilesystemIterator
ist der PHP 5.3+ -Supercedor über dem\DirectoryIterator
. Beide sind Teil der PHP SPL. Während PHP 5.2esermöglichte,dieeingebaute SPL-Erweiterung auszuschalten (weniger als 1% aller Installationen haben diesgetan),ist die SPLjetzt Teil des PHP-Kerns.<?php namespace Theme; $files = new \FilesystemIterator( __DIR__.'/src', \FilesystemIterator::SKIP_DOTS ); foreach ( $files as $file ) { /** @noinspection PhpIncludeInspection */ ! $files->isDir() and include $files->getRealPath(); }
Währendich PHP 5.2.xnoch unterstützte,habeich diefolgende Lösung verwendet: Ein
\FilterIterator
im Verzeichnissrc/Filters
,umnur Dateien (und keine Punkte) abzurufen Zeiger von Ordnern) undein\DirectoryIterator
zum Durchlaufen und Laden.namespace Theme; use Theme\Filters\IncludesFilter; $files = new IncludesFilter( new \DirectoryIterator( __DIR__.'/src' ) ); foreach ( $files as $file ) { include_once $files->current()->getRealPath(); }
Der
\FilterIterator
war soeinfach:<?php namespace Theme\Filters; class IncludesFilter extends \FilterIterator { public function accept() { return ! $this->current()->isDot() and $this->current()->isFile() and $this->current()->isReadable(); } }
Abgesehen davon,dass PHP 5.2inzwischentot/EOList (und auch 5.3),gibt es die Tatsache,dassesmehr Code undeine weitere Dateiim Spielgibt. Esgibt also keinen Grund,sichfür PHP 5.2.x zuentscheiden .
Zusammengefasst
BEARBEITEN Der offensichtlich richtige Wegist die Verwendung des Codes
namespace
d,derfür PSR-4 Autoloading,indem allesin dasentsprechende Verzeichnisgestellt wird,dasbereits über den Namespace definiertist. Verwenden Sie danneinfach Composer undeinencomposer.json
,um Ihre Abhängigkeiten zu verwalten und automatisch zu aktivieren. Erstellen Sie Ihren PHP-Autoloader (der automatischeine Dateiimportiert,indem Sieeinfachuse \<namespace>\ClassName
aufrufen). Diesist der De-facto-Standardin der PHP-Welt,dereinfachste Weg undnoch vorautomatisierter und vereinfachter durch WP Starter .Late answer
How to include your files the right way:
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' );
The same works in plugins too.
How to get the right path or URi
Also take a look at file system API functions like:
home_url()
plugin_dir_url()
plugin_dir_path()
admin_url()
get_template_directory()
get_template_directory_uri()
get_stylesheet_directory()
get_stylesheet_directory_uri()
- etc.
How to reduce the number of
include/require
If you need to fetch all files from a directory go with
foreach ( glob( 'path/to/folder/*.php' ) as $file ) include $file;
Keep in mind that this ignores failures (maybe good for production use)/not loadable files.
To alter this behavior you might want to use a different config during development:
$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;
Edit: OOP/SPL approach
As I just came back and saw that this answer is getting more and more upvotes, I thought I might show how I'm doing it nowadays - in a PHP 5.3+ world. The following example loads all files from a themes subfolder named
src/
. This is where I have my libraries that handle certain tasks like menus, images, etc. You don't even have to care about the name as every single file gets loaded. If you have other subfolders in this directory, they get ignored.The
\FilesystemIterator
is the PHP 5.3+ supercedor over the\DirectoryIterator
. Both are part of the PHP SPL. While PHP 5.2 made it possible to turn the built in SPL extension off (below 1% of all installs did that), the SPL now is part of PHP core.<?php namespace Theme; $files = new \FilesystemIterator( __DIR__.'/src', \FilesystemIterator::SKIP_DOTS ); foreach ( $files as $file ) { /** @noinspection PhpIncludeInspection */ ! $files->isDir() and include $files->getRealPath(); }
Previously while I still supported PHP 5.2.x, I used the following solution: A
\FilterIterator
in thesrc/Filters
directory to only retrieve files (and not dot pointers of folders) and a\DirectoryIterator
to do the looping and loading.namespace Theme; use Theme\Filters\IncludesFilter; $files = new IncludesFilter( new \DirectoryIterator( __DIR__.'/src' ) ); foreach ( $files as $file ) { include_once $files->current()->getRealPath(); }
The
\FilterIterator
was as easy as that:<?php namespace Theme\Filters; class IncludesFilter extends \FilterIterator { public function accept() { return ! $this->current()->isDot() and $this->current()->isFile() and $this->current()->isReadable(); } }
Aside from PHP 5.2 being dead/EOL by now (and 5.3 as well), there's the fact that it's more code and one more file in the game, so there's no reason to go with the later and support PHP 5.2.x.
Summed up
EDIT The obviously correct way is to use
namespace
d code, prepared for PSR-4 autoloading by putting everything in the appropriate directory that already is defined via the namespace. Then just use Composer and acomposer.json
to manage your dependencies and let it auto-build your PHP autoloader (that imports automatically a file by just callinguse \<namespace>\ClassName
). That's the de-facto standard in the PHP world, the easiest way to go and even more pre-automated and simplified by WP Starter. -
- 2012-10-04
Ich verwendegerneeine Funktionfür die Dateienin einem Ordner. Dieser Ansatzerleichtert das Hinzufügenneuer Funktionenbeim Hinzufügenneuer Dateien. Aberich schreibeimmerin der Klasse odermit Namespaces -geben Sieihmmehr Kontrolle über den Namespace von Funktionen,Methoden usw.
Untenein kleines Beispiel; ut auch Verwendungmit der Vereinbarung über die Klasse * .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; }
In Themen verwendeich oftein anderes Szenario. Ich definiere die Funktion derexternen Dateiin einer Support-ID,siehe Beispiel. Dasistnützlich,wennich die Funktion derexternen Dateieinfach deaktivierenmöchte. Ich verwende die WP-Kernfunktion
require_if_theme_supports()
under lädtnur,wenn die Support-ID aktiv war. Imfolgenden Beispiel habeich diese unterstützte IDin der Zeile vor dem Laden der Datei definiert./** * 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' );
Mehr davonfinden Sieim Repo dieses Themas .
I like to use a function to the files inside a folder. This approach makes it easy to add new features when adding new files. But I write always in class or with namespaces - give it more control about the Namespace of functions, method etc.
Below a small example; ut also useage with the agreement about the class*.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; }
In Themes I use often a other scenario. I define the function of the externel file in a support ID, see the example. That is usefull if I will easy deactivate the feture of the externel file. I use the WP core function
require_if_theme_supports()
and he load only, if the support ID was active. In the follow example I deifned this supported ID in the line before load the file./** * 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' );
You can see more of this in the repo of this theme.
-
- 2010-09-06
In Bezug auf das Aufteilen verwendeichin meiner Kesselplatteeine benutzerdefinierte Funktion,umim Themenverzeichnisnacheinem Ordnermit dem Namen "Funktionen" zu suchen. Wennernicht vorhandenist,wirdererstellt. Anschließend wirdein Array allerin diesem Ordnergefundenen .php-Dateienerstellt (falls vorhanden) undein include () ausgeführt. aufjedem vonihnen.
Auf diese Weisefügeichjedes Mal,wennichneue Funktionen schreibenmuss,einfacheine PHP-Datei zum Funktionsordner hinzu undmussmichnicht darum kümmern,siein die Site zu codieren.
<?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); } } }
in terms of breaking it up, in my boiler plate I use a custom function to look for a folder called functions in the theme directory, if it is not there it creates it. Then is creates an array of all the .php files it finds in that folder (if any) and runs an include(); on each of them.
That way, each time I need to write some new functionality, I just add a PHP file to the functions folder, and don't have to worry about coding it into the site.
<?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); } } }
-
* @mildfuzz *: Schöner Trick.Ichpersönlich würdeesnichtfür Produktionscode verwenden,daesfürjedes Ladeneiner Seite dastut,was wirbeim Starten der Site leichteinmaltun könnten.Außerdem würdeich aufirgendeine Weise hinzufügen,um Dateien wegzulassen,z. B.nichts zu laden,dasmit einem Unterstrichbeginnt,damitichnoch laufende Arbeitenim Themenverzeichnis speichern kann.Ansonsten schön!*@mildfuzz*: Nice trick. I personally wouldn't use it for production code because it does for every page load what we could easily do once when we launch the site. Also, I'd add in some way to omit files, like not loading anything starting with an underscore so I could still store works in progress in the theme directory. Otherwise, nice!
- 5
- 2010-09-06
- MikeSchinkel
-
Ich liebe die Idee,aberich stimme zu,dass diesmöglicherweise zu unnötigem Ladenfürjede Anfrageführen kann.Gibteseine Idee,obeseine einfache Möglichkeitgibt,dieendgültige Dateifunctions.php zugenerieren,die automatischmit einer Aktualisierung zwischengespeichert wird,wenn/wennneue Dateien hinzugefügt werden oderin einembestimmten Zeitintervall?love the idea but I agree this might possibly lead to unnecessary loading for each request. Any idea if there would be a simple way to have the final functions.php file being generated automatically cached with some type of update if/when new files are added or at a specific time interval?
- 0
- 2010-09-07
- NetConstructor.com
-
Schön,aberesführt zu Inflexibilitäten. Waspassiert auch,wennein Angreiferes schafft,seinen Code dort abzulegen?Und wasist,wenn die Bestellung von Includes wichtigist?Nice but it leads to inflexibilities, also what happens if an attacker manages to drop their code in there? And what if the ordering of includes is important?
- 0
- 2010-09-07
- Tom J Nowell
-
@MikeSchinkel Ich rufeeinfachmeine Arbeitsdateienfoo._php auf und lösche dann das _php,wennichmöchte,dasses ausgeführt wird.@MikeSchinkel I just call my working files foo._php, then drop the _php when I want it to run.
- 1
- 2010-09-10
- Mild Fuzz
-
@ NetConstructor: Würdemich auchfüreine Lösunginteressieren.@NetConstructor: Would be interested in some sollution too.
- 0
- 2011-02-01
- kaiser
-
@kaiser,ichnehme an,Sie könnten diesmit Cron-Skriptentun,dieeine Funktion ausführen,die die obige Ordnersuche ausführt,aber die Ergebnissein eine DB/Textdatei schreibt und dann die Lasten auf dieser Funktionbasiert.Dies könntemöglicherweise auch dazuführen,dass unfertige Arbeitenin die Ladunggelangen.@kaiser, I suppose you could do it with cron scripts running a function that run's the above folder search but writes the results to a DB/textfile, then bases the loads on that function. This could potentially lead to unfinished work going into the load also.
- 0
- 2011-02-01
- Mild Fuzz
-
@MildFuzz: Mike hatmichnur auf die Transienten-API hingewiesen.Vielleicht könnte das Teileiner Art Lösung werden ...@MildFuzz: Mike just pointed me at the transients API. Maybe that could get part of some sort of sollution...
- 0
- 2011-02-01
- kaiser
-
basierend auf der von @mildfuzzbeschriebenen Lösung - wasist Ihrer Meinungnach diebeste Methode,um Dateien oder Ordner (undihre Unterdateien/Ordner) automatisch von der Aufnahmein seinen Auto-Include-Ansatz auszuschließen?Mein Gedanke wäre,den Unterstrich als Präfix zu verwenden.Welcher richtige Code wäre derbeste Ansatz,um solche Funktioneneinzuschließen?based on the solution outlined by @mildfuzz - what do you guys believe to be the best method to automatically exclude any file or folder (and its subfiles/folders) from being included within his auto-include approach? My thought would be to use the underscore approach as a prefix. What proper code would be the best approach to include such capabilities?
- 0
- 2012-10-10
- NetConstructor.com
-
Siemüssennur "if (! strpos ($ value,'.php'))" ändern,um das von Ihnengewählte Systemeinzuschließen.you just need to change `if (!strpos($value, '.php'))` to include whatever system you choose.
- 0
- 2012-10-10
- Mild Fuzz
-
- 2012-10-04
Ich verwalteeine Sitemit ungefähr 50eindeutigenbenutzerdefinierten Seitentypenin mehreren verschiedenen Sprachen übereine Netzwerkinstallation. Zusammenmit einer TONNE Plugins.
Wir warengezwungen,allesirgendwann aufzuteilen. Eine Funktionsdateimit 20-30.000 Codezeilenist überhauptnicht lustig.
Wir haben unsentschlossen,dengesamten Code vollständig zu überarbeiten,um die Codebasisbesser verwalten zu können. Die Standardstrukturfür WordPress-Themeneignet sichfür kleine Websites,jedochnichtfürgrößere Websites.
Unsereneuefunctions.phpenthältnur das,was zum Starten der Siteerforderlichist,abernichts,was zueinerbestimmten Seitegehört.
Dasjetzt verwendete Themenlayout ähnelt dem MCV-Entwurfsmuster,jedochin einemprozeduralen Codierungsstil.
Zum Beispiel unsere Mitgliederseite:
page-member.php . Verantwortlichfür die Initialisierung der Seite. Aufrufen der richtigen Ajax-Funktionen oder ähnliches. Könnte dem Controller-Teilim MCV-Stilentsprechen.
functions-member.php . Enthält alle Funktionen dieser Seite. Diesist auch aufmehreren anderen Seitenenthalten,die Funktionenfür unsere Mitgliederbenötigen.
content-member.php . Bereitet die Datenfür HTML vor. Entsprichtmöglicherweise dem Modellin MCV.
layout-member.php . Der HTML-Teil.
Nachdem wir diese Änderungen vorgenommen haben,ist die Entwicklungszeit leicht um 50%gesunken,undjetzt hat der Product Owner Probleme,unsneue Aufgaben zugeben. :)
I manage a site with about 50 unique custom page types in serveral different languages over a network installation. Along with a TON of plugins.
We where forced to split it all up at some point. A functions file with 20-30k lines of code is not funny at all.
We decided to completley refactor all code in order to manage the codebase better. The default wordpress theme structure is good for small sites, but not for bigger sites.
Our new functions.php only contains what is necessary to start the site, but nothing which belongs to a specific page.
The theme layout we use now is similar to the MCV design pattern, but in a procedural coding style.
For example our member page:
page-member.php. Responsible for initializing the page. Calling the correct ajax functions or similar. Could be equivialent to the Controller part in the MCV style.
functions-member.php. Contains all functions related to this page. This is also included in serveral other pages which need functions for our members.
content-member.php. Prepares the data for HTML Could be equivialent to the Model in MCV.
layout-member.php. The HTML part.
Efter we did these changes the development time have easily dropped by 50% and now the product owner have trouble giving us new tasks. :)
-
Um dies hilfreicher zugestalten,sollten Sie zeigen,wie dieses MVC-Muster wirklichfunktioniert.To make this more helpful you might consider showing how this MVC pattern really works.
- 7
- 2012-10-05
- kaiser
-
Ich wäre auchneugierig,ein Beispielfür Ihren Ansatz zu sehen,vorzugsweisemit einigen Details/verschiedenen Situationen.Der Ansatz klingt sehrinteressant.Haben Sie die Serverlast/-leistungmit der Standardmethode verglichen,die andere verwenden?Geben Sienach Möglichkeitein Github-Beispiel an.i would also be currious to see an example of your approach, preferably with some details/various situations. The approach sounds very interresting. Have you compared server load/performance with the standard methodology others use? do provide a github example if at all possible.
- 0
- 2012-10-10
- NetConstructor.com
-
- 2013-10-20
Aus der Dateifunctions.php der untergeordneten Themen:
require_once( get_stylesheet_directory() . '/inc/custom.php' );
From child themes functions.php file:
require_once( get_stylesheet_directory() . '/inc/custom.php' );
-
- 2012-10-04
Infunctions.php wäreeine elegantere Möglichkeit,eine erforderliche Datei aufzurufen:
require_once location_template ('/inc/functions/shortcodes.php');
In functions.php, a more elegant way to call a required file would be:
require_once locate_template('/inc/functions/shortcodes.php');
-
[`locate_template ()`] (http://codex.wordpress.org/Function_Reference/locate_template) hateinen dritten Parameter…[`locate_template()`](http://codex.wordpress.org/Function_Reference/locate_template) has a third parameter …
- 4
- 2012-10-04
- fuxia
-
- 2018-08-19
Ich habe @kaiser und @mikeschinkel Antworten.
Ich habe allemeine Anpassungen anmeinem Themain einem
/includes
-Ordner undin diesem Ordner habeich allesin Unterordner aufgeteilt.Ichmöchtenur,dass
/includes/admin
und seine Unterinhalteeingeschlossen werden,wenntrue === is_admin()
Wennein Ordnerin
iterator_check_traversal_callback
durch Rückgabe vonfalse
ausgeschlossen wird,werden seine Unterverzeichnissenichtiteriert (oder aniterator_check_traversal_callback
übergeben)/p>/** * 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(); }
I combined @kaiser's and @mikeschinkel's answers.
I have all my customizations to my theme in a
/includes
folder and within that folder I have everything broken out into sub folders.I only want
/includes/admin
and its sub-contents to be included whentrue === is_admin()
If a folder is excluded in
iterator_check_traversal_callback
by returningfalse
then its sub-directories will not be iterated (or passed toiterator_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(); }
Jemehr Anpassungenich an WordPress vornehme,destomehr denkeich darübernach,obich diese Datei organisieren oder aufteilen soll.
Wennicheine Reihe vonbenutzerdefinierten Funktionen habe,dienurfür den Admin-Bereichgelten,und andere,dienurfürmeine öffentliche Websitegelten,gibt eseinen Grund,möglicherweise alle Admin-Funktionenin ihreeigene Datei aufzunehmen oder sie zugruppieren?
Würde das Aufteilenin separate Dateien oder das Gruppieren diesemöglicherweiseeine WordPress-Websitebeschleunigen oder überspringt WordPress/PHP automatisch Funktionenmit einemis_admin-Codepräfix?
Wasist derbeste Weg,ummit einergroßen Funktionsdatei umzugehen (meineist 1370 Zeilen lang).