Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to embed Symfony2 actions into WordPress?

I've been researching it a lot and trying it out but I'm kind of stumped.

I want to setup a site in WordPress, which is helpful for another guy working with me. The site will advertise our product and provide information. Then users can sign up through a series of forms. I want to write this custom part (forms, etc.) in Symfony2 because it has no need to be tied to WordPress, and it would have reusable Doctrine2 entities to display the data after a user has signed up (displaying happens outside of WordPress anyway).

But, design-wise, we would like the whole process to be uninterrupted and have the same look-and-feel. So the forms should actually be rendered in WordPress pages. We are using a custom, non-free theme and I'd hate to just copy-paste a bunch of WordPress CSS and headers into Symfony views.

Ideally, I want to just define pages in WordPress which can render Symfony2 actions. So the actions themselves might display and process forms (which should work independently of WordPress say at http://example.com/app.php/signup), but they should normally be displayed in the WordPress site (for example within a page like http://example.com/index.php?page_id=2 or a permalink).

I have been researching LowPress as a way to integrate (http://www.lowpress.com/), but it does way more than I want by removing the WordPress themes altogether and replacing them with Twig themes. I tried to borrow a few ideas from it, so now I have WordPress in the web folder of the Symfony project and this in my wp-config.php:

// ...code omitted
define('WP_DEBUG', true);

define('SYMFONY_DIR', __DIR__.'/../app/');

require_once SYMFONY_DIR.'/bootstrap.php.cache';
require_once SYMFONY_DIR.'/AppKernel.php';
//require_once SYMFONY_DIR.'/AppCache.php';

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\Request;

$kernel = new AppKernel((WP_DEBUG) ? 'dev' : 'prod', WP_DEBUG);
$kernel->loadClassCache();
$kernel->boot();
$GLOBALS['sf2_kernel'] = $kernel;
// save request before WordPress messes with it
$GLOBALS['sf2_request'] = Request::createFromGlobals();

$doctrine = $kernel->getContainer()->get('doctrine');
$conn = $doctrine->getConnection($doctrine->getDefaultConnectionName());

// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME',       $conn->getDatabase());

/** MySQL database username */
define('DB_USER',       $conn->getUsername());

/** MySQL database password */
define('DB_PASSWORD',   $conn->getPassword());

/** MySQL hostname */
define('DB_HOST',       $conn->getHost());

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');

// ...code omitted

So all I've got now is a shared DB config via parameters.ini in Symfony. Next I've been trying to make a simple plugin which uses a shortcode so I can render a Symfony2 action in a WordPress page. Here is what I have so far as an idea (it is dependent upon the above bootstrapping and it's incomplete):

use Symfony\Component\HttpFoundation\Request;

class Symfony2Page
{
    public function render($atts)
    {
        extract(shortcode_atts(array(
            'controller' => 'CroltsMainBundle:Default:index',
        ), $atts));
        $kernel = $GLOBALS['sf2_kernel'];
        $request = $GLOBALS['sf2_request'];
        $request->headers->set('X-Php-Ob-Level', ob_get_level());
        $attributes = array();
        // @TODO fix this

        $kernel->getContainer()->enterScope('request');
        $kernel->getContainer()->set('request', $request, 'request');

        try {
            $response = $kernel->getContainer()->get('http_kernel')->render($controller, $attributes)->getContent();
        } catch (\Exception $e) {
            $kernel->getContainer()->leaveScope('request');

            throw $e;
        }

        $kernel->getContainer()->leaveScope('request');

        return $response;
    }
}

add_shortcode('sf_action', array('Symfony2Page', 'render'));

My first problem is I don't know how to actually render some Symfony2 route, which may have parameters, when the given $request won't have the information I need. The other problem is, if I want forms to submit, it probably wouldn't work because it would redirect the user outside of WordPress, when really I may want a series of forms which all exist in the WordPress page. At the same time, I want the forms to be independent of WordPress so they work on their own.

So I want to know if this is just a bad/hacky idea which won't work, or if there is some way to get it working.

I was also thinking of just using AJAX to load the Symfony2 code in WordPress (assuming that all of my users have Javascript enabled). As a fallback, the page could just go to a Symfony2-only app rather than being within a WordPress page. Would that be better/easier? The only downside I can see is that I have to keep the ajax code in sync with my Symfony2 code.

like image 767
Matt Avatar asked Jun 01 '12 01:06

Matt


1 Answers

As you don't want to "..just copy-paste a bunch of WordPress CSS and headers into Symfony views", I suggest you embed the WordPress header and footer to all you Symfony views programmatically.

Also take a look at Silex as this has lower overhead than Symfony and works with Symfony forms.

  1. Install Symfony2, or Silex
  2. Put the WordPress files in your web/ folder
  3. wp-config.php can live one folder up next to composer.json, which is better for security anyway
  4. Move your Symfony, or Silex, front controller/s to a sub-folder, probably named signup/ in your case
  5. Fix the require / include paths at the top of your front controller/s
  6. Add a line at the top of your front controller/s to include wp-load.php from the parent folder - this file fires up WordPress and makes all the WordPress functions available to you - note it has to be included from the global scope not from inside a function
  7. Call the WordPress methods get_header(); and get_footer(); above the and below the Symfony, or Silex, code in your front controller/s. In Silex that's just above and below $app->run();

Your file structure should look like this:

vendor/
  |-- Third party libraries 
web/
  |-- WordPress files
  |-- signup/
       |-- Symfony2 or Silex front controller
composer.json
wp-config.php

Inspired by this post.

like image 106
matthew Avatar answered Nov 04 '22 12:11

matthew