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

Sulu Google Reviews Bundle Laravel Package

depa/sulu-google-reviews-bundle

Symfony bundle for Sulu CMS 3 that imports Google Places reviews via the Places API, stores reviews rated 4 stars or higher in a dedicated table, adds a native admin interface for moderation, and renders them on the frontend through a flexible Sulu block.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the mismatch: this is not a Laravel package. It is a Symfony bundle for Sulu CMS 3.0+ (PHP 8.2+, Symfony 7.0+, MySQL 8.0+). There is no service provider, no artisan, no config/google-reviews.php. It expects a Sulu application skeleton with the Sulu admin already bootstrapped. If your day job is Laravel, treat this as a reference implementation for the fetch-and-moderate workflow, or run it beside your app on the same database — do not try to composer require it into a Laravel project.

Minimum viable path in a Sulu 3 app:

  1. composer require depa/sulu-google-reviews-bundle
  2. Confirm registration in config/bundles.php (Flex does it; otherwise add Depa\SuluGoogleReviewsBundle\DepaSuluGoogleReviewsBundle::class => ['all' => true]).
  3. Import the admin routes into config/routes/routes_admin.yaml (the README excerpt cuts off here — check whether the resource path is @DepaSuluGoogleReviewsBundle/Resources/config/routing_admin.xml or a PHP/YAML equivalent shipped in the repo).
  4. Obtain a Google Places API key with Places API enabled, then wire it into the bundle config (look in src/DependencyInjection/Configuration.php for the exact node name and whether it reads %env(...)% or a plain string).
  5. Run Doctrine migrations for the reviews table, then rebuild Sulu: bin/console doctrine:migrations:migrate, bin/console sulu:build, and clear cache.
  6. Log into /admin — you should see a new navigation entry for reviews.

Where to look first in the repo: DependencyInjection/Configuration.php (the config tree is the real documentation), Entity/ or Model/ for the table schema, Admin/ for the list/form metadata, and Resources/views/ for the Twig block template. First real use case: fetch reviews for one place ID, moderate them (approve/hide) in the admin, and render the approved set through the provided Sulu block on an "About" or "Testimonials" page.

Implementation Patterns

Config-driven, single place. The bundle is built around one Google Place ID plus an API key. In a multi-location site you will either instantiate the bundle's fetch service per place (if it accepts a place argument) or accept one place per site and use Sulu's webspace/multi-site config to vary the key and place ID per webspace. Verify by reading the fetch service's constructor before designing around multi-tenancy.

Scheduled fetch, not request-time fetch. Never call the Places API inside a page render. Wrap the bundle's fetch service in your own Symfony command (or reuse the one shipped, if present) and run it on a cron or Symfony Scheduler at a low frequency — daily or weekly is plenty. Google reviews change slowly and the Places API is billed per call.

Moderation as the gate, not the source of truth. The bundle stores reviews filtered to ≥ 4 stars and then lets an editor approve them in the Sulu admin. Treat the "approved" flag as the only column your frontend should ever read. Build a thin repository or Twig function that queries approved-and-not-deleted reviews ordered by publish_time DESC, with an explicit limit — the admin list will grow and you do not want an unbounded query on a homepage.

Render via the Sulu block. Add the bundle's block type as a property on your page template XML, then in Twig iterate the block items. This is the intended path and keeps editorial control (order, count, layout) with the content team rather than in code. If you need a hard-coded widget instead, skip the block and query the table directly from a controller — the schema is plain Doctrine, so it reads fine from anywhere.

Integration tip for non-Sulu frontends. Because the reviews land in a normal MySQL table, a Laravel app pointed at the same database can read them with a trivial Eloquent model (protected $table = '...') and skip the bundle entirely on the read side. The only Sulu-specific value is the admin moderation UI and the block — if you already have a CMS admin, you are paying a lot of setup for a table and a cron job.

Decorate, don't fork. Both the fetcher and the persistence step should be Symfony services with interfaces. Register a decorator in services.yaml to change filtering rules (e.g. 3-star threshold, de-duplication, translating relative_time_description into a real timestamp) without patching vendor code.

Gotchas and Tips

  • Zero stars, zero dependents, one maintainer. This is a small internal-extraction bundle. Pin the exact version in composer.json, commit composer.lock, and read CHANGELOG.md before every bump. The advertised last release date in the metadata looks implausible (a future date) — verify against the actual git tags before trusting the version constraint.
  • The ≥ 4 star filter is almost certainly hardcoded. Check Configuration.php for a threshold node. If it is not configurable, the practical options are a decorator on the fetch/persist service or storing everything and filtering in your query — the latter is safer and keeps 3-star reviews available for editorial judgement.
  • Places API review limits and billing. The Places Details endpoint returns a capped subset of reviews (historically five, "most relevant"), not the full review history, and it bills per request with field-mask-dependent SKUs. Do not promise a client "all our Google reviews" — set the expectation that this is a highlights feed. Budget alerts on the Google Cloud project are mandatory.
  • Multilingual sites. Google returns review text in the reviewer's language, not your webspace locale. There is no translation layer here. Either accept mixed-language reviews, label them, or filter by language yourself before writing to the table.
  • Cache invalidation is manual. Sulu's HTTP cache and any Twig-level cache will happily serve a deleted review. Hook the moderation action (or a Doctrine postUpdate listener) to purge the relevant URLs, or set a short TTL on the block's cache key.
  • Admin routes need the right firewall. If the bundle's admin routes 404 or redirect to login loops, the import landed in the wrong routing file or outside the SuluAdmin firewall context. Compare against the other *_admin.yaml imports in a stock Sulu app.
  • Migrations and sulu:build are both required. Forgetting sulu:build after install leaves the admin list without its metadata and looks like a broken bundle. Forgetting the migration produces "table not found" on first admin visit.
  • API key handling. Put the key in .env as GOOGLE_PLACES_API_KEY and reference it from the bundle config; never commit it. If the bundle's config node only accepts a literal string, you can still pass an env var through Sulu's parameters — but confirm the container compiles with bin/console debug:container <service_id> before assuming the value reached the fetcher.
  • Debugging fetch failures. The fetch runs outside the request cycle, so errors surface in var/log/ only. Add a Monolog channel or a NotifierInterface-based alert around your cron wrapper; a silently expiring API key looks identical to "no new reviews this week."
  • Extension points to verify early: the Twig block template (overridable by copying into templates/bundles/DepaSuluGoogleReviewsBundle/), the admin list XML (overridable the same way), and the fetch service ID (decoratable). If none of those three are cleanly overridable, budget for a fork — with zero dependents, upstream fixes will not arrive on your schedule.
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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin