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

Demosplan Core Laravel Package

demos-europe/demosplan-core

Core library for demosplan, an open-source digital participation platform used in urban planning and public consultation. It provides shared domain models, services, and workflow logic for managing procedures, statements, and planning documents in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

demosplan-core is not a Laravel package — it's a Symfony bundle (namespace DemosEurope\DemosplanCoreBundle) that ships the domain model for demosplan, a German municipal public-participation platform (procedures, statements, consultations, files). A Laravel mental model will actively mislead you: no ServiceProvider, no auto-discovery, no facades, no Eloquent, no Blade, no Artisan. Treat it as a Composer library consumed by a Symfony host app.

Minimum steps:

  1. Match the runtime. PHP 8.1+, Symfony 6/7, Doctrine ORM, MySQL/Postgres, Elasticsearch 7.x, Redis, RabbitMQ. Check the host's composer.json — the bundle expects specific symfony/* majors; mixing in a Laravel 10/11 app is not supported.
  2. Install into a Symfony skeleton, not Laravel:
    composer require demos-europe/demosplan-core
    
  3. Register the bundle in config/bundles.php:
    DemosEurope\DemosplanCoreBundle\DemosplanCoreBundle::class => ['all' => true],
    
  4. Import routing and config in config/routes.yaml and config/packages/ — the bundle ships YAML defaults that the host is expected to override (demosplan_core.yaml, Elasticsearch, permissions).
  5. Run Doctrine migrations and seed an admin/procedure so a page renders.
  6. Index Elasticsearch before touching statements — a chunk of the UI is empty without it:
    bin/console demosplan:elasticsearch:index
    

First use case: load the Verfahren (procedure) list page, click into a procedure, view a Stellungnahme (statement). That single path wires up Doctrine entities, the statement service, ES-backed search, and the Twig views — enough to see the shape of the package before you start extending anything.

Where to look first in the repo: src/Entity (Doctrine entities), src/Services (domain logic), src/Controller (routes), src/Command (console commands), src/Resources/config (services and YAML defaults), and tests/ for the expected wiring.

Implementation Patterns

Composition over inheritance. The bundle exposes services; extend behaviour by decorating them, not subclassing controllers.

final class LoggingStatementService implements StatementServiceInterface
{
    public function __construct(
        private StatementServiceInterface $inner,
        private LoggerInterface $logger,
    ) {}

    public function getStatement(string $id): Statement
    {
        $this->logger->info('statement.fetch', ['id' => $id]);
        return $this->inner->getStatement($id);
    }
}
services:
  App\Service\LoggingStatementService:
    decorates: demosplan_core.statement.service
    arguments: ['@.inner', '@logger']

Extend the entity graph via Doctrine inheritance, not migrations of the vendor schema. If you need extra fields on procedures or statements, map them in your own entity extending the bundle's, and register an attribute override. Editing src/Entity/* in vendor/ will be wiped on composer update.

Hook into the domain with Doctrine listeners and Symfony event subscribers. There are no Laravel-style model observers; use doctrine.event_listener for entity lifecycle and kernel.event_subscriber for application events (statement creation, assignment, notification). This is where integrations — e.g. pushing new statements to a CRM — belong.

Reuse the repository layer. The bundle's repositories extend ServiceEntityRepository; inject them rather than writing raw DQL, especially for anything touching statements, where ES and Doctrine are kept in sync and bypassing the repo will drift them.

Async work is expected. Statement import, ES indexing, and mail are pushed through RabbitMQ workers. In dev, run:

bin/console messenger:consume async -vv

Otherwise statements appear to "not save" when they're queued.

Console commands are the integration surface for batch work. Look under src/Command for demosplan:import:*, demosplan:elasticsearch:*, and maintenance tasks; wrap them in cron rather than re-implementing logic.

Config layering. The bundle ships Resources/config/*.yaml defaults; override under the host's config/packages/demosplan_core.yaml. Prefer explicit overrides over env-var-only tweaks — many keys are read at container compile time.

Gotchas and Tips

  • License is NOASSERTION. Read the actual LICENSE file in the repo (demosplan historically ships EUPL-1.2) before you depend on this in a commercial product. NOASSERTION means the packagist metadata could not be normalised — it does not mean "no license", but you cannot assume permissiveness. Get this cleared by legal first.
  • Do not try to glue this into a Laravel app. There is no DemosplanCoreServiceProvider, no config publishing, no facades, no Blade. If your team is Laravel-only, budget for a Symfony ramp-up or pick a lighter public-participation package.
  • Elasticsearch is load-bearing, not optional. Many list/search screens depend on ES being reachable and indexed. A fresh install without indexing looks broken. Also watch ES version — 7.x vs 8.x queries differ.
  • Doctrine proxies and __construct requirements. Entities with mandatory constructor args require named constructors; don't new Statement() in your own code, use the factory/service or Hydrators. Lazy proxies will bypass constructors in ways that are surprising if you're used to Eloquent's "new model with defaults".
  • php bin/console cache:clear after any config YAML change. The bundle compiles substantial DI and config; stale container errors look like code bugs but are cache.
  • Environment variable sprawl. Expect DATABASE_URL, ELASTICSEARCH_*, REDIS_*, MESSENGER_*, MAILER_*, plus demosplan-specific keys. Diff the bundle's .env/config against your app; missing keys fail late at runtime, not at boot.
  • Migrations are versioned with the bundle. Don't hand-edit vendor migrations; if you need a schema change, create a host-app migration that alters after the bundle's.
  • Testing setup is heavier than PHPUnit defaults. The repo uses PHPUnit plus fixtures against a real DB; there's no SQLite shortcut. Expect to need a MySQL/Postgres container in CI.
  • Extension points to reach for first: service decorators, Doctrine event listeners, kernel.event_subscriber, and custom console commands. Avoid forking the bundle — track upstream demos-europe/demosplan-core releases and rebase your decorators.
  • Low stars (11) is a signal, not a verdict: this is infrastructure for one specific product, not a general-purpose library. Expect fewer third-party answers, no Stack Overflow corpus, and a smaller community — read source and tests instead.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager