mukadi/wordpress-bundle
A Symfony bundle that integrates WordPress into your application, letting you use WordPress core features and functions alongside Symfony. It streamlines bridging content, hooks, and templating so you can build hybrid apps without duplicating setup or fighting two frameworks.
Reality check first: this is a Symfony bundle, not a Laravel package — there's no service provider and it won't install into a Laravel app. Everything below assumes a Symfony host app; for a Laravel project the equivalent play is corcel/corcel or a hand-rolled repository over $wpdb. Concepts map roughly: bundle → package, auto-wired services → container bindings, Twig → Blade, Doctrine entities → Eloquent models, mukadi_wordpress.yaml → config/wordpress.php.
Minimal setup:
wp-config.php + database) somewhere the PHP process can read, e.g. public/wp or a sibling directory.composer require mukadi/wordpress-bundle, then register Mukadi\WordpressBundle\MukadiWordpressBundle::class => ['all' => true] in config/bundles.php.config/packages/mukadi_wordpress.yaml with at minimum the WordPress directory, the table prefix, and the Doctrine entity manager that points at the WordPress database. Check the repo README and Resources/config/ for the exact keys in your pinned version — the config surface is small and has shifted between releases.wp_posts, wp_postmeta, wp_users, wp_usermeta, wp_terms, wp_term_relationships, wp_term_taxonomy, wp_comments).Where to look first, in this order: the bundle's Entity/ directory (tells you which WP fields are actually exposed), Wordpress/Api (the wrapper around WP functions, service id mukadi_wordpress.api), then Resources/config for service ids and route definitions.
First use case: render the five latest posts on a Symfony page. Inject the API service into a controller and call its post query wrapper, or use the PostRepository with findBy([], ['date' => 'DESC'], 5). That single request exercises all four moving parts — WP bootstrap, DB connection, entity hydration, Twig output — so it's the fastest way to prove the integration works before you build on it.
Read through the WP API, write through the WP API. The Api service (verify the method list in Wordpress/Api.php for your version) exposes wrappers such as getPosts(), getPost(), getTerms(), getCurrentUser(), getOption(), applyFilters(), doAction(), and shortcode rendering. Going through these means WP's real query stack runs: visibility rules, password protection, sticky posts, pre_get_posts filters, plugin modifications. Doctrine repositories bypass all of that.
Use Doctrine for structure, not for behaviour. Entities and repositories are best for your own admin screens and dashboards — things like "list drafts by author with a join on usermeta", pagination via Pagerfanta, or exporting. Treat them as read-mostly projections of WP data. For writes, call wp_insert_post / update_post_meta through the API so revisions, caches, and save_post hooks stay consistent.
Keep the controller thin and hand plain data to the view. Hydrated Doctrine proxies and WP objects both serialize badly into Twig and leak persistence concerns into templates. Map to small arrays or DTOs in the controller.
Render content deliberately. Post content is raw HTML with unrendered shortcodes. Run do_shortcode() then wp_kses_post(), and only then |raw in Twig. Anything less is either broken output or an XSS bug.
Authentication. The bundle provides a WordPress-backed user provider (phpass-based) so a Symfony firewall can authenticate against wp_users. That's how you keep one login for both halves of the app. Gate Symfony routes on WP roles/capabilities rather than building a parallel permission model.
Decide the routing split on day one. Either WP owns /blog/* and Symfony owns the app, or Symfony is the single front controller and WP is purely a data source (WP_USE_THEMES off). Mixing them ad hoc produces rewrite-rule collisions that are miserable to debug. Write the split down.
Plugins and themes. Drop plugins into wp-content/plugins; they load with the WP bootstrap and their hooks fire. Themes usually shouldn't render — if Symfony owns the front end, disable theme loading.
Bridging hooks to Symfony. WP's add_action/apply_filters and Symfony's EventDispatcher are separate systems. Where you need one to trigger the other, write an explicit small adapter service rather than sprinkling add_action calls in controllers.
wordpress_url mismatches silently break it. Test login end-to-end early.$wpdb) on every request is expensive and occasionally fatal if constants collide with an existing require of WordPress elsewhere in the process. Isolate it to the routes that need it and keep it out of queue workers and API endpoints.save_post hooks, no cache invalidation. Expect subtle breakage in plugins that assume those hooks ran.base_prefix aren't handled well. Don't plan on it.wp-content/uploads must be web-served. If Symfony owns public/, symlink it in, otherwise media 404s while the database looks perfectly fine.debug: true in the bundle config and WP_DEBUG in wp-config.php. Errors otherwise land in whichever log you aren't reading — check both Symfony's and WP's.$wpdb queries or a Doctrine mapping of your own without touching controllers. That single abstraction is the highest-value thing you can do with a dependency this size.How can I help you explore Laravel packages today?