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

Restboot Bundle Laravel Package

silasyudi/restboot-bundle

A Laravel/PHP bundle for bootstrapping REST API scaffolding, offering ready-made structure for common endpoints to reduce repetitive setup. A starting point rather than a full framework. Low adoption; review the source before relying on it in production.

View on GitHub
Deep Wiki
Context7

Getting Started

This release moves the package onto JMS Serializer as its serialization engine and adds first-class support for serializing arrays of objects. If you are upgrading from a v2.x install, treat this as a hard breaking change and budget time to re-audit every annotated model/DTO before deploying.

First steps:

  1. Require the new major: composer require <vendor>/<package>:^3.0. JMS Serializer (jms/serializer) will be pulled in as a transitive dependency — do not also require symfony/serializer, and remove it if nothing else uses it.
  2. Publish the config if the package exposes one (php artisan vendor:publish --tag=<package>-config) and review config/jms_serializer.php — metadata driver, cache dir, naming strategy, and default serialization context all live there.
  3. Confirm the service provider is registered. If you relied on the old Symfony-backed binding, check that your container bindings still resolve — the concrete serializer class has changed.
  4. Look first at the package's Serializer facade/service wrapper (usually injected as a contract or resolved via the container). That is your day-to-day entry point for serialize() / deserialize().

First use case — serialize a simple DTO to JSON through the wrapper:

$json = app(Serializer::class)->serialize($user, 'json');

Then immediately test the same payload against your existing API contract. The output shape will differ from Symfony Serializer in several places (null handling, date formatting, empty collections), so diff the response before moving on.

Implementation Patterns

Metadata via attributes. JMS uses its own attribute set, which is not interchangeable with Symfony's:

use JMS\Serializer\Annotation as Serializer;

class UserDto
{
    #[Serializer\Groups(['api'])]
    #[Serializer\SerializedName('user_id')]
    public int $id;

    #[Serializer\Groups(['api'])]
    #[Serializer\Type("DateTimeImmutable<'Y-m-d'>")]
    public \DateTimeImmutable $createdAt;

    #[Serializer\Exclude]
    public string $internalNote;
}

Group-based contexts. Define the shape of your payload per endpoint via groups, and pass the context at call time:

$json = $serializer->serialize($user, 'json', SerializationContext::create()->setGroups(['api']));

Prefer a small, stable set of group names (api, api.detail, admin) over ad-hoc per-controller groups.

Arrays of objects (the headline feature). The new support means you can now declare the element type and get real hydration rather than nested arrays:

#[Serializer\Type('array<App\DTO\UserDto>')]
public array $users;

or, with the property docblock:

/** @var UserDto[] */
#[Serializer\Type('array<App\DTO\UserDto>')]
public array $users;

Apply the same type hint on the receiving DTO when deserializing collections. Without an explicit element type, JMS falls back to array and you get plain arrays back — the single most common cause of "it worked in v2" confusion.

Deserialization into DTOs. Use the wrapper's deserialize() with a target class and let JMS hydrate constructors/accessors:

$dto = $serializer->deserialize($request->getContent(), UserDto::class, 'json');

If your DTOs are immutable, make sure constructor parameter names or #[SerializedName] match the incoming keys.

Integration with controllers / API resources. Wrap the serializer behind a small application service so controllers do not talk to JMS directly. This gives you one place to set default groups and context, and keeps the eventual next serializer swap cheap.

Versioned payloads. If you expose public APIs, use #[Since('3.0')] / #[Until('4.0')] and set the version on the context rather than branching in code.

Custom handlers for value objects. Register handlers (e.g. money, UUID, enums) in the config's handler list rather than adding __serialize hacks to domain objects.

Gotchas and Tips

  • Symfony Serializer attributes are silently ignored. #[Groups], #[SerializedName], and #[Ignore] from Symfony\Component\Serializer\Annotation do nothing under JMS. Worse, JMS exports everything by default, so properties you thought were excluded may now leak. Audit all models before shipping.
  • Default exposure is permissive. Without groups or #[Exclude], all public properties/accessors are serialized. Lock this down with a default group or an explicit exclusion policy in config.
  • null handling changed. Symfony tended to emit "key": null; JMS omits nulls unless serialize_null is enabled on the context. Flip it explicitly per-endpoint if clients expect nulls.
  • Date formats are not preserved. JMS defaults to Y-m-d\TH:i:sP (or ISO variants). If your API contract had a different format, set #[Type("DateTimeImmutable<'format'>")] or configure the handler.
  • Clear the metadata cache on every deploy. JMS caches parsed metadata to disk. New/renamed annotated classes, or a changed cache path, will produce stale or empty metadata. Add a cache clear to your deploy script, or ensure the cache dir is in .gitignore and writable.
  • Arrays of objects need the element type twice. Both the property type hint and the #[Type] declaration matter; a docblock alone may be picked up by one driver but not another. Verify with a round-trip test (deserialize(serialize($x)) == $x).
  • Empty arrays vs. {}. An empty PHP array serializes to [] in JSON; if a client expects an object, you will need a wrapper handler or a collection type.
  • Constructor requirements on deserialize. DTOs with required constructor params but no matching keys will throw MissingConstructorArgumentsException. Either default the parameters or mark them optional.
  • Circular references. Bidirectional entity relations will recurse indefinitely without #[MaxDepth] or #[Exclude] on the back-reference. Set enable_max_depth in the context if you rely on it.
  • Naming strategy mismatch. If the host app configures a snake_case naming strategy, #[SerializedName] still wins — but you can end up with a mixed casing contract. Pick one convention and enforce it in a test.
  • Performance. Metadata parsing is expensive on first touch. In production, use the file cache driver with a warm cache; avoid ArrayCache outside tests.
  • Extension points worth knowing: custom handlers (config-level), serialization event subscribers (pre/post serialize per class), and visitor hooks. These are the safe places to adapt DTOs whose shape you cannot change.
  • Upgrade checklist: remove symfony/serializer if unused, re-annotate all DTOs to JMS attributes, re-verify JSON contracts with a golden-file test, add array-of-object element types, and clear/warm the metadata cache before rolling out.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
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