PHPackages                             jooservices/laravel-wordpress - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. jooservices/laravel-wordpress

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

jooservices/laravel-wordpress
=============================

Laravel service package for WordPress local/remote CRUD, sync, and media/file management.

v1.0.0(1mo ago)00MITPHPPHP ^8.5CI passing

Since May 31Pushed 1mo agoCompare

[ Source](https://github.com/jooservices/laravel-wordpress)[ Packagist](https://packagist.org/packages/jooservices/laravel-wordpress)[ RSS](/packages/jooservices-laravel-wordpress/feed)WikiDiscussions develop Synced 1w ago

READMEChangelog (1)Dependencies (11)Versions (3)Used By (0)

Laravel WordPress
=================

[](#laravel-wordpress)

Laravel service package for WordPress local/remote CRUD, sync, and media record/file management.

This package is a service layer only: no routes, controllers, jobs, queues, events, listeners, audit log, sync history, background processing, or UI. It stores local WordPress state in package-owned tables, talks to remote WordPress through `jooservices/wordpress-sdk`, and keeps sync state explicit.

Install
-------

[](#install)

```
composer require jooservices/laravel-wordpress
php artisan vendor:publish --tag=laravel-wordpress-config
php artisan vendor:publish --tag=migrations
php artisan migrate
```

See [installation](docs/01-getting-started/installation.md) and [configuration](docs/01-getting-started/configuration.md) for setup notes.

Usage
-----

[](#usage)

```
use Jooservices\LaravelWordPress\DTOs\Credentials\CredentialCreateData;
use Jooservices\LaravelWordPress\DTOs\Sites\SiteCreateData;
use Jooservices\LaravelWordPress\Enums\AuthType;
use Jooservices\LaravelWordPress\Facades\WordPress;

$site = WordPress::sites()->create(new SiteCreateData('Production', 'https://example.com'));

WordPress::credentials()->createForSite($site, new CredentialCreateData(
    name: 'Default',
    authType: AuthType::ApplicationPassword,
    username: 'admin',
    secret: env('WP_APP_PASSWORD'),
));

WordPress::site($site)->users()->users()->pull();
WordPress::site($site)->content()->posts()->pull();
WordPress::site($site)->media()->records()->pull();
WordPress::site($site)->media()->files()->download($media);
```

Architecture Overview
---------------------

[](#architecture-overview)

The public flow is:

```
WordPress facade -> Manager -> SiteContext -> grouped service -> ResourceService
    -> ResourceDefinition -> ResourceLocalService / ResourceRemoteService / ResourceSyncService

```

Grouped services expose resource families while the shared resource layer owns common local, remote, and sync behavior. `ResourceDefinition` classes adapt WordPress REST resources to local tables, Eloquent models, remote SDK services, and payload mapping. Details are in [architecture](docs/00-architecture/service-architecture.md).

Service Map
-----------

[](#service-map)

Entry pointPurpose`WordPress::sites()`Site records`WordPress::credentials()`Site credentials`WordPress::site($site)->content()`Posts, pages, revisions, autosaves`WordPress::site($site)->media()->records()`Media attachment record local/remote CRUD and record sync`WordPress::site($site)->media()->files()`Media file upload, download, and local file deletion`WordPress::site($site)->taxonomy()`Taxonomies and terms`WordPress::site($site)->users()`Users`WordPress::site($site)->applicationPasswords()`Application passwords`WordPress::site($site)->comments()`Comments`WordPress::site($site)->system()`Settings, options, types, statuses, themes, plugins`WordPress::site($site)->editor()`Blocks, patterns, templates, global styles`WordPress::site($site)->navigation()`Navigation, menus, menu items, locations`WordPress::site($site)->widgets()`Sidebars, widgets, widget types`WordPress::site($site)->remoteResources()`Dynamic remote resource accessResource Capability Matrix
--------------------------

[](#resource-capability-matrix)

Resource areaStatusPosts and pagesFeature-level tested for pull, local create/update, push, taxonomy IDs, featured media, unpublish, trash reflection, and conflict detectionMedia recordsFeature-level tested for attachment record pull and source URL persistenceMedia file downloadFeature-level tested through explicit `downloadFile()` local byte copyMedia uploadSupported through `media()->files()->upload(...)` / `uploadFile(...)` using `jooservices/wordpress-sdk` real Media Library uploadGeneric resource tables and definitionsAvailable for remote/local/sync operations through the shared resource layer, but not all are feature-completeAuthor assignmentRuntime-dependent; WordPress REST permissions can override requested authorsCustom REST metaRuntime-dependent; keys must be registered in WordPress with `show_in_rest=true`Sync Lifecycle
--------------

[](#sync-lifecycle)

`pull()` reads remote REST payloads, maps them through a `ResourceDefinition`, stores local records, and updates explicit sync hashes and timestamps. `push()` creates or updates remote records from local models. `sync()` currently aliases pull behavior on shared resources.

Sync state uses local and remote hashes, `sync_status`, `synced_at`, `last_pulled_at`, `last_pushed_at`, `conflict_payload`, and `conflicted_at`. See [sync](docs/02-user-guide/sync.md).

Conflict Handling
-----------------

[](#conflict-handling)

The package does not auto-merge conflicts. Dirty local records are not silently overwritten by a remote pull, and remote changes are not silently overwritten by a local push unless force/local resolution is intentionally used. Use:

- `resolveConflictUsingLocal($model)` to force the local model to WordPress.
- `resolveConflictUsingRemote($model)` to replace the local model with the remote payload.
- `resolveConflictManually($model, $payload)` after building an explicit merged payload.

Media Lifecycle
---------------

[](#media-lifecycle)

`media()->records()->pull()` stores attachment records and source URLs. `media()->files()->download($media)`copies remote bytes into Laravel Storage. `media()->files()->upload($data)` sends file bytes to the WordPress Media Library and persists the returned attachment record locally. `media()->files()->deleteLocal($media)` deletes only the local copied file. Physical files are never deleted as a side effect of record sync.

See [media files](docs/02-user-guide/media-files.md).

Adding a New Resource
---------------------

[](#adding-a-new-resource)

Add a `ResourceDefinition`, register it in `ResourceRegistry`, expose it from the appropriate grouped service if needed, and cover payload mapping plus sync behavior with focused tests. Keep resource definitions as adapters and keep database or remote coordination in services. See [adding a resource](docs/04-development/adding-resource.md).

Testing
-------

[](#testing)

```
composer validate --strict
composer install
composer lint
composer test
composer test:unit
composer test:feature
composer test:integration
composer test:real
composer quality
```

Real Docker Integration Workflow
--------------------------------

[](#real-docker-integration-workflow)

The Docker workflow installs a fresh Laravel app, installs this package into it with a Composer path repository, installs WordPress with WP-CLI, seeds real WordPress records and media files, runs Laravel package migrations, and executes a PHPUnit smoke test against the real services.

Prerequisites: Docker and Docker Compose.

```
./scripts/test-docker.sh
```

The workflow validates package discovery, config loading, package migrations, WP-CLI availability, WordPress installation, real WordPress post/media generation, WordPress-to-Laravel pull sync, media record pull, explicit media file download, update handling, idempotent repeated pull behavior, Laravel-originated post create/update push through DTOs, Laravel-originated page create push through DTOs, taxonomy assignment, featured media assignment, unpublish, trash behavior with local reflection, and dirty-local conflict detection against a real remote change. It writes:

```
artifacts/integration-report.json
artifacts/integration-summary.txt
artifacts/junit.xml

```

The JSON report includes environment versions, executed paths/commands, package capabilities, schema audit notes, WordPress record counts, Laravel record counts, media record/file evidence, pull/push/idempotency results, assertions, skipped assertions, failures, and limitations. Media is reported in three separate buckets: WordPress attachments, Laravel media records, and local copied files. Useful defaults can be overridden with environment variables such as `DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`, `WORDPRESS_PATH`, `WORDPRESS_URL`, `LARAVEL_APP_PATH`, and `PACKAGE_PATH`.

See [Docker WordPress testing](docs/04-development/docker-wordpress.md).

Known Limitations
-----------------

[](#known-limitations)

- Media upload uses the SDK's Media Library upload endpoint; field acceptance still depends on WordPress runtime permissions and REST support.
- Posts/pages have feature-level coverage; many generic resource definitions are available through shared services but are not all feature-complete.
- Author assignment depends on runtime WordPress REST permissions and configuration.
- Custom meta requires WordPress meta keys registered with `show_in_rest=true`.
- Endpoint shape and capabilities can vary by WordPress version, plugins, themes, auth type, and user permissions.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance89

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

54d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/142772948?v=4)[JOOservices Ltd](/maintainers/jooservices)[@jooservices](https://github.com/jooservices)

---

Top Contributors

[![soulevilx](https://avatars.githubusercontent.com/u/2688707?v=4)](https://github.com/soulevilx "soulevilx (18 commits)")

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/jooservices-laravel-wordpress/health.svg)

```
[![Health](https://phpackages.com/badges/jooservices-laravel-wordpress/health.svg)](https://phpackages.com/packages/jooservices-laravel-wordpress)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45444.2k1](/packages/pressbooks-pressbooks)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
