syrup/component-bundle
A Laravel/PHP component bundle that provides reusable UI components for building consistent interfaces faster. Drop components into your Blade views, customize styling, and reduce repetitive markup across your application.
syrup/component-bundle is not a standalone library — it is a Symfony bundle that only makes sense inside a Keboola Syrup application (the precursor to today's Docker-based keboola/php-component). Treat it as a framework plugin, not a utility package.
keboola/syrup in composer.json). The bundle expects the Syrup kernel, the /data volume layout (/data/config.json, /data/in/tables, /data/out/tables), and the component service registration that Syrup injects.composer require syrup/component-bundle, then register the bundle in the app kernel (new Syrup\Bundle\ComponentBundle\ComponentBundle()) and let Syrup wire the services — do not instantiate component classes manually in normal flow.Component/AbstractComponent.php — the lifecycle contract (run(), getComponentName(), getComponentType()).Extractor/AbstractExtractor.php, Writer/AbstractWriter.php, Application/AbstractApplication.php — the three concrete bases you will actually extend.StorageApi/, Logger/, and Encryption/ directories — the helpers your run() will lean on.AbstractExtractor, implement run(), read parameters with $this->getParameters(), fetch from the source API, and write CSV files into /data/out/tables/. Syrup takes care of loading the config, tagging the job, uploading outputs, and reporting run status.If you are starting a new component today, stop here and use keboola/php-component instead. This package is for maintaining existing Syrup components.
The three component archetypes. Every component is one of extractor, writer, or application. Extend the matching base class rather than AbstractComponent directly — the subclasses supply the config-file loading, logging, and manifest conventions for that type.
Configuration access. Do not parse /data/config.json yourself. Use the accessors exposed by the base class (getConfig(), getParameters(), and the per-section helpers). Syrup already normalises the config, merges defaults from the component schema, and masks encrypted values, so reading the raw file desynchronises you from the runtime.
Logging. Use $this->getLogger() (a Monolog channel with Keboola handlers attached). Logs are expected to flow to both the container output and the job's stored log; calling error_log() or print bypasses job attribution and makes failures invisible in the Syrup UI.
Storage API. For any component that reads inputs or writes outputs, use the injected Storage API client to list tables, download files, and upload results. The bundle exposes the client as a service — resolve it from the container and mock it in tests rather than constructing it against live credentials.
Running as a job vs. synchronously. Extractors/writers are typically invoked asynchronously by the Syrup queue, while applications expose action endpoints for synchronous calls. Keep run() side-effect-driven and free of assumptions about HTTP context; put request-shaped logic in the application's action methods.
Structured outputs. Write only into /data/out/tables (and /data/out/files for non-tabular artifacts). The bundle and the parent runtime infer what to upload from those locations plus the manifest — files written anywhere else are silently dropped.
Testing. Build a fixture /data tree (config, input tables) and run the component class against it in a unit test, with the Storage client swapped for a mock. This mirrors production closely enough to catch most path and config bugs without a queue.
Manifest / UI. Component metadata (name, configuration schema, action buttons) lives in the component's manifest and is consumed by the Syrup UI. Changes there are as much a part of "implementing the component" as the PHP code.
/data layout, almost every class fails at construction. Do not try to use it in a generic Laravel app — the Symfony container assumptions are load-bearing./data/config.json. Absolute paths are baked in. Local development requires bind-mounting a fake /data directory (or a Docker volume) or the component cannot boot./data/out/tables. The job reports success with no output. Check the directory and the manifest before suspecting your business logic./data/out/ plus the job log; the Syrup UI log is truncated, so local reproduction is usually faster than reading it.keboola/php-component and the Docker runner; the class shapes (extractor/writer/application, config accessors, logging) map cleanly, and the port removes the Syrup runtime as your test dependency.How can I help you explore Laravel packages today?