1. Go to this page and download the library: Download ponito/elastico 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/ */
// like → match query (strips % wildcards)
Article::where('title', 'like', '%elasticsearch%')->get();
Article::orderBy('published_at', 'desc')->get();
// With missing value handling
Article::orderBy('score', 'desc', missing: '_last')->get();
// With nested sort
Article::orderBy('comments.likes', 'desc', nested: ['path' => 'comments'])->get();
Article::limit(20)->offset(40)->get();
Article::paginate(20);
// Total hits are preserved even with limit
$results = Article::limit(10)->get();
$results->total(); // full match count
use Elastico\Mapping\RuntimeField;
use Elastico\Mapping\FieldType;
Article::runtimeField('day_of_week', new RuntimeField(
type: FieldType::keyword,
script: "emit(doc['published_at'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))",
))->get();
// Lazy collection — streams all matching docs without memory overhead
Article::where('status', 'published')->cursor()->each(function ($article) {
// process
});
// Execute multiple queries in a single HTTP round-trip
[$published, $drafts] = $builder->getMany([
Article::where('status', 'published'),
Article::where('status', 'draft'),
]);
// Inspect the Elasticsearch DSL payload
$payload = Article::where('status', 'published')->toSql();
use Elastico\Aggregations\Metric\Avg;
use Elastico\Aggregations\Metric\Sum;
use Elastico\Aggregations\Metric\Min;
use Elastico\Aggregations\Metric\Max;
use Elastico\Aggregations\Metric\Cardinality;
use Elastico\Aggregations\Metric\ValueCount;
use Elastico\Aggregations\Metric\Stats;
use Elastico\Aggregations\Metric\Percentiles;
use Elastico\Aggregations\Metric\TopHits;
$results = Article::where('status', 'published')
->addAggregation('avg_score', new Avg('score'))
->addAggregation('total_views', new Sum('views'))
->addAggregation('authors', new Cardinality('author_id'))
->limit(0) // set to 0 if you only need aggregation results
->get();
$avgScore = $results->aggregation('avg_score')->value();
$totalViews = $results->aggregation('total_views')->value();
$authCount = $results->aggregation('authors')->value();
use Elastico\Aggregations\Bucket\Terms;
use Elastico\Aggregations\Bucket\DateHistogram;
use Elastico\Aggregations\Bucket\Histogram;
use Elastico\Aggregations\Bucket\Range;
use Elastico\Aggregations\Bucket\Filter;
use Elastico\Aggregations\Bucket\Nested;
$results = Article::addAggregation(
'by_status',
new Terms('status', size: 10)
)->limit(0)->get();
foreach ($results->aggregation('by_status')->buckets() as $bucket) {
echo "{$bucket['key']}: {$bucket['doc_count']}\n";
}
$byStatus = (new Terms('status', size: 10))
->addAggregation('avg_score', new Avg('score'));
$results = Article::addAggregation('by_status', $byStatus)->limit(0)->get();
foreach ($results->aggregation('by_status')->buckets() as $bucket) {
$avg = $bucket->aggregation('avg_score')->value();
}
use Elastico\Scripting\Increment;
$article->update(new Increment(field: 'views', amount: 1));
// With additional fields to set alongside
$article->update(new Increment(field: 'views', amount: 1, extra: ['last_viewed_at' => now()]));
// Decrement
Article::where('status', 'active')->decrement('priority', 5);
use Elastico\Scripting\UpdateParams;
$article->update(
(new UpdateParams(['multiplier' => 2]))
->withModel(['score' => 100]) // merges with model fields
);
$results = Article::addAggregation('by_status', new Terms('status'))
->postWhere('status', 'published') // filters hits but not aggs
->get();
use Elastico\ILM\Policy;
use Elastico\ILM\Phases\HotPhase;
use Elastico\ILM\Phases\WarmPhase;
use Elastico\ILM\Phases\DeletePhase;
use Elastico\ILM\Actions\RolloverAction;
use Elastico\ILM\Actions\ReadOnlyAction;
use Elastico\ILM\Actions\DeleteAction;
use Elastico\ILM\Actions\ForceMergeAction;
$policy = new Policy(
id: 'articles-policy',
hot_phase: new HotPhase(
min_age: '0ms',
rollover: new RolloverAction(max_age: '7d', max_size: '50gb'),
),
warm_phase: new WarmPhase(
min_age: '7d',
read_only: new ReadOnlyAction(),
force_merge: new ForceMergeAction(max_num_segments: 1),
),
delete_phase: new DeletePhase(
min_age: '90d',
delete: new DeleteAction(),
),
);
class Article extends Model
{
// Elasticsearch-to-Elasticsearch
public function comments(): HasMany
{
return $this->hasMany(Comment::class, 'article_id');
}
// Embedded documents
public function metadata(): EmbedsOne
{
return $this->embedsOne(ArticleMetadata::class);
}
// Hybrid: Elasticsearch model → SQL model
public function author(): BelongsTo
{
return $this->belongsTo(\App\Models\User::class, 'author_id');
}
}