【问题标题】:The role of "functions.php" in a WordPress site“functions.php”在 WordPress 网站中的作用
【发布时间】:2015-07-15 16:17:39
【问题描述】:

据我了解,在开发主题时,functions.php 会包含在每个 WordPress 页面中,并且应该包含所有主题逻辑。 Wordpress 主题没有真正的“安装”,所以如果它使用一个名为my_theme_table 的表,那么functions.php 中的一段逻辑可能是

if (my_theme_table is not in db) create my_theme_table;

我查看了我下载的主题的 functions.php,它有超过 6,000 行。每次加载页面时都要读取“安装逻辑”、类定义等,这不是非常低效吗?

有人可以帮我解决这个问题吗?我来自 ASP.NET 背景,这看起来很奇怪。

【问题讨论】:

  • 欢迎使用 Wordpress。它一团糟,不应该被视为 PHP 的一个很好的例子

标签: php wordpress


【解决方案1】:

据我了解,在开发主题时,functions.php 会包含在每个 WordPress 页面中,并且应该包含所有主题逻辑。

主题的函数文件包含在每个请求中,但它不应包含所有主题的逻辑。如何组织主题的非模板文件取决于您,但您应该避免尝试将所有代码都塞进函数文件中。

我查看了我下载的主题的functions.php,它有超过 6,000 行。

不幸的是,对于主题开发人员来说,将所有代码转储到函数文件中并将其变成一场大的程序噩梦是很常见的。不要以此作为应该如何做事的例子。

像组织其他项目一样组织您的主题文件。我个人喜欢在开发主题时坚持PSR standards。我的函数文件通常只包含一些常量,一个PSR-4 autoloader 和一个初始化。例如:

// Const
define('MYPROJECT_VERSION', '1.0.3');
define('MYPROJECT_BUILD', 169);

// Autoloader (PSR-4)
// Adapted from https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
spl_autoload_register(function ($class) {
    // Project namespace
    $prefix = 'MyProject\\';

    // Base directory for the namespace prefix
    $base_dir = __DIR__ . '/core/';

    // Does the class use the namespace prefix
    $len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        return;
    }

    // Get the relative class name
    $relative_class = substr($class, $len);

    // Replace the namespace prefix with the base directory, replace namespace
    // separators with directory separators in the relative class name, append
    // with .php
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';

    // If the file exists, require it
    if (file_exists($file)) {
        /** @noinspection PhpIncludeInspection */
        require $file;
    }
});

// Initialize
\MyProject\MyTheme::init();

// End of file

每次加载页面时都要读取“安装逻辑”、类定义等,这不是非常低效吗?

如果您使用自动加载器,则只会包含您使用的类。如果您担心 PHP 通常需要在每个请求上解析源文件,请查看 OPCache

关于“安装逻辑”,可以分别使用after_switch_themesswitch_themes钩子进行安装和卸载。

add_action('after_switch_theme', function() {
    // Install
});

add_action('switch_theme', function() {
    // Uninstall
});

【讨论】:

  • 如果您正在创建一个小型个人作品集网站,那么您真的不需要一些复杂的文件结构文件,对吧?
  • @dingo_d 项目会随着时间的推移而变化和增长。如果你花时间计划和组织你的代码,从长远来看,你最终会得到一些不那么复杂的东西。一旦您了解了标准以及如何应用它,设置起来就不是那么难了,即使对于一个小项目也是如此。
【解决方案2】:

答案与 Wordpress 或 functions.php 无关,而与 PHP 本身有关。每次都包含该文件,但在典型环境中,它只会在重新启动后被读取和编译一次,然后使用字节码缓存进行缓存。由于 PHP5.5 Zend Opimizer 是 PHP 的一部分,在此之前 APC 是一个非常常见的工具。

所以剩下的唯一问题就是每次执行的代码。

【讨论】:

    【解决方案3】:

    functions.php 包含在 wordpress 上挂钩的函数 - 它不应该包含任何类定义(这应该在自定义插件中完成)。从 MVC 的角度来看,我们可以说 functions.php 是将模板(视图)与模型(Wordpress Core、自定义插件)链接起来的控制器。

    一些阅读:https://codex.wordpress.org/Functions_File_Explained

    【讨论】:

      【解决方案4】:

      使用 WordPress 的条件标签、全局变量、定义、类检查等。比如像这样:

      <?php
      // load helper functions - always
      require_once get_stylesheet_directory() . '/inc/helper-functions.php';
      
      // load admin functions - for back-end only
      if ( is_admin() )
      require_once get_stylesheet_directory() . '/inc/admin-functions.php';
      
      // load WooCommerce functions - when WooCommerce is active
      if ( in_array(
      'woocommerce/woocommerce.php',
      apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) )
      )
      require_once get_stylesheet_directory() . '/inc/woocommerce-functions.php';
      
      // load SomeClass' functions - when class SomeClass is known
      if ( class_exists( 'SomeClass' ) )
      require_once get_stylesheet_directory() . '/inc/someclass-functions.php';
      
      // load debug functions - when debugging
      if ( defined( 'WP_DEBUG' ) && WP_DEBUG )
      require_once get_stylesheet_directory() . '/inc/debug-functions.php';
      

      您还可以在满足某些功能内的某些条件时退出:

      add_action( 'wp_enqueue_scripts', 'wpdev_143439_enqueue_scripts' );
      
      function wpdev_143439_enqueue_scripts() {
      
      if (
          ! is_single()
          || is_singular( 'my_cpt' )
          || (
              defined( 'NEVERSCRIPT' )
              && NEVERSCRIPT
          )
      ) {
          return;
      }
      
      // Enqueue some scripts here
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-19
        • 2015-02-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多