kayue/kayue-wordpress-bundle
KayueWordPressBundle integrates WordPress with Symfony, letting you run WordPress alongside a Symfony application and access its content, templates, and functions from your Symfony project. It helps bridge routing, templating, and shared services for hybrid WordPress/Symfony sites.
This is a Symfony 2/3 bundle, not a Laravel package — if you're coming from Laravel, mentally map "service provider + facade" to "bundle + service id," and "Eloquent models" to "Doctrine entities mapped over the WordPress wp_* tables."
Minimal setup:
composer require kayue/wordpress-bundle (the repo name is kayue/kayue-wordpress-bundle).new Kayue\WordpressBundle\KayueWordpressBundle() in AppKernel.config.yml:
kayue_wordpress:
wordpress_directory: %kernel.root_dir%/../web/wordpress
table_prefix: wp_
entity_manager: default # which Doctrine EM owns the WP tables
wordpress_directory must point at a real WordPress install — the bundle bootstraps WordPress (wp-load.php/wp-includes) so wpdb and helper functions are available.Where to look first:
Kayue\WordpressBundle\Wordpress\Wordpress — the service that owns the bootstrapped WordPress instance and exposes getWpdb().Kayue\WordpressBundle\Repository\* — PostRepository, UserRepository, TermRepository, CommentRepository. This is the main day-to-day API.Kayue\WordpressBundle\Security\* — WordpressUserProvider and WordpressPasswordEncoder for authenticating Symfony users against wp_users.First realistic use case: authenticate existing WordPress users in a Symfony app. Configure a firewall with the bundle's user provider and you're reading from wp_users with wp_check_password-compatible hashing on day one.
Second use case: read posts/terms into a Symfony controller or Twig template without re-implementing WP_Query using the provided repositories.
Repositories as your read layer. Inject PostRepository / TermRepository and query them like Doctrine repos. For publishing pipelines, PostRepository::findBy(['postStatus' => 'publish', 'postType' => 'post']) plus taxonomy filtering via TermRepository mirrors what WP_Query does, but stays inside Symfony's service container.
Authentication wiring. In security.yml:
providers:
wordpress:
id: kayue_wordpress.security.user_provider
encoders:
Kayue\WordpressBundle\Entity\User: wordpress
firewalls:
main:
form_login:
provider: wordpress
WordpressPasswordEncoder handles phpass hashes already in user_pass, so you don't need to migrate passwords. This is the killer feature — don't rehash unless you plan to lock out WP itself.
Bridging WP functions into Symfony. For anything the repositories don't cover (shortcodes, get_permalink, custom post types, media), pull the Wordpress service and call the global WP function — the bootstrap has already loaded wp-includes. Pattern: a thin WordpressFacade service that wraps Wordpress and exposes only the 5–6 WP functions your app needs, so you can mock it in tests.
Custom entities when the defaults are too thin. Extend Kayue\WordpressBundle\Entity\Post (or copy it) and register it on the same EM with the same wp_posts table. Useful when you need to add association mappings to custom tables that join on post_id.
Cross-app session avoidance. Run Symfony and WordPress on different cookie names/scopes, or front WP through a proxy. The bundle doesn't manage WP cookies for you.
Read-only discipline. Treat WP tables as a legacy schema you don't migrate. Write via the WP bootstrap (wp_insert_post, wp_update_user) if you must, not via Doctrine flush — otherwise you skip wp_*_meta bookkeeping and cached term counts.
wp-load.php runs plugins, sets constants, and often prints output or starts a session. Guard against this: point wordpress_directory at a minimal WP install with plugins disabled, and expect WP_DEBUG output to leak into Symfony responses.table_prefix disagrees with the real install, repositories return zero rows, not an error. Verify with SELECT COUNT(*) FROM wp_posts vs a PostRepository::findAll() count.doctrine:schema:validate / doctrine:migrations:diff for the EM that maps WP tables, or Doctrine will try to "fix" columns it doesn't own.wp_capabilities is a serialized PHP array in wp_usermeta. The bundle's User entity parses it, but if you query usermeta directly you'll get the raw a:1:{s:13:"administrator";b:1;} blob. Use User::getRoles() rather than reading the meta row.WordpressPasswordEncoder still authenticates — test an admin login against a real wp_users table before deploying.wp_postmeta and wp_term_relationships are notoriously unindexed for arbitrary lookups. For dashboards or list pages, drop to wpdb/DBAL with a hand-written query rather than chaining repository findBy calls.wp_* schema fixture, and mock the Wordpress service in unit tests — no need to bootstrap PHP WordPress in CI.Wordpress service is your seam. If you're stuck on a WP function the bundle doesn't expose, add a method there rather than scattering require statements through controllers.How can I help you explore Laravel packages today?