Статьи

Как создать сайт с текстами песен с Laravel Scout и Algolia

В этом уроке мы создадим веб-сайт с минимальной лирикой, используя Laravel Scout и Algolia . Для этого нам нужно приложение CRUD для работы с нашими данными и интерфейс поиска, чтобы пользователи могли осуществлять поиск по содержимому. Однако вместо того, чтобы создавать полное приложение с нуля, давайте просто установим готовое приложение CRUD , которое мы создали для этого урока.

Algolia — это размещенный API поисковых систем, предоставляющий нам все инструменты и ресурсы, которые нам когда-либо понадобятся для создания продуктов с потрясающими возможностями поиска.

Поиск векторного изображения

Читайте Jump Start PHP Environment
Настройте свои проекты PHP правильно

К концу урока у нас будет такой продукт:

Lyrics_Website_With_Algolia_Scout

Страница деталей текстов песен

Начальная загрузка приложения

Я предполагаю, что у вас уже есть среда разработки. Однако, если вам нужна хорошая среда разработки, чтобы сразу приступить к действиям, вы должны использовать Homestead Improved .

Незнакомец Бродяге? Прочитайте это . Хотите углубиться? Купите нашу книгу о среде PHP!

Не стесняйтесь пропустить эту часть, если у вас уже есть подобное приложение или у вас достаточно опыта, чтобы создать его относительно быстро.

Приложение CRUD

Самый удобный способ скачать готовый проект CRUD — это клонировать его:

git clone git@github.com: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» в левом меню.

Algolia API Keys

Теперь мы открываем файл конфигурации 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, изменить настройки и посмотреть результаты. Вы также можете добавить синонимы для каждого термина, если у вас нет этого термина в вашей базе данных.

Если у вас есть какие-либо вопросы по этой теме или мы что-то пропустили, сообщите нам об этом в комментариях ниже!