sohophp/sofinder-core
sofinder-core provides the foundational search and discovery layer for SOFinder, with lightweight Laravel/PHP utilities for indexing, querying, and result handling. A compact core for building finder-style features.
sohophp/sofinder-core is a very young package (0 stars, 0 dependents, essentially no external documentation), so treat the repository itself as the documentation. The provided agents/AGENTS.md only defines how to run commands, not what the package does — plan to read source before writing any integration code.
First steps, in order:
Read composer.json.
sohophp/sofinder-core) and latest version constraint.autoload — it may differ from the vendor/package name, which affects your use statements.config.platform.php: this is the minimum dependency-resolution target, not the interpreter you run locally. Keep the two separate in your head.Check .php-version and scripts/.
This repo does not allow bare php/composer. Local PHP is declared in .php-version; all commands must go through the wrappers:
./scripts/php-bin.sh -v
./scripts/composer.sh install
./scripts/php-bin.sh vendor/bin/phpunit
Inspect src/ for the surface area. Look for a *ServiceProvider, a Facade, a Manager, and any Contracts/ or Concerns/ directory. Those tell you whether it's a driver-based search/finder abstraction or a single-purpose service.
Check Laravel auto-discovery. In composer.json, look for:
"extra": { "laravel": { "providers": ["Sohophp\\SoFinder\\SoFinderServiceProvider"] } }
If it's absent, register manually in bootstrap/providers.php (Laravel 11+) or config/app.php.
Install into a scratch Laravel app, not your main project:
./scripts/composer.sh require sohophp/sofinder-core
./scripts/php-bin.sh artisan vendor:publish --provider="Sohophp\\SoFinder\\SoFinderServiceProvider"
First use case: get the smallest possible "find/lookup" call working from artisan tinker before touching application code. Confirm the container resolves the binding, confirm config is published, confirm a happy-path result. Only then wire it into a controller or job.
Configuration-first, always. Publish the config file into config/sofinder.php and edit that — never modify files under vendor/. If the package has no publishable config, keep your own config/finder.php that reads from env() and feeds the package constructor.
Wrap the package behind an app-level adapter. At 0 stars and 0 dependents, the API is not stable and there is no community knowledge base. Protect your domain from it:
namespace App\Support\Finder;
use Sohophp\SoFinder\Contracts\Finder; // adjust to the real contract/class
final class FinderAdapter
{
public function __construct(private readonly Finder $finder) {}
public function find(array $criteria): array
{
return $this->finder->find($criteria); // map to your DTOs here
}
}
Bind the vendor implementation to your adapter in a dedicated FinderServiceProvider, and bind your own interface to the adapter. Swapping the package later then touches one file.
Constructor injection over facades. Facades are convenient for prototyping, but constructor-injecting the underlying service (or your adapter) is what makes this testable and what lets you $this->app->instance(...) in tests.
Service-provider binding pattern:
public function register(): void
{
$this->app->singleton(Finder::class, fn ($app) =>
$app->make(YourAdapter::class)
);
}
Batch/queued usage. If the package performs lookups against an index or remote source, do those inside a queued job or artisan command and cache results. Do not call a finder synchronously in a hot request path until you've measured it.
Testing pattern. Because there is no built-in fake, create a stub implementation of the package's interface (or mock your adapter). Register it via $this->swap(...) / $this->instance(...) in your test's setUp. This is the main reason to wrap the package rather than call it directly.
Local dev workflow. Run everything through the repo's scripts:
./scripts/php-bin.sh artisan test
./scripts/php-bin.sh artisan tinker
./scripts/php-bin.sh artisan config:clear
Never invoke bare php or composer in this repo. The rules are explicit: use ./scripts/php-bin.sh and ./scripts/composer.sh. Scripts that silently call php directly will break against .php-version.
Two different PHP versions matter. .php-version selects your local interpreter; composer.json's config.platform.php is only the minimum target for dependency resolution. A package that installs cleanly can still fail at runtime on your local PHP — or vice versa in CI. Check both.
Sparse documentation is the biggest risk. With 0 stars and 0 dependents there are effectively no blog posts, no Stack Overflow answers, and no third-party integrations to copy. Budget time for source-reading, and pin an exact version in composer.json so a silent patch release can't change behavior under you.
Verify the version before trusting the release date. The metadata shows a release dated 2026-10-15, which is anomalous. Confirm with ./scripts/composer.sh show sohophp/sofinder-core --all and pin a real, existing constraint.
Auto-discovery is not guaranteed. If you get "Target class ... does not exist" or "Class not found", the provider isn't registered. Add it to bootstrap/providers.php manually.
Config caching after publishing. If the config looks ignored, you're probably looking at a cached copy:
./scripts/php-bin.sh artisan config:clear
Remember to re-run config:cache in production.
Namespace mismatch. PSR-4 autoload namespaces frequently don't match the Composer package name. Check autoload.psr-4 before writing use statements; an IDE will happily suggest the wrong one.
Debugging tips.
./scripts/php-bin.sh artisan tinker → app()->bound(Finder::class) to confirm registration.dd(app(Finder::class)) to inspect the resolved object's class and constructor args.try/catch and dump() the exception message — with no docs, the package's own exception messages are your best source of truth.Extension points to look for. If src/Contracts/ exists, prefer implementing those interfaces over extending concrete classes — contracts are far more likely to survive minor releases. If there are no contracts, use the Decorator pattern around your adapter instead of subclassing.
License is MIT — permissive and fine for commercial use; just keep the license file if you vendor or fork it.
Keep vendor types out of your public API. Don't type-hint vendor classes in controllers, models, or events. Return your own DTOs from the adapter so a future removal of this package doesn't ripple through your codebase.
How can I help you explore Laravel packages today?