В этом уроке мы создадим веб-сайт с минимальной лирикой, используя Laravel Scout и Algolia . Для этого нам нужно приложение CRUD для работы с нашими данными и интерфейс поиска, чтобы пользователи могли осуществлять поиск по содержимому. Однако вместо того, чтобы создавать полное приложение с нуля, давайте просто установим готовое приложение CRUD , которое мы создали для этого урока.
Algolia — это размещенный API поисковых систем, предоставляющий нам все инструменты и ресурсы, которые нам когда-либо понадобятся для создания продуктов с потрясающими возможностями поиска.
К концу урока у нас будет такой продукт:
Начальная загрузка приложения
Я предполагаю, что у вас уже есть среда разработки. Однако, если вам нужна хорошая среда разработки, чтобы сразу приступить к действиям, вы должны использовать Homestead Improved .
Незнакомец Бродяге? Прочитайте это . Хотите углубиться? Купите нашу книгу о среде PHP!
Не стесняйтесь пропустить эту часть, если у вас уже есть подобное приложение или у вас достаточно опыта, чтобы создать его относительно быстро.
Приложение CRUD
Самый удобный способ скачать готовый проект CRUD — это клонировать его:
git clone [email protected]:lavary/lyrics-crud.git coolyrics cd coolyrics composer install
Настройка базы данных
Теперь давайте создадим базу данных MySQL. Приведенные ниже настройки применяются к улучшенной среде Homestead, упомянутой выше. Изменить по мере необходимости.
mysql -h localhost -u homestead -psecret mysql> CREATE DATABASE lyrics
После того, как база данных была создана, мы создаем копию .env.example
(находится в корневом каталоге нашего проекта) и .env
ее .env
. Здесь мы помещаем наши учетные данные базы данных:
#... DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=lyrics DB_USERNAME=root DB_PASSWORD=password # ...
Опять же, обратитесь к своим предпочтениям по мере необходимости.
Теперь мы запускаем команду migration
для создания таблиц:
php artisan migrate
Заполнение базы данных образцами данных
Сайт с текстами песен содержит информацию о музыкантах и их работах, и, конечно же, тексты их песен. Чтобы создать минимальную структуру данных, мы создали только две модели Eloquent для этого проекта, а именно Artist
и Song
. Модель Artist
имеет отношение один-ко-многим с моделью Song
. Это означает, что у каждого исполнителя может быть много песен, и каждая песня принадлежит исполнителю в нашей базе данных.
Прежде чем перейти к следующему разделу, вы можете продолжить и вставить несколько записей в базу данных, начиная с ваших любимых исполнителей, а затем добавив несколько песен для каждой.
Это то, что мы имеем до сих пор:
Вы также можете использовать файл SQL, включенный в файлы проекта, и выгрузить его в свою базу данных с помощью следующей команды:
mysql -h localhost -u {USERNAME} -p{PASSWORD} lyrics < /path/to/the/sql/file
Вы также можете импортировать файл с помощью вашего любимого приложения для управления MySQL, такого как Sequel Pro, MySQL Workbench или PHPMyAdmin.
Установка Скаута
Давайте продолжим, установив Scout:
composer require laravel/scout
Затем мы добавляем поставщика услуг в $providers
в файле config/app.php
:
Laravel\Scout\ScoutServiceProvider::class,
Теперь нам нужно сгенерировать файл конфигурации Scout с помощью команды publish:config
artisan:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
В результате в каталоге конфигурации создается файл конфигурации с именем scout.php
. Мы отредактируем этот файл позже.
Чтобы сделать модель данных доступной для поиска, нам нужно использовать черту Laravel\Scout\Searchable
внутри соответствующего класса модели. Это модель Song
в нашем случае:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Searchable; class Song extends Model { use Searchable; protected $fillable = ['title', 'album', 'lyrics', 'youtube_link']; public function artist() { return $this->belongsTo('App\Artist'); } }
Настройка Алголии
Как и планировалось, мы будем использовать Algolia в качестве API для поисковых систем.
Во-первых, давайте создадим учетную запись для получения идентификатора нашего приложения . Для работы Scout требуется идентификатор приложения и ключ API администратора . После завершения регистрации мы можем найти наши учетные данные в разделе « Ключи API» в левом меню.
Теперь мы открываем файл конфигурации config/scout.php
и помещаем туда свои учетные данные:
<?php 'algolia' => [ 'id' => env('ALGOLIA_APP_ID', ''), 'secret' => env('ALGOLIA_SECRET', ''), ],
Рекомендуется хранить ключи в .env
и загружать их в scout.php
с помощью scout.php
env()
или getenv()
.
Чтобы использовать API Algolia, нам нужно установить SDK Algolia для PHP, который также доступен в виде пакета Composer:
composer require algolia/algoliasearch-client-php
Индексация наших данных
На данный момент нам нужно создать наш индекс по Алголии. Каждая запись в индексе представляет собой объект JSON без схемы (каждая представляет запись в нашей базе данных) с набором атрибутов, которые можно использовать для поиска, отображения, ранжирования и фильтрации данных.
Вместо индексации всей записи нам нужно только проиндексировать данные, необходимые для вышеуказанных операций. Это помогает сохранить наш индекс чистым и оптимизированным.
Кроме того, индекс не является реляционной базой данных, а это означает, что при поиске по индексу мы не можем использовать сложные операторы where
или SQL-соединения. Чтобы обойти это ограничение, мы должны определить пользовательскую структуру для наших записей индекса. С другой стороны, мы должны объединить все необходимые таблицы, подготовив настроенный объект JSON перед индексацией.
Для этого мы переопределяем метод toSearchableArray()
в модели Song
(этот метод добавляется в класс с помощью признака Laravel\Scout\Searchable
). По умолчанию метод toSearchableArray()
возвращает вывод $this->toArray()
качестве нашего индексного объекта (при отправке индексной записи в Algolia), тогда как нам нужны дополнительные данные, такие как имя исполнителя , жанры и URL изображения , которые находятся в другом столе — стол artists
.
Вот как мы это делаем:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Laravel\Scout\Searchable; class Song extends Model { use Searchable; protected $fillable = ['title', 'album', 'lyrics', 'youtube_link']; public function toSearchableArray() { $genres = array_map(function($item) { return trim($item); }, explode(',', $this->artist->genres)); return array_merge( $this->toArray(), ['artist' => $this->artist->name, 'photo' => $this->artist->photo, 'genres' => $genres]); } public function artist() { return $this->belongsTo('App\Artist'); } }
Поскольку поле genres
может содержать в нашей базе данных значение, разделенное запятыми (в нашем приложении CRUD оно имеет простое текстовое поле), мы разделяем жанры с помощью explode
. Затем мы перебираем результаты, удаляя ненужные пробелы до и после каждой части, используя функцию map()
:
<?php // ... $genres = array_map(function($item) { return trim($item); }, explode(',', $this->artist->genres)); // ...
Наконец, мы объединяем выходные данные $this->toArray()
с нашими желаемыми атрибутами, возвращая окончательный массив.
<?php // ... return array_merge( $this->toArray(), ['artist' => $this->artist->name, 'photo' => $this->artist->photo, 'genres' => $genres]); // ...
Почему мы должны индексировать случайно сгенерированную строку, такую как URL изображения, которая может вас заинтересовать. Мы вернемся к этому в ближайшее время.
Для существующих записей в базе данных мы можем импортировать индекс сразу с помощью команды scout:import
artisan, например:
php artisan scout:import "App\Song"
Когда процесс индексирования завершен, мы можем увидеть индекс по Алголии, перейдя в раздел Индексы и выбрав имя нашего индекса в раскрывающемся меню:
Индексация не является одноразовой задачей. После первоначального импорта индекс необходимо синхронизировать с базой данных. Поскольку мы используем Скаут, обо всем уже позаботились. Отныне, каждый раз, когда запись вставляется, обновляется или удаляется из базы данных, соответствующая индексная запись будет соответственно изменяться — благодаря наблюдателям модели Laravel.
Чтобы узнать больше о том, как Scout управляет процессом индексации, ознакомьтесь с документацией .
Настройка Алголии
Следующее, что нужно сделать, это настроить наш индекс Алголии для оптимальной работы. Эти параметры могут быть изменены либо из панели управления, либо программно с помощью API Algolia.
Наиболее важными параметрами конфигурации являются атрибуты поиска и пользовательские атрибуты ранжирования .
Параметр «Атрибуты поиска» определяет, какие атрибуты записи используются для поиска. Порядок этих атрибутов также имеет значение, так как те, которые находятся сверху, считаются более важными и контролируют рейтинг.
Параметр «Атрибуты пользовательского рейтинга» указывает на популярность каждой записи, что также влияет на рейтинг. Они могут быть чем угодно: от количества лайков, просмотров, загрузок до комментариев. Тем не менее, мы должны включить эту информацию в индекс.
Алголия поставляется с большим количеством вариантов конфигурации. Работа с каждым параметром выходит за рамки данного руководства. Чтобы узнать больше о параметрах конфигурации, вам следует взглянуть на часто задаваемые вопросы Algolia о конфигурации и актуальности.
Веб-сайт
Последнее, что нужно сделать, — это реализовать интерфейс поиска на нашем сайте текстов песен. Преимущество Algolia в том, что он не ограничивает нас какой-либо реализацией интерфейса.
Традиционные реализации поиска имеют тенденцию иметь логику поиска на бэкэнде. Чтобы достичь этого, мы можем использовать Eloquent для поиска в записях, используя метод search()
(предоставленный признаком Searchable
). Этот метод немного медленнее, поскольку поисковый запрос проходит через различные уровни абстракции. Это можно сделать так:
<?php // ... use Illuminate\Http\Request; Route::get('/search', function (Request $request) { return App\Song::search($request->search)->get(); }); // ...
Другой способ — напрямую отправлять поисковые запросы из браузера пользователя в поисковый API Algolia, предоставляя нашим пользователям возможность поиска по мере ввода. Этот метод намного быстрее, чем первый, так как здесь нет интерфейса. Это означает, что каждый атрибут, который мы хотим в наших результатах поиска, должен присутствовать в самом индексе.
В этом уроке мы воспользуемся вторым подходом. Мы используем Scout для индексации и синхронизации нашего индекса с нашей базой данных, затем мы используем API Algolia для поиска.
При втором подходе у нас будет много вариантов отображения результатов. Мы можем использовать AngularJS, Vue.js или две популярные библиотеки Algolia, а именно Autocomplete и Instantsearch.js .
Для этого проекта мы будем использовать Instantsearch.js
, который представляет собой библиотеку виджетов пользовательского интерфейса на основе React, что позволяет без труда создавать интерфейсы поиска.
Наш веб-сайт с текстами песен состоит из двух страниц, главной страницы поиска и одной страницы для отображения сведений о песне.
Сначала давайте создадим маршруты и контроллеры для этих двух страниц. Тогда мы создадим представления.
Файл: routes/web.php
<?php //... Route::get('/', 'LyricsController@search'); Route::get('song/{id}', 'LyricsController@lyric'); // ...
И контроллер:
php artisan make:controller LyricsController
Файл: app/Http/Controllers/LyricsController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Song; class LyricsController extends Controller { public function search() { return view('search'); } public function song(Request $request, $id) { $song = Song::find($id); return view('lyrics', compact('song')); } }
Методы song()
и search()
отображают страницы нашего сайта.
Во-первых, давайте создадим мастер-макет шаблона для наших страниц. Внутри resources/views/layouts
создайте файл с именем basic.blade.php
со следующим содержимым:
Файл: resources/views/layouts/basic.blade.php
<!DOCTYPE html> <html lang="{{ config('app.locale') }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{{ config('app.name', 'Coolyrics') }}</title> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- Styles --> <link rel="stylesheet" type="text/css" href="{{ asset('css/styles.css') }}"> </head> <body> @yield('content') @section('javascript') @show </body> </html>
Наличие отдельных разделов Blade для файлов CSS и JavaScript позволяет нам лучше контролировать глобальные и специфичные для страницы ресурсы, а также внутренний код Javascript для дочерних шаблонов.
На страницу также загружен файл CSS, чтобы сделать сайт немного более индивидуальным. Пожалуйста, не стесняйтесь менять стили, если вам не нравится их внешний вид.
В настоящее время давайте создадим файл с именем styles.css
в public/css
со следующим содержимым:
Файл: public/css/styles.css
html, body { height: 100%; } h2 { color: #888; font-size: 30pt; } #header { background: #34495e; color: #f1c40f; height: 80px; } #header .input-group { margin-top: 20px; } #header h1 { margin-left: 50px; font-size: 20pt; font-weight: bold; } #header h1 sup { font-size: 8pt; font-weight: normal; display: inline-block; } .dropdown-menu .ais-menu { padding: 5px 5px; } .dropdown-menu .ais-menu--item { border-bottom: #ccc 1px dotted; padding: 5px 25px 5px 15px; } .dropdown-menu .ais-menu--item:last-child { border: 0; } .container { padding: 35px; } .container-fluid { padding: 40px; } #hits-container { } .ais-hits__empty { height: 100%; font-size: 15pt; font-weight: bold; color: #888; } .ais-hits__empty p { font-size: 12pt; font-weight: normal; color: #999; padding-top: 5px; } .song { border-bottom: #ccc 1px dotted; padding: 20px; } .song a.song-link { color: #000; font-size: 15pt; display: block; } .song a.song-link em { font-style: normal; color: #000; font-weight: bold; } .song span { color: #888; display: block; } .song span.song-artist { margin: 3px 0; } .song-youtube-link { margin-top: 10px; } #pagination-container { text-align: center; font-size: 11pt; margin: 20px 0; } #login-link { font-weight: bold; text-transform: uppercase; line-height: 80px; } #login-link a { color: #fff; } /* to control the size of the thumbnail adjust the .thumbnail width and height */ .band-thumbnail { width: 90px; height: 90px; background-position: center; background-size: cover; margin-right: 30px; border-radius: 3px; } #lyrics-container { } #lyrics-container p { font-size: 13pt ; } h1 { font-size: 30pt; } #lyrics-container h1 span { color: #000; } #lyrics-header { background: #f5f5f5; padding: 60px 0; } #lyrics-album-details { font-size: 11pt; font-weight: normal; display: block; color: #888; margin-bottom: 20px; } #lyrics-album-details .glyphicon { color: #ccc; margin-right: 5px; } #lyrics-youtube-link { position: absolute; left: 0; bottom: 0; background: #cc181e; width: 100%; height: 30px; line-height: 30px; } #lyrics-youtube-link a { color: #fff; } #lyrics-thumbnail { position: relative; width: 370px; height: 220px; margin: 0 auto; } #post-meta { margin: 15px 0; } #post-meta span { color: #ccc; font-size: 10pt; font-weight: normal; margin: 5px 0; } #lyrics-content { background-color: #f1f1f1; padding: 40px 0; } .btn-xs .glyphicon { color: #888; font-size: 8pt; }
Страница с текстами песен
Теперь мы создаем файл с именем song.blade.php
внутри resources/views
со следующим содержанием:
Файл: resources/views/song.blade.php
@extends('layouts.basic') <div id="lyrics-container" class="text-center"> <div id="lyrics-header"> <h1>{{$song->title}}</h1> <span id="lyrics-album-details"> {{$song->artist->name}} - {{$song->album}} Album </span> <div id="lyrics-thumbnail"> <img src="{{Storage::url('artists/' . $song->artist->photo)}}"> <div id="lyrics-youtube-link"> <a href="{{$song->youtube_link}}"><i class="glyphicon glyphicon-play"></i> Watch on Youtube</a> </div> </div><!--/#lyrics-thumbnail--> </div><!--/#lyrics-header--> <div id="lyrics-content"> <p><strong>"{{$song->title}}"</strong></p> <p>{!! nl2br($song->lyrics) !!}</p> </div><!--/#lyrics-content--> </div>
Эта страница отображается и контролируется в бэкэнде — Laravel.
В этом шаблоне мы расширяем макет и выводим атрибуты текста. Вот как это должно выглядеть:
Интерфейс поиска
Теперь мы переходим к основной части, для которой мы все создали, поисковому интерфейсу.
Чтобы создать интерфейс поиска, нам нужно объединить несколько виджетов Instantsearch.js и настроить каждый виджет в соответствии с нашими потребностями.
Наш интерфейс поиска будет состоять из трех виджетов:
- Поле поиска (виджет SearchBox )
- Раздел для отображения результатов (виджет Хиты )
- Пагинация (виджет пагинации )
Все виджеты соединены вместе из коробки и не требуют дополнительной разработки с нашей стороны. То есть всякий раз, когда пользователь вводит значение в поле поиска, все виджеты (окно поиска, попадания, нумерация страниц и т. Д.) Будут реагировать соответственно.
Создайте новый файл с именем search.blade.php
в search.blade.php
resources/views
следующего содержания:
Файл: resources/views/search.blade.php
@extends('layouts.basic') @section('content') <div id="header"> <div class="col-md-2"><h1>Coolyrics</h1></div> <div class="col-md-6"> <div id="search-box"></div> </div> </div> <div class="container-fluid"> <div id="hits-container"></div> <div id="pagination-container"></div> </div> @endsection @section('scripts') <!-- Scripts --> @parent <script language="javascript" src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/instantsearch.js/1/instantsearch.min.js"></script> @endsection @section('javascript') @endsection
В разделе content
у нас есть контейнер с идентификатором search-box
куда мы собираемся разместить наш виджет searchBox
. У нас также есть контейнеры для hits
и виджетов pagination
.
В разделе scripts
мы сначала загружаем сценарии мастер-макета, используя директиву @parent
. Затем мы добавляем сценарии, специфичные для этого шаблона, а именно jQuery
и Instantsearch.js
.
У нас также есть раздел ( javascript
) для внутреннего кода Javascript нашего шаблона. Здесь мы создаем экземпляр Instantsearch.js и добавляем наши виджеты.
Настройка InstantSearch.Js
Мы можем использовать Bower или NPM для установки Instantsearch.js или просто использовать CDN следующим образом:
Файл: resources/views/search.blade.php
@section('css') <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/instantsearch.js/1/instantsearch.min.css" /> @endsection
И файл Javascript:
Файл: resources/views/search.blade.php
@section('scripts') @parent <script language="javascript" src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/instantsearch.js/1/instantsearch.min.js"></script> @endsection
инициализация
Теперь нам нужно создать поисковый объект с указанным Application Id
и API Key
. В файле resources/views/search.blade.php
добавьте следующий код javascript
раздел javascript
.
Файл: resources/views/search.blade.php
... section('javascript') var search = instantsearch({ // You should put your keys here: appId: 'XXXX', apiKey: 'XXX', indexName: 'songs' }); @endsection ...
В приведенном выше коде нам нужно предоставить три значения для создания экземпляра объекта поиска: appId
, ApiKey
и indexName
.
Поскольку мы выполняем инициализацию в среде Javascript, ключи видны всем. Зная это, мы должны использовать наш API-ключ только для поиска, который ограничен только поисковыми операциями. Вы можете найти его в разделе API Keys в вашем профиле Algolia.
indexName
— это имя индекса, который мы хотим найти, в нашем случае это songs
.
Добавление поля поиска
Виджет searchBox создает интеллектуальное текстовое поле для ввода ключевого слова поиска.
Чтобы добавить виджет, мы вызываем метод addWidget
search
объекта search
(который мы только что создали), передавая ему экземпляр searchBox
:
Файл: resources/views/search.blade.php
... search.addWidget( instantsearch.widgets.searchBox({ container: '#search-box', placeholder: 'Search by artist, song, or lyrics', wrapInput: false, cssClasses: { input: 'form-control' } }) ); @endsection ...
Как видно из приведенного выше кода, мы передаем объект конфигурации при создании экземпляра виджета. Этот объект используется для настройки поведения виджета.
container
— это место, где находится наш виджет searchBox
. placeholder
— это обычный HTML-заполнитель для текстового поля.
Если для wrapInput
установлено значение true
, само текстовое поле оборачивается другим элементом <div>
с классом с именем ais-search-box
.
Наконец, опция cssClasses
указывает дополнительные классы, которые будут добавлены в виджет. В приведенных выше настройках мы просто добавляем класс в само текстовое поле. Мы также можем добавить классы к элементу упаковки.
Чтобы узнать о других доступных опциях для searchBox
, вы должны взглянуть на документацию .
Добавление виджета хитов
Виджет попаданий отображает результаты поиска на основе набора определенных шаблонов.
Добавьте следующий код сразу после кода для searchBox
:
Файл: resources/views/search.blade.php
... search.addWidget( instantsearch.widgets.hits({ container: '#hits-container', templates: { item: $('#hits-temp').html(), empty: 'No lyrics was found! <p>We will be adding more lyrics to the database.</p>', header: '<h2>Lyrics</h2>' } }) ); @endsection ...
Опять же, у нас есть объект настроек для настройки поведения виджета. Опция templates
определяет шаблоны, используемые для визуализации различных частей раздела попаданий (результатов). В приведенном выше коде мы определяем шаблон для элемента , который отображается для каждого элемента в наборе результатов. Мы также определяем шаблон для любого времени, когда поиск не дал результатов. Есть также еще один шаблон для раздела заголовков хитов.
Эти шаблоны могут быть либо шаблоном Усы, либо просто строкой, возвращаемой анонимной функцией Javascript.
В нашем случае шаблон item
— это шаблон усов, который хранится в <script>
, который мы получаем с помощью jQuery:
// ... item: $('#hits-temp').html(), // ...
Это наш усатый шаблон. Вы можете разместить его где search.blade.php
шаблоне search.blade.php
:
Файл: resources/views/search.blade.php
<script type="text/javascript" id="hits-temp"> <div class="row song"> <div class="pull-left band-thumbnail" style="background-image: url(/storage/artists/@{{photo}});"></div> <a class="song-link" href="song/@{{objectID}}">@{{{_highlightResult.title.value}}}</a> <span class="song-artist">- <a href="?q=@{{artist}}&hPP=20&idx=songs&p=0&is_v=1">@{{artist}}</a> (@{{album}})</span> <span class="song-youtube-link"><a href="@{{youtube_link}}" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-play"></i> Watch on Youtube</a></span> </div> </script>
В этом шаблоне у нас есть доступ к атрибутам каждой строки в индексе, таким как objectID
, artist
, title
, photo
, objectID
и т. Д.
Чтобы не допустить рендеринга директив усов Blade, мы ставим @
перед каждым набором фигурных скобок, чтобы Blade знал, что это выражение должно оставаться нетронутым и обрабатываться Instantsearch.js позже.
Кроме того, Algolia предоставляет объект для каждого элемента, называемый _highlightResult
. Этот объект содержит выделенный текст для каждого атрибута на основе ключевого слова поиска. Это полезно, чтобы показать, какая часть результатов соответствует искомому ключевому слову.
<a class="song-link" href="song/@{{objectID}}">@{{{_highlightResult.title.value}}}</a>
Обратите внимание, что мы связываем каждый элемент со своей страницей сведений.
Добавление пагинации
Виджет разбивки на страницы генерирует ссылки разбивки на страницы:
Файл: resources/views/search.blade.php
... search.addWidget( instantsearch.widgets.pagination({ container: '#pagination-container' }) ); ...
Чтобы увидеть все доступные опции для этого виджета, вам следует взглянуть на документацию .
Наконец, мы начинаем search
объекта:
Файл: resources/views/search.blade.php
// ... search.start(); // ...
Полный код должен выглядеть следующим образом:
Файл: resources/views/search.blade.php
@extends('layouts.basic') @section('content') <div id="header"> <div class="col-md-2"><h1>Coolyrics</h1></div> <div class="col-md-6"> <div class="input-group" id="search-box"> <div class="input-group-btn"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <span>Genre</span> <span class="caret"></span></button> <ul id="genres" class="dropdown-menu"> </ul> </div><!-- /btn-group --> </div> </div> <div id="login-link" class="col-md-4 text-right"> <a href="{{route('login')}}">Login</a> </div> </div> <div class="container-fluid"> <div id="hits-container"></div> <div id="pagination-container"></div> </div> @endsection @section('scripts') <!-- Scripts --> @parent <script language="javascript" src="https://cdn.jsdelivr.net/jquery/3.1.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/instantsearch.js/1/instantsearch.min.js"></script> @endsection @section('javascript') <script type="text/javascript" id="hits-temp"> <div class="row song"> <div class="pull-left band-thumbnail" style="background-image: url(/storage/artists/@{{photo}});"></div> <a class="song-link" href="song/@{{objectID}}">@{{{_highlightResult.title.value}}}</a> <span class="song-artist">- <a href="?q=@{{artist}}&hPP=20&idx=songs&p=0&is_v=1">@{{artist}}</a> (@{{album}})</span> <span class="song-youtube-link"><a href="@{{youtube_link}}" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-play"></i> Watch on Youtube</a></span> </div> </script> <span></span> <script> var search = instantsearch({ appId: 'XI8PV16IK6', apiKey: '63c96991d445cb2de4fff316ac909c1a', indexName: 'songs', urlSync: true }); search.addWidget( instantsearch.widgets.searchBox({ container: '#search-box', placeholder: 'Search by artist, song, or lyrics', wrapInput: false, cssClasses: { input: 'form-control' } }) ); search.addWidget( instantsearch.widgets.hits({ container: '#hits-container', templates: { item: $('#hits-temp').html(), empty: 'No lyrics was found! <p>We will be adding more lyrics to the database.</p>', header: '<h2>Lyrics</h2>' } }) ); search.addWidget( instantsearch.widgets.hits({ container: '#hits-container', templates: { item: $('#hits-temp').html(), empty: 'No lyrics was found! <p>We will be adding more lyrics to the database.</p>', header: '<h2>Lyrics</h2>' } }) ); search.addWidget( instantsearch.widgets.menu({ container: '#genres', attributeName: 'genres', limit: 10, templates: { header: '', footer: '', item: '<li><a href="@{{url}}">@{{name}}</></li>' } }) ); search.addWidget( instantsearch.widgets.pagination({ container: '#pagination-container' }) ); search.start(); </script> @endsection
Теперь, если мы перезагрузим страницу, мы увидим потрясающий интерфейс поиска, который работает прямо из коробки. Никакого дополнительного кодирования, никаких хлопот.
Не стесняйтесь играть с интерфейсом. Ищите разные термины и открывайте ссылки, чтобы посмотреть, как это выглядит. Вы также можете сделать некоторые опечатки специально при поиске, чтобы увидеть ответ. Алголийские алгоритмы допуска к опечаткам автоматически определят, что ищут ваши пользователи, и вернут правильные результаты.
Хорошо, я думаю, что это поможет начать со Скаута и Алголии. Вы можете найти полный код на Github, если вы хотите попробовать его сами.
Чтобы увидеть рабочую демонстрацию того, что мы создали в этом уроке, нажмите здесь .
Завершение
Мы создали наш минимальный текст песни с помощью Laravel Scout и Algolia.
Обратите внимание, что этот проект был только для образовательных целей, реализован в максимально возможной форме и, следовательно, не должен использоваться в производственной среде. Пожалуйста, не стесняйтесь изменять код любым удобным для вас способом.
Чтобы двигаться дальше, вы можете зайти в свой профиль Algolia, изменить настройки и посмотреть результаты. Вы также можете добавить синонимы для каждого термина, если у вас нет этого термина в вашей базе данных.
Если у вас есть какие-либо вопросы по этой теме или мы что-то пропустили, сообщите нам об этом в комментариях ниже!