valiton/shariff-bundle
valiton/shariff-bundle integrates Shariff privacy-friendly social sharing buttons into Symfony apps. Add Facebook, X, LinkedIn and other share buttons without third-party tracking, with optional server-side share counts and configurable templates.
This is a thin Symfony 2-era wrapper around the heise/shariff PHP backend, so "getting started" is really three steps: install, register, point shariff.js at the bundle's route.
composer require valiton/shariff-bundle. It pulls in heise/shariff (the privacy-friendly share-count backend) and Guzzle as the HTTP client.app/AppKernel.php:
new Valiton\ShariffBundle\ValitonShariffBundle(),
app/config/routing.yml:
valiton_shariff:
resource: "@ValitonShariffBundle/Resources/config/routing.yml"
(Check the actual filename — it may be routing.xml. This bundle predates routing.yml being the default.)app/config/config.yml under the bundle's extension key (likely valiton_shariff: — confirm against DependencyInjection/Configuration.php). You need at minimum a cache directory, an allowed-domains list, and which services to query:
valiton_shariff:
cache:
ttl: 3600
directory: "%kernel.cache_dir%/shariff"
domains: ["example.com"]
services: ["Facebook", "Twitter", "LinkedIn"]
shariff.min.js + CSS into your template and set data-backend-url="/shariff" (or whatever path the bundle's routing file exposes). Every social button on the page now fetches its count from your server instead of from Facebook/Twitter directly, which is the entire point of Shariff: no third-party requests, no user tracking.Where to look first when something doesn't work: Resources/config/ (services, routing, DI extension), then Heise\Shariff\Backend\Shariff in vendor/heise/shariff — the bundle is a thin DI layer, the real logic is there.
Server-side endpoint (the default path). The bundle's controller returns JSON of the form {"facebook": 12, "twitter": 4, "linkedin": 0}. shariff.js calls it as GET /shariff?url=<encoded>&services[]=facebook&services[]=twitter. Anything you do on the front end is just shariff.js configuration — the bundle's job ends at the JSON.
Injecting the backend service. For anything beyond the bundled controller (a JSON API, a queue worker warming counts, a per-article "popularity" score), pull the Shariff service out of the container and call getCounts($url). This is the real day-to-day use: you aren't limited to the share buttons.
Cache aggressively. Counts change slowly and the backend makes one outbound HTTP call per service per URL. Set ttl to 600–3600s and make the cache directory a shared, writable path — not %kernel.cache_dir% if you run multiple app servers. In production this is the difference between a fast endpoint and one that times out under load.
Per-environment backend selection. Enable Facebook/Twitter only where you can supply credentials; leave them off in dev so the endpoint doesn't fail on missing API keys. Keep domains restricted to your own hosts — it's an SSRF guard as much as a whitelist.
Rendering fallbacks. Shariff returns 0 for a service that failed or has no count; templates should treat 0 as "hide the count", not "show zero shares". Decide this once in Twig rather than per-button.
Testing. A functional test that hits the route with ?url=... and asserts valid JSON is worth more than unit-testing the wrapper — it catches the routing/DI wiring, which is the only thing this bundle actually owns.
AppKernel only (i.e. won't work on Symfony 4+/Flex without conversion) and whether its composer.json still allows your PHP version. If it's a hard blocker, use heise/shariff directly — you lose roughly 60 lines of bundle boilerplate and gain a maintained dependency. That's usually the right trade.{} rather than a 500 when a network call fails.heise/shariff still supports the service you want before configuring it.data-backend-url to an absolute URL. Cross-origin backends need CORS headers on the JSON response, which the bundle's controller almost certainly does not set — add them yourself.DependencyInjection/Configuration.php directly rather than trusting README examples or blog posts; config trees in this era differed by a character or two (valiton_shariff vs shariff) and silently ignored unknown keys.composer update.How can I help you explore Laravel packages today?