まず、基本的なクエリビルダーを使用してこれを行う方法を見てみましょう。次に、Eloquentモデルを使用してこのクエリを実行する方法について説明します。
function paginateDishesFromPoint(Point $point, $pageSize)
{
$distanceField = "ST_Distance_Sphere(locations.coordinates, "
. "ST_GeomFromText('{$point->toWKT()}') AS distance";
return DB::table('dishes')
->select('dishes.*', DB::raw($distanceField))
->join('dish_locations', 'dish_locations.dish_id', '=', 'dishes.id')
->join('locations', 'locations.id', '=', 'dish_locations.location_id')
->orderBy('distance')
->paginate($pageSize);
}
ST_Distance_Sphere()
関数は、結果を並べ替えることができる距離を計算します。 Laravelのpaginate()
メソッドは、page
を使用して自動ページネーションを実行します リクエストURLを介して渡されるパラメータ。 ページネーションドキュメント
を読む 詳細については。上記の関数を使用すると、次のようにページ化された結果セットをフェッチできます。
$point = new Point($latitude, $longitude);
$sortedDishes = paginateDishesFromPoint($point, 15);
...ここでPoint
Grimzy\LaravelMysqlSpatial\Types\Point
です パッケージ
のクラス 使用している、および15
はページあたりの結果の数です。
それでは、Eloquentモデルでこれを試してみましょう。 ローカルクエリスコープ を使用します 順序付けを実行するクエリの部分を作成するために必要なロジックをカプセル化するには:
class Dish extends Model
{
...
public function locations()
{
return $this->belongsToMany(App\Location::class);
}
public function scopeOrderByDistanceFrom($query, Point $point)
{
$relation = $this->locations();
$locationsTable = $relation->getRelated()->getTable();
$distanceField = "ST_Distance_Sphere($locationsTable.coordinates, "
. "ST_GeomFromText('{$point->toWKT()}') AS distance";
return $query
->select($this->getTable() . '.*', DB::raw($distanceField))
->join(
$relation->getTable(),
$relation->getQualifiedForeignKeyName(),
'=',
$relation->getQualifiedParentKeyName()
)
->join(
$locationsTable,
$relation->getRelated()->getQualifiedKeyName(),
'=',
$relation->getQualifiedRelatedKeyName()
)
->orderBy('distance');
}
}
この実装では、モデルのメタデータを使用してテーブル名とフィールド名をクエリに追加するため、変更された場合にこのメソッドを更新する必要はありません。これで、モデルを使用して順序集合をフェッチできます:
$point = new Point($latitude, $longitude);
$sortedDishes = Dish::orderByDistanceFrom($point)->paginate($pageSize);
$sortedDishes
LaravelのLengthAwarePaginator
のインスタンスです Collection
をラップします モデルの。結果をビューに渡す場合、Bladeテンプレートに結果を表示する方法は次のとおりです。
<ul>
@foreach($sortedDishes as $dish)
<li>{{ $dish->name }} is {{ $dish->distance }} meters away.</li>
@endforeach
</ul>
<a href="{{ $sortedDishes->nextPageUrl() }}">Load more...</a>
上に示したように、paginatorは便利なメソッド を提供します ページ結果間を簡単に移動するために使用できます。
または、AJAXリクエストを使用して結果を読み込むこともできます。必ず現在のページ+1を渡すようにしてください page
リクエストデータのパラメータ。