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

Pandosearch Bundle Laravel Package

printdeal/pandosearch-bundle

Symfony bundle that integrates the PandoSearch search service into your application, providing configuration and services to index content and run fast, relevant searches with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there is no service provider, facade, or config/pandosearch.php. A Laravel developer picking it up should treat it as a reference implementation and port the thin client logic rather than installing it.

Minimal steps for a Symfony app:

  1. Install (expect version friction — last tagged release is Nov 2018):

    composer require printdeal/pandosearch-bundle
    

    You will likely need --with-all-dependencies and may have to pin symfony/http-kernel or Guzzle to versions contemporary with PHP 7.1–7.3.

  2. Register the bundle — in legacy apps, AppKernel::registerBundles(); in Symfony 4/5 Flex apps, config/bundles.php:

    Printdeal\PandosearchBundle\PrintdealPandosearchBundle::class => ['all' => true],
    
  3. Configure it — create config/packages/pandosearch.yaml (or config.yml in Symfony 3). Because the bundle is archived and docs are sparse, open DependencyInjection/Configuration.php first to confirm the exact root key and option names before trusting any snippet:

    pandosearch:
        host: https://api.pandosearch.com
        api_key: '%env(PANDO_API_KEY)%'
        # index / default search options as defined in Configuration.php
    
  4. Where to look first, in order:

    • DependencyInjection/Configuration.php — the authoritative list of config keys.
    • Resources/config/services.yml (or .xml) — the service ID you will inject.
    • The client/transport class under src/ — this is what you actually call.
  5. First use case — inject the client and run a search in a controller:

    public function search(Request $request, PandosearchClient $client): Response
    {
        $results = $client->search($request->query->get('q', ''), ['limit' => 10]);
    
        return $this->render('search/results.html.twig', ['results' => $results]);
    }
    

    Verify the method name against the source; the bundle wraps Pandosearch's REST API, so search, suggest, and index/update operations are the expected surface.

Budget half a day for the first integration, most of it spent on dependency resolution and confirming the API contract in source — not on writing application code.

Implementation Patterns

Isolate the vendor client behind your own service. Never let controllers or Twig talk to the bundle's client directly. Create App\Search\SearchGateway that wraps it with typed inputs/outputs. This is the single highest-value pattern here, because the package is archived and you will eventually swap it for direct Guzzle/PSR-18 calls or a maintained SDK. With a gateway in place that swap is a one-file change.

final class SearchGateway
{
    public function __construct(private PandosearchClient $client) {}

    public function find(string $term, int $limit = 10): array
    {
        try {
            return $this->client->search($term, ['limit' => $limit])['results'] ?? [];
        } catch (\Throwable $e) {
            $this->logger->error('pandosearch search failed', ['term' => $term, 'e' => $e]);
            return []; // degrade gracefully
        }
    }
}

Controller → Twig flow. Keep pagination, sorting, and filter mapping in the controller or a form/model object; pass a normalized array to the template. Do not pass the raw vendor response into Twig — the shape is not under your control.

Autocomplete endpoint. Wire a small JSON action that calls the suggestion/suggest method and returns a trimmed array. Cache aggressively (see below) — type-ahead traffic is the biggest volume driver against a metered search API.

Indexing. The idiomatic Symfony approach is an event subscriber or postPersist/postUpdate listener on the entities you index, pushing documents to Pandosearch. Better: dispatch a domain event and consume it from a queued listener (Symfony Messenger) so a slow external API never blocks a write. Also provide an app:search:reindex console command that iterates your content in batches — you will need it after every schema/mapping change.

Testing. Because the client is a concrete service, define an interface in your app (e.g. SearchGatewayInterface) and mock that in tests. If you must test the bundle client itself, mock its underlying HTTP transport (Guzzle handler stack / MockHandler) rather than hitting the network. Add a single integration test gated behind an env var that hits a staging index.

Environment separation. Point host/index name at different values per environment via .env. Never share an index name between dev and prod — you will pollute production results.

Gotchas and Tips

  • Archived status is the headline risk. No security patches, no PHP 8 / Symfony 5+ support, zero dependents and zero stars means effectively no community. Treat it as vendored code you now own. If a composer update breaks it, you fix it or fork it.
  • Dependency conflicts. A 2018 bundle will pull old Guzzle/PSR versions that clash with modern Symfony HTTP clients. If resolution fails, fork the repo, relax the constraints in its composer.json, and require it via a VCS repositories entry.
  • Config key names are not documented reliably. The Configuration.php node tree is the source of truth. Common failure mode is a silently-ignored key that only surfaces as a runtime 401/404 from the API.
  • API key handling. Put it in .env (PANDO_API_KEY) and reference via %env()%. Never commit it; the bundle will not mask it in exception traces, so avoid dumping the resolved config in dev.
  • No timeouts by default is common in bundles of this era. A hung external call will hang your request. Configure the HTTP transport timeout explicitly; if the bundle doesn't expose it, decorate/replace the client service in your app's services.yaml.
  • Handle failures, always. Search is a non-critical path. Wrap calls, log, and return an empty result set or cached result — never let the search API take down a page render.
  • Cache reads. Wrap find/suggest in Symfony Cache (cache.app or a Redis pool) keyed by normalized query + filters, TTL of 60–300s. This alone can cut API spend dramatically.
  • Debugging. Enable the HTTP client's logging middleware or Symfony's profiler HTTP panel (if the transport is a supported client) to see the actual request/response. Logging the outbound URL and status code catches most misconfiguration.
  • Result shape drift. The vendor's response is a plain array. Normalize into your own DTOs inside the gateway so a future API change or client swap touches one class, not every template.
  • Migration path. For a new project, skip the bundle entirely: it's ~a thin wrapper over HTTP. Write a small SearchClient using Laravel's Http facade or Symfony HttpClient, 50–100 lines, fully typed and under your control. That is a better long-term bet than reviving a dead bundle.
  • Extension points are minimal. There is no plugin system to speak of; customization means overriding the service definition (compiler pass or services.yaml override) or forking. Don't plan an architecture that assumes you can extend it cleanly.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
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