1. Go to this page and download the library: Download honey-odm/core 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 / core example snippets
namespace App;
use DateTimeInterface;
use Honey\ODM\Core\Config\AsDocument;
use Honey\ODM\Core\Config\AsField;
use Honey\ODM\Core\Config\TransformerMetadata;
use Honey\ODM\Core\Mapper\PropertyTransformer\DateTimeImmutableTransformer;
use Honey\ODM\Core\Mapper\PropertyTransformer\RelationTransformer;
#[AsDocument(collection: 'books')]
final class Book
{
public function __construct(
#[AsField(primary: true)]
public string $id,
#[AsField(name: 'title')]
public string $name,
#[AsField(name: 'author_id', transformer: RelationTransformer::class)]
public ?Author $author = null,
#[AsField(name: 'published_at', transformer: new TransformerMetadata(DateTimeImmutableTransformer::class, ['from_format' => 'Y-m-d', 'to_format' => 'Y-m-d']))]
public ?DateTimeInterface $publishedAt = null,
) {
}
}
use Honey\ODM\Core\Config\AsDocument;
use Honey\ODM\Core\Config\AsField;
use Honey\ODM\Meilisearch\Config as Meili;
#[AsDocument(collection: 'books')]
#[Meili\Document(rankingRules: ['words', 'typo', 'sort'])]
final class Book
{
public function __construct(
#[AsField(primary: true)]
#[Meili\Attribute(filterable: true, sortable: true)]
public int $id,
) {
}
}
use Honey\ODM\Core\Config\AsDocument;
use Honey\ODM\Core\Config\ClassMetadataRegistry;
$registry = new ClassMetadataRegistry(configurations: [
Book::class => new AsDocument(collection: 'books'),
]);
$registry = new ClassMetadataRegistry(configurations: [Book::class, Author::class]);
use Honey\ODM\Core\Criteria\Criteria;
use function Honey\ODM\Core\Criteria\field;
use function Honey\ODM\Core\Criteria\not;
$criteria = Criteria::create()
->search('gatsby')
->where(field('publishedAt')->greaterThan('1920-01-01'))
->andWhere(field('author')->in([1, 2, 3]))
->orWhere(not(field('name')->startsWith('Draft:')))
->orderBy('publishedAt', 'desc')
->orderBy('name')
->limit(20)
->offset(40);
$books = $objectManager->getRepository(Book::class)->findBy($criteria);
$repository->findBy(['name' => 'The Great Gatsby']); // shorthand for Criteria::fromArray([...])
$repository->findOneBy(['id' => '123']);
$repository->findAll();
field('summary')->exists(); // the key is present in the document, whatever its value - including null
field('summary')->isNotNull(); // the key is present AND its value is not null
field('summary')->isEmpty(); // the value is null, '', [] or {}
field('tags')->in(['monument', 'paris']); // tagged monument OR paris
field('tags')->hasAll(['monument', 'paris']); // tagged monument AND paris
field('coordinates')->withinGeoRadius(48.8566, 2.3522, 5000); // within 5 km of Paris
field('coordinates')->withinGeoBoundingBox(48.80, 2.22, 48.90, 2.47); // swLat, swLon, neLat, neLon
use Honey\ODM\Core\Criteria\Geo\BoundingBox;
use Honey\ODM\Core\Criteria\Geo\Coordinates;
use Honey\ODM\Core\Criteria\Geo\Radius;
new Coordinates(91.0, 0.0); // InvalidArgumentException: Invalid latitude
new Radius(new Coordinates(48.85, 2.35), -1); // InvalidArgumentException: Radius must be greater than 0
new BoundingBox(new Coordinates(48.9, 2.2), new Coordinates(48.8, 2.4)); // InvalidArgumentException
new Comparison('coordinates', Operator::WITHIN_GEO_RADIUS, $radius);
$criteria = Criteria::create()
->search('a bee on a flower')
->metadata('vector', $embedding)
->metadata('semanticRatio', 0.9);
use Honey\ODM\Core\Criteria\UnsupportedExpressionException;
throw UnsupportedExpressionException::expression($expression);
throw UnsupportedExpressionException::operator(Operator::STARTS_WITH);
throw UnsupportedExpressionException::feature('offset');
use Honey\ODM\Core\Manager\ObjectManager;
$objectManager = new ObjectManager(new MyTransport(...));
$objectManager = new ObjectManager(
transport: $transport,
classMetadataRegistry: new ClassMetadataRegistry(), // default
documentMapper: new DocumentMapper(), // default
eventDispatcher: $psr14EventDispatcher, // defaults to a no-op dispatcher
defaultFlushOptions: [], // implementation-specific options passed to the transport
repositoryFactory: null, // Closure(ObjectManager, class-string): ObjectRepositoryInterface
);
$book = new Book(id: '1', name: 'The Great Gatsby');
$objectManager->persist($book);
$objectManager->flush();
$objectManager->remove($book);
$objectManager->flush(['wait' => true]); // options are merged with $defaultFlushOptions
$book = $objectManager->find(Book::class, '1');
$books = $objectManager->getRepository(Book::class)->findBy(['name' => 'The Great Gatsby']);
$objectManager->clear(); // detaches everything and resets the Unit of Work
$objectManager = new ObjectManager(
transport: $transport,
repositoryFactory: fn (ObjectManager $om, string $className) => new MyRepository($om, $className),
);
$objectManager->registerRepository(Book::class, new BookRepository($objectManager, Book::class));
interface ObjectRepositoryInterface
{
public function findBy(Criteria|array|null $criteria): iterable;
public function findAll(): iterable;
public function findOneBy(Criteria|array $criteria): ?object;
public function find(mixed $id): ?object;
}
$book1 = $objectManager->find(Book::class, '123');
$book2 = $objectManager->find(Book::class, '123');
var_dump($book1 === $book2); // true - same instance returned
use Honey\ODM\Core\Event\PrePersistEvent;
$eventDispatcher->addListener(PrePersistEvent::class, function (PrePersistEvent $event) {
$event->object->createdAt = new DateTimeImmutable();
});
use Honey\ODM\Core\Config\AsField;
use Honey\ODM\Core\Mapper\MappingContextInterface;
use Honey\ODM\Core\Mapper\PropertyTransformer\PropertyTransformerInterface;
final class MoneyTransformer implements PropertyTransformerInterface
{
public function fromDocument(mixed $value, AsField $propertyMetadata, MappingContextInterface $context): ?Money
{
return null === $value ? null : Money::fromCents($value);
}
public function toDocument(mixed $value, AsField $propertyMetadata, MappingContextInterface $context): ?int
{
return $value?->cents;
}
}
use Honey\ODM\Core\Mapper\DocumentMapper;
use Honey\ODM\Core\Mapper\PropertyTransformer\PropertyTransformers;
$transformers = new PropertyTransformers();
$transformers->register(new MoneyTransformer());
$objectManager = new ObjectManager(
transport: $transport,
documentMapper: new DocumentMapper(transformers: $transformers),
);
use Honey\ODM\Core\Manager\ObjectManager;
use Honey\ODM\Core\Transport\InMemoryTransport;
$transport = new InMemoryTransport();
$objectManager = new ObjectManager($transport);
$objectManager->persist(new Book('123', 'The Great Gatsby'));
$objectManager->flush();
$books = $objectManager->getRepository(Book::class)->findBy(
Criteria::create()->where(field('name')->contains('Gatsby')),
);
$transport->storage['books'] = [
'123' => ['id' => '123', 'title' => 'The Great Gatsby', 'author_id' => 1],
];
interface TransportInterface
{
public function flushPendingOperations(UnitOfWork $unitOfWork, array $flushOptions = []): void;
/**
* @param AsDocument<object> $classMetadata
* @return iterable<array<string, mixed>>
* @throws UnsupportedExpressionException
*/
public function retrieveDocuments(AsDocument $classMetadata, Criteria $criteria): iterable;
/**
* @param AsDocument<object> $classMetadata
* @return array<string, mixed>|null
*/
public function retrieveDocumentById(AsDocument $classMetadata, mixed $id): ?array;
}
use Honey\ODM\Core\Mapper\MappingContext;
use Honey\ODM\Core\Transport\TransportInterface;
use Honey\ODM\Core\UnitOfWork\UnitOfWork;
final class RestTransport implements TransportInterface
{
public function __construct(
private ClientInterface $httpClient,
private string $baseUrl,
) {
}
public function flushPendingOperations(UnitOfWork $unitOfWork, array $flushOptions = []): void
{
$objectManager = $unitOfWork->objectManager;
$registry = $objectManager->classMetadataRegistry;
$mapper = $objectManager->documentMapper;
foreach ($unitOfWork->getPendingUpserts() as $object) {
$classMetadata = $registry->getClassMetadata($object::class);
$context = new MappingContext($classMetadata, $objectManager, $object, []);
$document = $mapper->objectToDocument($object, [], $context);
$id = $objectManager->getIdentifier($object);
$endpoint = $this->baseUrl . '/' . $classMetadata->collection;
$this->httpClient->put("{$endpoint}/{$id}", ['json' => $document]);
}
foreach ($unitOfWork->getPendingDeletes() as $object) {
$classMetadata = $registry->getClassMetadata($object::class);
$id = $objectManager->getIdentifier($object); // Doesn't initialize lazy objects
$this->httpClient->delete("{$this->baseUrl}/{$classMetadata->collection}/{$id}");
}
}
// retrieveDocuments() / retrieveDocumentById() omitted for brevity
}
namespace MyODM\Config;
use Attribute;
use Honey\ODM\Core\Config\PlatformMetadataInterface;
#[Attribute(Attribute::TARGET_CLASS)]
final readonly class Collection implements PlatformMetadataInterface
{
public function __construct(
public ?int $shards = null,
) {
}
}
$objectManager = new ObjectManager(new RestTransport($httpClient, 'https://api.example.com'));
$book = new Book(id: '1', name: 'The Great Gatsby');
$objectManager->persist($book);
$objectManager->flush(); // HTTP PUT /books/1
$foundBook = $objectManager->find(Book::class, '1'); // HTTP GET /books/1
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.