behappy/wordpress-bundle

用于将Symfony与Wordpress链接的Symfony扩展包

1.2.1 2017-03-08 16:44 UTC

This package is not auto-updated.

Last update: 2024-09-20 03:24:25 UTC


README

Build Status SensioLabsInsight

此扩展包用于将一些Symfony服务引入Wordpress,并使用Symfony操作Wordpress。

以下是功能列表:

  • 在Wordpress中使用自定义的Symfony服务
  • 使用Symfony操作Wordpress数据库
  • 从Wordpress创建自定义的Symfony路由
  • 在Wordpress上认证后,在Symfony上也进行认证,并正确分配用户角色。(需要ekino-wordpress-symfony Wordpress插件)
  • 捕获一些Wordpress钩子,通过Symfony EventDispatcher分发 (需要ekino-wordpress-symfony Wordpress插件)

安装

本安装教程的目的是让WordPress通过web根目录渲染,采用以下架构:

project
|-- wordpress (web root)
|-- symfony (not available over HTTP)

1) 安装Symfony和WordPress

wordpress目录中安装你的Wordpress项目,通过解压缩来自https://www.wordpress.org的最新WordPress源代码。在symfony目录中使用composer(例如,或新的Symfony Installer工具)安装Symfony。

$ php composer.phar create-project symfony/framework-standard-edition symfony/

2) 将ekino/wordpress-bundle安装到Symfony的项目中

编辑symfony/composer.json文件以添加此扩展包包

"require": {
    ...
    "ekino/wordpress-bundle": "dev-master"
},

运行php composer.phar update ekino/wordpress-bundle

然后,将扩展包添加到symfony/app/AppKernel.php

<?php
    public function registerBundles()
    {
        $bundles = array(
            ...
            new Ekino\WordpressBundle\EkinoWordpressBundle(),
        );

        ...

        return $bundles;
    }

将WordpressBundle路由文件添加到你的symfony/app/config/routing.yml中,在你的自定义路由之后,以捕获所有Wordpress路由

...
ekino_wordpress:
    resource: "@EkinoWordpressBundle/Resources/config/routing.xml"

编辑你的配置,并在你的app/config.yml中指定以下选项

ekino_wordpress:
    globals: # If you have some custom global variables that WordPress needs
        - wp_global_variable_1
        - wp_global_variable_2
    table_prefix: "wp_" # If you have a specific Wordpress table prefix
    wordpress_directory: "%kernel.root_dir%/../../wordpress"
    load_twig_extension: true # If you want to enable native WordPress functions (ie : get_option() => wp_get_option())
    enable_wordpress_listener: false # If you want to disable the WordPress request listener
    security:
        firewall_name: "secured_area" # This is the firewall default name
        login_url: "/wp-login.php" # Absolute URL to the wordpress login page

如果你想要使用UserHook在Symfony上进行认证,你应该将此配置添加到你的symfony/app/security.yml

security:
    providers:
        main:
            entity: { class: Ekino\WordpressBundle\Entity\User, property: login }

    # Example firewall for an area within a Symfony application protected by a WordPress login
    firewalls:
        secured_area:
            pattern:    ^/admin
            access_denied_handler: ekino.wordpress.security.entry_point
            entry_point: ekino.wordpress.security.entry_point
            anonymous: ~

    access_control:
        - { path: ^/admin, roles: ROLE_WP_ADMINISTRATOR }

3) 更新你的WordPress index.php文件以加载Symfony库

<?php

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Debug\Debug;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Retrieves or sets the Symfony Dependency Injection container
 *
 * @param ContainerInterface|string $id
 *
 * @return mixed
 */
function symfony($id)
{
    static $container;

    if ($id instanceof ContainerInterface) {
        $container = $id;
        return;
    }

    return $container->get($id);
}

$loader = require_once __DIR__.'/../symfony/var/bootstrap.php.cache';

// Load application kernel
require_once __DIR__.'/../symfony/app/AppKernel.php';

$sfKernel = new AppKernel('dev', true);
$sfKernel->loadClassCache();
$sfKernel->boot();

// Add Symfony container as a global variable to be used in Wordpress
$sfContainer = $sfKernel->getContainer();

if (true === $sfContainer->getParameter('kernel.debug', false)) {
    Debug::enable();
}

symfony($sfContainer);

$sfRequest = Request::createFromGlobals();
$sfResponse = $sfKernel->handle($sfRequest);
$sfResponse->send();

$sfKernel->terminate($sfRequest, $sfResponse);

4) 如果只暴露Symfony

为了避免与某些Wordpress插件的问题,你需要将web/app.php代码包装在一个函数中,如下所示

<?php
use Symfony\Component\HttpFoundation\Request;

// change for app_dev.php
function run(){
    $loader = require_once __DIR__.'/../var/bootstrap.php.cache';

    require_once __DIR__.'/../app/AppKernel.php';

    $kernel = new AppKernel('dev', true);
    $kernel->loadClassCache();
    Request::enableHttpMethodParameterOverride();
    $request = Request::createFromGlobals();
    $response = $kernel->handle($request);
    $response->send();
    $kernel->terminate($request, $response);
}
run();

5) 编辑WordPress根项目目录的 .htaccess 文件

放置以下规则

DirectoryIndex index.php

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^index\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule .? - [L]

    # Rewrite all other queries to the front controller.
    RewriteRule .? %{ENV:BASE}/index.php [L]
</IfModule>

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        RedirectMatch 302 ^/$ /index.php/
    </IfModule>
</IfModule>

现在你可以开始了。

在Symfony中使用

你可以通过调用以下服务在Symfony中调用Wordpress表管理器

因此,在自定义的Symfony控制器中,你可以创建/更新/删除Wordpress数据库中的数据,如下所示

# Here an example that sets user #2 as author for post #1
$postManager = $this->get('ekino.wordpress.manager.post');
$userManager = $this->get('ekino.wordpress.manager.user');

$user = $userManager->find(2);

$post = $postManager->find(1);
$post->setAuthor($user);

$postManager->save($post);

在WordPress中使用

从Symfony容器中调用服务

简单地使用symfony()方法并按如下方式调用你的自定义服务

$service = symfony('my.custom.symfony.service');

覆盖

实体

对于每个Wordpress实体,你都可以覆盖默认类。要这样做,只需在你的config.yml中添加以下配置(针对Post实体)

ekino_wordpress:
    services:
        post:
            class: MyApp\AppBundle\Entity\Post

为了在创建新实例时避免进一步的问题(例如),请记住始终使用管理器来创建新实体($container->get('ekino.wordpress.manager.post')->create())。

管理器

你还可以使用自己的管理器。要自定义它,将你的管理器注册为服务 - 应该标记为私有 - 如下所示

ekino_wordpress:
    services:
        comment:
            manager: my_custom_comment_service

现在,你可以通过通常的命令访问你的管理器,即从控制器:$this->get('ekino.wordpress.manager.comment')

仓库

实现你的自定义仓库类就像以下这样

ekino_wordpress:
    services:
        comment_meta:
            repository_class: MyApp\MyBundle\Repository\ORM\CustomCommentMetaRepository

额外

启用跨应用程序I18n支持

如果您已经有了用于处理 I18n 的 WordPress 插件,EkinoWordpressBundle 允许在 Symfony 和 WordPress 之间持久保存语言切换。要做到这一点,只需从 WordPress 插件中获取 cookie 名称,并在配置中提供其名称,如下所示

ekino_wordpress:
    i18n_cookie_name: pll_language # This value is the one used in "polylang" WP plugin

此外,您可以在 Symfony 中实现自己的跨应用语言切换器。例如

<?php

namespace Acme\DemoBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;

class LanguageController extends Controller
{
    /**
     * @param Request $request
     * @param string $locale
     *
     * @return RedirectResponse
     */
    public function toggleLocaleAction(Request $request, $locale)
    {
        $response = new RedirectResponse($this->generateUrl('homepage'));
        $response->headers->setCookie(new Cookie($this->getWpCookieName(), $locale, time() + 31536000, '/', $request->getHost()));

        return $response;
    }

    /**
     * @return string
     */
    protected function getWpCookieName()
    {
        return $this->container->getParameter('ekino.wordpress.i18n_cookie_name');
    }
}

处理受密码保护的帖子

如果您使用受密码保护的帖子并且已经定义了自己的 COOKIEHASH 常量,您可以在 config.yml 文件中使用 cookie_hash 参数提供它。然后,您将能够使用行为与 post_password_required WordPress 函数完全相同的 wp_post_password_required twig 函数。

在 Symfony 的 Twig 渲染的路由中显示 WordPress 主题

您可以使用此 bundle 中提供的以下 Twig 函数,将 WordPress 的头部(如果有管理菜单栏,则包括它)、侧边栏和页脚显示在您的 Symfony 的 Twig 模板中

{{ wp_get_header() }}
{{ wp_get_sidebar() }}

<div id="main">
    Your Twig code comes here
</div>

{{ wp_get_footer() }}