PHP code example of honey-odm / loupe

1. Go to this page and download the library: Download honey-odm/loupe library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

honey-odm / loupe example snippets




use DateTimeInterface;
use Honey\ODM\Core\Config\AsDocument;
use Honey\ODM\Core\Config\AsField;
use Honey\ODM\Core\Mapper\PropertyTransformer\DateTimeImmutableTransformer;
use Honey\ODM\Loupe\Config\AsAttribute;
use Honey\ODM\Loupe\Config\AsIndex;

#[AsDocument(collection: 'movies')] // <-- One SQLite database per collection
#[AsIndex(languages: ['en'], stopWords: ['the'], typoTolerance: false)]
final class Movie
{
    /**
     * @param list<string> $genres
     * @param array{lat: float, lng: float}|null $location
     */
    public function __construct(
        #[AsField(name: 'movie_id', primary: true)] // <-- Exactly 1 property must be marked as primary key
        public int $id,

        #[AsField(name: 'title')] // <-- Optionally set the field name on Loupe's side
        #[AsAttribute(sortable: true, searchable: true)]
        public string $name,

        #[AsField]
        #[AsAttribute(filterable: true)] // <-- Array attribute: `genres = 'Action'` means "contains"
        public array $genres = [],

        #[AsField]
        #[AsAttribute(filterable: true, sortable: true)]
        public ?int $year = null,

        #[AsField]
        #[AsAttribute(filterable: true)] // <-- Any attribute can carry geo filters, no reserved `_geo`
        public ?array $location = null,

        #[AsField(name: 'released_at', transformer: DateTimeImmutableTransformer::class)]
        #[AsAttribute(sortable: true)]
        public ?DateTimeInterface $releasedAt = null,
    ) {
    }
}



use Honey\ODM\Loupe\ObjectManagerFactory;

// On disk: one SQLite database per collection, under $dataDir/{collection}/
$objectManager = ObjectManagerFactory::create(dataDir: __DIR__ . '/var/loupe');

// In memory: nothing touches the filesystem - great for tests and ephemeral use
$objectManager = ObjectManagerFactory::create();

// Get a repository for your entity
$movieRepository = $objectManager->getRepository(Movie::class); // <-- Reads the AsDocument / AsField attributes automatically

use Honey\ODM\Core\Config\ClassMetadataRegistry;
use Honey\ODM\Loupe\Schema\SchemaUpdater;

$updater = new SchemaUpdater(
    $objectManager->transport->indexRegistry, // <-- LoupeTransport::$indexRegistry is public for exactly this
    new ClassMetadataRegistry(configurations: [Movie::class]),
);
$updater->updateSchema();



use Honey\ODM\Core\Criteria\Criteria;

use function Honey\ODM\Core\Criteria\field;

// Find all movies
$movies = $movieRepository->findAll();

// Find by ID
$movie = $movieRepository->find(1);

// Find by criteria (array of equality filters, AND-combined)
$movies = $movieRepository->findBy(['year' => 1977]);

// Find one by criteria
$movie = $movieRepository->findOneBy(['year' => 1977]);

// Using the portable Criteria API for complex queries
$movies = $movieRepository->findBy(
    Criteria::create()->where(field('genres')->equals('Action'))->orderBy('year', 'desc'),
);

$movie = new Movie(id: 1, name: 'Star Wars', genres: ['Action', 'SciFi'], year: 1977);

$objectManager->persist($movie);
$objectManager->flush();

$movie->year = 1978;
$objectManager->flush(); // <-- Change on $movie detected, Loupe updated

$objectManager->remove($movie);
$objectManager->flush(); // <-- $movie removed from Loupe

use Honey\ODM\Core\Criteria\Criteria;

use function Honey\ODM\Core\Criteria\field;
use function Honey\ODM\Core\Criteria\not;

$results = $movieRepository->findBy(
    Criteria::create()
        ->where(
            field('genres')->equals('Action'),
            not(field('year')->lessThan(1980)),
        )
        ->orderBy('year', 'desc')
        ->limit(10),
);

use Loupe\Loupe\SearchParameters;

$movies = $movieRepository->findBy(
    SearchParameters::create()
        ->withQuery('star wars')
        ->withFacets(['genres'])
        ->withAttributesToHighlight(['title']),
);

use Honey\ODM\Core\Config\ClassMetadataRegistry;
use Honey\ODM\Loupe\Schema\SchemaUpdater;

$updater = new SchemaUpdater(
    $objectManager->transport->indexRegistry,
    new ClassMetadataRegistry(configurations: [Movie::class, Actor::class]),
);

$updater->updateSchema(function (string $class, $metadata, bool $needsReindex) {
    if ($needsReindex) {
        // Loupe froze this index's configuration at creation time - your #[AsAttribute] /
        // #[AsIndex] attributes have since changed, and the stored data no longer matches them.
        // Deciding whether (and how) to re-index is an application concern, not this library's:
        // updateSchema() only ever reports drift, it never re-indexes on its own.
    }
});

$updater->dropSchema(function (string $class, $metadata) {
    // ...
});

use Honey\ODM\Core\Config\TransformerMetadata;

#[AsField(transformer: new TransformerMetadata(
    MyCustomTransformer::class,
    ['option1' => 'value1'],
))]
public mixed $myProperty;

use Honey\ODM\Core\Criteria\Criteria;
use Honey\ODM\Loupe\Repository\ObjectRepositoryInterface;
use Honey\ODM\Loupe\Repository\ObjectRepositoryTrait;

use function Honey\ODM\Core\Criteria\field;

/**
 * @implements ObjectRepositoryInterface<Movie>
 */
final class MovieRepository implements ObjectRepositoryInterface
{
    use ObjectRepositoryTrait;

    public function findReleasedAfter(int $year): iterable
    {
        return $this->findBy(Criteria::create()->where(field('year')->greaterThan($year)));
    }
}

$movieRepository = new MovieRepository($objectManager, Movie::class);
$objectManager->registerRepository(Movie::class, $movieRepository);

use Honey\ODM\Core\Event\PrePersistEvent;
use Honey\ODM\Loupe\ObjectManagerFactory;

$eventDispatcher = new EventDispatcher(); // <-- Any PSR-14 compliant dispatcher
$objectManager = ObjectManagerFactory::create(eventDispatcher: $eventDispatcher);
$eventDispatcher->addListener(PrePersistEvent::class, function (PrePersistEvent $event) {
    var_dump($event->object); // <-- The object being persisted
});

use Honey\ODM\Core\Config\AsDocument;
use Honey\ODM\Loupe\ObjectManagerFactory;
use Loupe\Loupe\Configuration;

$objectManager = ObjectManagerFactory::create(
    configurator: function (Configuration $configuration, AsDocument $classMetadata): Configuration {
        // Replay whatever your production backend already declares - here, the settings you
        // keep for Meilisearch indexes.
        $settings = json_decode(file_get_contents(
            sprintf('%s/config/indexes/%s.json', __DIR__, $classMetadata->collection),
        ), true);

        return $configuration
            ->withFilterableAttributes($settings['filterableAttributes'])
            ->withSortableAttributes($settings['sortableAttributes'])
            ->withSearchableAttributes($settings['searchableAttributes']);
    },
);

$objectManager->transport->indexRegistry->drop($objectManager->getClassMetadata(Movie::class));