setono/sylius-log-entry-plugin
Setono Sylius Log Entry Plugin adds a LogEntry resource and admin grid to Sylius, letting you store and browse log entries directly from the administration panel for easier auditing and debugging of store activity.
Install the plugin with Composer and enable it in the kernel, which is the standard Sylius plugin flow:
composer require setono/sylius-log-entry-plugin
Register the bundle in config/bundles.php:
return [
// ...
Setono\SyliusLogEntryPlugin\SetonoSyliusLogEntryPlugin::class => ['all' => true],
];
Import the routing so the admin grid is reachable:
# config/routes/setono_sylius_log_entry.yaml
setono_sylius_log_entry_admin:
resource: "@SetonoSyliusLogEntryPlugin/Resources/config/routing/admin.yaml"
prefix: /admin
Then create and run the Doctrine migration in your host application (the plugin ships mappings, not migrations you should blindly run):
bin/console doctrine:migrations:diff
bin/console doctrine:migrations:migrate
Where to look first, in this order:
src/Model/LogEntryInterface.php and src/Entity/LogEntry.php — this defines exactly what a log entry can hold (message/level/channel/context/timestamp, or whatever subset the package implements). Everything you build depends on this shape.src/Resources/config/ — resource, grid, and admin route wiring. This tells you how the admin page is assembled and where to hook overrides.src/Factory/ and src/Repository/ — the extension points for creating and querying entries.First use case: treat the plugin as a persistent, admin-visible audit/activity log. The quickest win is to make your own services write a LogEntry whenever something meaningful happens (order state change, payment capture, import run), then verify it appears in the Sylius admin grid. That validates entity mapping, routing, and security in one pass before you invest in deeper integration.
Writing entries from application code. Don't construct entities by hand — use the plugin's factory and persist through the manager, respecting the Sylius resource pattern:
final class OrderAuditListener
{
public function __construct(
private LogEntryFactoryInterface $factory,
private EntityManagerInterface $manager,
) {}
public function onStateChange(OrderStateChanged $event): void
{
$entry = $this->factory->createNew();
$entry->setMessage(sprintf('Order %s -> %s', $event->order->getNumber(), $event->newState));
// set level/channel/context as exposed by the interface
$this->manager->persist($entry);
$this->manager->flush();
}
}
Bridging Symfony/Monolog logs. The most valuable day-to-day pattern is registering a Monolog handler that writes selected channels into the plugin's entity, so logger->info(...) from anywhere ends up in the admin grid. Create a small handler in your app that wraps the plugin factory, and only route the channels/levels you actually want persisted — do not dump the whole logger stack into the database.
Extending the log entry. If you need extra columns (tenant ID, admin user, correlation ID), override the resource in config/packages/_sylius.yaml with your own entity extending the plugin model, and map the parent fields. This is the supported Sylius way and keeps the admin grid working. Do this before running migrations to avoid a churn of table alterations.
Customizing the admin grid. Copy or override the plugin's grid definition in config/packages/_sylius.yaml under sylius_grid.grids.setono_sylius_log_entry to add filters (level, channel, date range) or extra columns. This is where most teams spend their customization time — raw timestamps and serialized context are rarely readable, so add a formatted createdAt and a truncated message column early.
Querying programmatically. Inject the plugin's repository for dashboards or health checks. Keep queries indexed on createdAt (and level/channel if you filter by them) — a log table without a timestamp index will slow down the admin grid surprisingly fast.
Security. Lock the admin route down in config/packages/security.yaml to a specific role (ROLE_ADMIN or a dedicated log-viewer role). Log content can leak order or customer data, so treat the grid as sensitive.
doctrine:query:sql, and monitor table size.composer.json, read the changelog between bumps, and budget time to audit the source. There is little community troubleshooting to lean on, so keep your integration thin — a Monolog handler + factory wrapper is easy to fork or replace if the package stalls.doctrine:migrations:diff in your own app and review the generated SQL before migrating, especially on an existing production database.context columns. If the entity stores context as JSON, remember it may come back as an array or string depending on the mapping. Defensive decoding (json_decode with a fallback) in grid templates and exporters avoids blank or fatal rendering._sylius.yaml resource definition is loaded after the plugin's. If overrides "don't work," check prepend/append order in config/packages/.createdAt may be set with the PHP default timezone while the admin displays in the app timezone. Standardize on UTC storage and format at render time to avoid confusing logs during incident debugging.postFlush/kernel.terminate where possible; otherwise you'll turn logging into your slowest code path.How can I help you explore Laravel packages today?