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

Catalog Bundle Laravel Package

tourze/catalog-bundle

Symfony bundle for catalog management in PHP applications. Provides Doctrine-backed entities, repositories, and services for organizing catalog items and categories, with integration points for admin panels, forms, and APIs so you can add structured catalog data without building it from scratch.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by pinning the version explicitly, since 2.0.0 is a major bump with no published migration notes:

composer require tourze/catalog-bundle:^2.0

Before writing any code, do three reads in this order:

  1. composer.json of the package — check require for symfony/* vs illuminate/*. Tourze publishes a lot of Symfony-flavoured bundles, so confirm whether 2.0.0 ships a Laravel service provider (extra.laravel.providers) or expects manual wiring in config/app.php / bootstrap/providers.php.
  2. src/ layout — the directory names tell you the mental model: Entity/ or Model/, Repository/, Service/, EventSubscriber/, DependencyInjection/. That is your API surface. Anything under DependencyInjection/ or Resources/config/ is configuration you can override.
  3. The diff itself — https://github.com/tourze/catalog-bundle/compare/1.0.2...2.0.0. With an empty changelog body, the compare view is your only source of truth for BC breaks.

Then publish and migrate:

php artisan vendor:publish --provider="Tourze\CatalogBundle\CatalogBundleServiceProvider" --list
php artisan vendor:publish --provider="Tourze\CatalogBundle\CatalogBundleServiceProvider" --tag=config
php artisan vendor:publish --provider="Tourze\CatalogBundle\CatalogBundleServiceProvider" --tag=migrations
php artisan migrate

First use case to validate the install end-to-end: create a two-level catalog (root → child), attach one item to the child, and read it back through the package's own repository/service rather than raw SQL. If that round-trips, your wiring is correct and you can start layering domain logic on top.

Implementation Patterns

Resolve through the container, not new. Bundles of this type almost always bind a manager/service in the DI config. Inject the interface, not the concrete class — that keeps you compatible with the 2.x line where internals are most likely to churn:

public function __construct(
    private readonly CatalogManagerInterface $catalog,
) {}

Treat the catalog as a tree, and load it as one. The dominant day-to-day cost in catalog packages is recursive queries. Two patterns that hold up:

  • Fetch the whole tree for a given root in one query (or one cached call) and build the hierarchy in memory when you need to render a menu or a category page.
  • For "give me the subtree ids" checks (permissions, filters, breadcrumbs), resolve ids first, then query the item table with whereIn.
$ids = $this->catalog->descendantIds($rootId);          // cheap, cacheable
$items = Item::whereIn('catalog_id', $ids)->paginate(24);

Keep a thin application layer over the package. Wrap the package's write operations in your own actions/services so that a future 2.x → 3.x rename touches one file:

final class AttachItemToCatalog
{
    public function __construct(private readonly CatalogManagerInterface $catalog) {}

    public function __invoke(Item $item, int $catalogId): void
    {
        $this->catalog->attach($item, $catalogId);
    }
}

Use events as the integration seam. If the bundle dispatches domain events (check Event/ or EventSubscriber/), subscribe rather than editing vendor behaviour — reindexing search, busting caches, firing webhooks. This is the pattern least likely to break across majors.

Cache reads, invalidate on write. Catalog data is read-heavy and write-rare. Cache the tree and the id-resolution results under keys that include the catalog id, and flush them from the same actions that write. Do not cache the relationship queries themselves unless you also tag them.

Seed deterministic fixtures for tests. Rather than relying on package factories (which may not exist), build a small in-test helper that creates a root + child + item; that helper becomes your regression harness for the 2.0.0 upgrade.

Admin/API layers. For an API, expose the tree as a nested resource with a depth limit and a ?flat=1 escape hatch — deeply nested JSON is the usual source of frontend pain. For admin, prefer a single "tree" screen plus an item table filtered by selected node over per-node CRUD pages.

Gotchas and Tips

2.0.0 with an empty changelog is a red flag, not a formality. 1.0.2 → 2.0.0 is a semver-major, so assume breakage until proven otherwise. Read the compare diff specifically for:

  • namespace/PSR-4 root changes (Tourze\CatalogBundle\...),
  • renamed config keys and env vars,
  • renamed tables/columns or dropped migrations (a new migration that renames will not run cleanly on a DB that already has 1.0.2 data — plan a maintenance window or a manual migration),
  • method signature changes on the manager/repository interfaces (added required params, changed return types from array to collection),
  • constructor argument order in services you subclass.

Do not trust vendor:publish blindly. Publishing migrations into your own database/migrations directory means you now own them; future package migrations will collide by class name or timestamp. Prefer loading migrations from the package (loadMigrationsFrom) if the provider supports it, and only publish the config.

Watch the framework mismatch. If the bundle is Symfony-first, its service definitions may rely on Symfony's DI (tags, autoconfigure, compiler passes) that Laravel's container ignores silently — you get "class not found" or un-injected constructor args, not a clear error. If you hit that, either wire the services manually in your own provider or look for a Laravel bridge package from the same vendor.

Tree queries will N+1 unless you stop them. Enable DB::listen or Laravel Debugbar on a category page early. A recursive children() accessor is the classic offender. Materialised path or nested-set columns, if present, need to be maintained through the package's own write methods — never ->update() the tree columns directly.

Ordering is usually a column, not a config. If the catalog renders unordered, look for sort/position/weight on the entity and make sure your write path sets it; most "sorting is broken" reports are actually "we never set the sort field".

Upgrade procedure that keeps you safe: create a branch, bump to ^2.0 with --with-dependencies, run composer why-not tourze/catalog-bundle 2.0.0 to see what's blocking, run your test suite, then diff the package's own config file against yours (git diff of the published config is the fastest way to spot renamed keys).

Debugging aids: php artisan about to confirm the provider is registered, php artisan vendor:publish --list to see available tags, and app()->make(SomePackageClass::class) in tinker to confirm the container can resolve the service before you wire it into a controller.

Extension points to prefer: published config, event subscribers, and decorated interfaces. Avoid extending concrete package classes — those are exactly what majors rewrite.

Pin the version in composer.json ("tourze/catalog-bundle": "2.0.*") until you have read the diff and characterised the 1.0.2 → 2.0.0 changes; an unpinned ^2.0 on an actively-released vendor package can drop a 2.1.0 on you mid-sprint.

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