mikemccabe/json-patch-php
PHP library implementing JSON Patch (RFC 6902) and JSON Pointer (RFC 6901). Diff two JSON documents, apply patch operations, or read values via pointers. Works with json_decode(..., true) arrays; includes optional SimpleXML-style array handling.
json_decode($json, true) output, eliminating serialization overhead. Compatible with Eloquent models, API resources, and Form Request validation.PatchMiddleware for /api/*/patch).JsonPatch as a singleton for dependency injection.php artisan patch:apply --file=updates.json).Validator can enforce JSON Patch syntax (e.g., required op, path fields) before processing.json-patch-tests) for regression coverage.phpunit to verify patch idempotency and side effects.json_encode() already rejects circular data; patching will fail gracefully.array_key_first).strict_types=1 in the fork to catch type issues early./a/b/c/.../z) could trigger recursion limits or high memory usage.laravel-debugbar to identify hotpaths.../../../etc/passwd) could expose sensitive data./users/*).Str::of($path)->startsWith('allowed/') for validation.toArray() or custom accessors.User model’s posts relationship by converting to an array first.json-patch)?Jsonable/Arrayable interfaces, or custom JSON encoders (e.g., for API resources)?fast-json-patch) for frontend-backend consistency, even if it requires a microservice wrapper?Illuminate\Http\Request and validate with Illuminate\Validation\Validator.Route::patch('/users/{user}', [UserPatchController::class, 'update'])).PatchMiddleware to:
JsonPatch as a singleton in AppServiceProvider:
$this->app->singleton(JsonPatch::class, function ($app) {
return new \mikemccabe\JsonPatch\JsonPatch();
});
save():
$user = User::find($id);
$patched = app(JsonPatch::class)->patch($user->toArray(), $patches);
$user->fill($patched)->save();
$users = User::query()->get()->map(function ($user) {
return app(JsonPatch::class)->patch($user->toArray(), [
['op' => 'remove', 'path' => '/sensitive_data']
]);
});
JsonResource:
public function toArray($request) {
$data = parent::toArray($request);
return app(JsonPatch::class)->patch($data, $this->patches);
}
git submodule init + php runtests.php).composer.json (prefer dev-master for now).PatchService facade:
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class PatchService extends Facade { protected static function getFacadeAccessor() { return 'json-patch'; } }
PatchMiddleware to handle incoming PATCH requests.$validator = Validator::make($request->all(), [
'patches' => 'required|array',
'patches.*' => 'required|array|min:3',
'patches.*.op' => 'required|in:add,remove,replace,move,copy,test',
'patches.*.path' => 'required|string|starts_with:/',
]);
Laravel\Log:
Log::info('Applied patch', ['path' => $path, 'op' => $op, 'user_id' => auth()->id()]);
laravel-debugbar and optimize recursive patching.#[ReturnTypeWillChange] or modern return types.__construct() with named arguments if needed.ext-json polyfills if missing (e.g., spatie/php-polyfill).date, encrypted):
$patched = app(JsonPatch::class)->patch($user->toArray(), $patches);
$user->fill(array_map(fn($v) => is_string($v) ? Carbon::parse($v) : $v, $patched));
How can I help you explore Laravel packages today?