Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Wp Rest Laravel Package

pollora/wp-rest

Pollora WP REST adds Laravel-style REST API routing to WordPress: register routes and controllers with an expressive syntax, group endpoints, apply middleware, and return clean JSON responses while staying compatible with the native WordPress REST API.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a small, framework-agnostic slice of Pollora: it turns PHP 8 attributes on controller classes into WordPress REST API routes. It is the piece you reach for when you want attribute-driven register_rest_route() calls without pulling in the whole Pollora framework.

Install and wiring (v0.1.0)

  • composer require pollora/wp-rest (pin the version — this is a 0.x release explicitly tracking the next Laravel/framework release, so treat the API as provisional).
  • The package does not boot itself. You construct Pollora\WpRest\WpRestDiscovery, hand it a PSR-11 container and a set of directories to scan, and run it (typically from a mu-plugin, a service provider's boot(), or a small bootstrap file loaded on plugins_loaded).
  • Read src/WpRest/ first. It is a direct lift from pollora/framework (src/WpRest) with class names unchanged, so any existing Pollora documentation or blog posts about WP REST controllers apply verbatim, with the namespace swapped to Pollora\WpRest\*.
  • Pollora\Support\WpGlobals ships alongside it for WordPress global access; check whether you already have an equivalent helper before adopting it.

First use case

Add a controller class under a scanned directory, annotate the class with the package's route attribute and its methods with the method/args attributes, and let discovery register it. The fastest sanity check is a single GET route returning a static array: hit it via wp-json/<namespace>/<route> to confirm the scan directories, container resolution, and namespace/version are all correct before adding auth callbacks or argument schemas.

Because v0.1.0 can run without Laravel's application, verify early whether you are in a Laravel context or a bare WordPress one — the bootstrap differs (container source) but the controller code does not.

Implementation Patterns

Attribute-driven controllers. Keep one controller per resource. Class-level attribute sets the namespace/route base; method-level attributes set HTTP verb, path, and args. This mirrors how register_rest_route() arguments map, so anything you can express in the array form you can express here.

Constructor injection, resolved by discovery. Controllers are built by the discovery's instance resolver, not by WordPress. That means constructor dependencies (repositories, services, a logger) work as long as your PSR-11 container can resolve them — and they are resolved at registration time, not per request. Keep constructors cheap and side-effect-light; do expensive work lazily inside the handler.

Two integration modes.

  1. Bare WordPress / PSR-11: build any container implementing Psr\Container\ContainerInterface, pass it to WpRestDiscovery, and let it construct controllers. Ideal for mu-plugins and non-Laravel sites.
  2. Laravel: pass the application container so controllers can use framework bindings. Note the package itself does not register a service provider in v0.1.0 — you write the glue in your own provider.

Custom HandlesAttributes attributes. This is the extension seam. Implement HandlesAttributes on your own attribute class to introduce project-specific metadata (feature flags, capability requirements, cache TTLs, OpenAPI hints). The handler receives the PSR-11 container, so it can act on the attribute at discovery time — a good place to auto-register permission_callbacks derived from a #[RequiresCapability('manage_options')]-style attribute rather than repeating them per method.

Workflow that pays off. Centralise cross-cutting REST concerns (nonce/permission checks, response shaping, error envelopes) in base controller classes or in a HandlesAttributes implementation, and keep endpoint classes to argument definition plus a thin handler. Register the discovery once on rest_api_init-adjacent timing and cache the scan in production if directory walking shows up in profiles.

Gotchas and Tips

  • Version pinning. 0.1.0 is a staging release for a forthcoming framework release; 1.0.0 will land with it. Expect namespace or bootstrap changes at 1.0.0 — wrap your bootstrap in one file so the upgrade touches one place.
  • Discovery timing. Routes must be registered before WordPress dispatches rest_api_init consumers. Running discovery too late silently yields 404s (rest_no_route) with no error. If a route "doesn't exist", check timing before checking attributes.
  • Silent misconfiguration. Directory scanning fails quietly: wrong path, wrong namespace, or a file that doesn't autoload produces zero routes and zero warnings. Dump the resolved route list or var_dump inside the resolver while bringing up a new scan root.
  • Container resolution errors surface as fatals. A missing binding throws from the constructor during registration — which happens on every request, not just requests to that route. Keep unresolvable dependencies out of controller constructors.
  • No Laravel assumption. Do not use facades, app(), or config() inside controllers if you want the bare-WordPress path to keep working. The architecture test enforcing "attributes, discovery, PSR contracts and WordPress" only constrains the package, not your code — you can still accidentally couple yourself to Laravel.
  • Pollora\Support\WpGlobals is a static-ish helper over WordPress globals. Useful, but be aware of the usual caveats: it is not mockable in unit tests without extra work, and globals differ under multisite and WP-CLI. Prefer passing values in via the container where practical.
  • Debugging checklist for a non-firing endpoint: (1) discovery actually ran, (2) the class is inside a scanned directory and autoloadable, (3) namespace/version in the attribute match your URL, (4) permission_callback isn't returning a WP_Error (a 401/403 is often a permissions bug, not a routing bug), (5) args validation isn't rejecting the payload with a 400.
  • Testability. Because controllers are plain classes with constructor injection, they unit-test well by instantiating them with fakes and calling methods directly — you do not need a WordPress test harness for handler logic, only for the discovery/registration layer.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle