This sponsored post features a product relevant to our readers while meeting our editorial guidelines for being objective and educational.
() translation by (you can also view the original English article)
В этом уроке я покажу вам, как реализовать приложение чата реального времени на Laravel 5, PostgreSQL и Pusher. Затем мы вместе задеплоим это приложение на Modulus.
Мы будем использовать Laravel 5 для службы back-end, HTML5 и jQuery для простого внешнего приложения PostgreSQL для базы данных и Pusher для обмена данными между сервером и клиентами в режиме реального времени. Общая архитектура будет выглядеть так:



Сценарий
- Пользователь открывает приложение чата в браузере и предоставляет псевдоним для продолжения.
- Пользователь вводит текст и нажимает кнопку «Отправить».
- Сообщение будет обрабатываться службой, написанной с использованием Laravel 5, и оно будет сохранена в базе данных.
- Сохраненное сообщение будет отправлено в Pusher, чтобы инициировать новое событие сообщения для трансляции этого сообщения на подключенных клиентов.
- Новое сообщение будет получено клиентами, а список сообщений чата будет обновлен для всех подключенных клиентов.
В этом сценарии мы рассмотрим очень полезные темы, даже если это очень простое приложение.
Подготовка окружения
Настройка проекта Laravel
Давайте сначала установим Laravel, чтобы мы могли написать чат-сервис для нашего приложения. Мы будем использовать Composer для установки Laravel и связанных с ним пакетов. Дополнительную информацию об установке Composer см. на веб-сайте Composer. После установки Composer откройте командную строку и выполните следующую команду для установки Laravel 5:
композитор глобальный требует "laravel / installer = ~ 1.1"
Вы увидите следующий результат:



Мы готовы создать проект Laravel. Выполните следующий код для создания структуры проекта для приложения чата.
laravel new RealtimeChatLaravel
Это создаст шаблонный проект Laravel, и вы увидите следующую структуру папок:



База данных
Наше приложение будет взаимодействовать с базой данных, и это будет PostgreSQL. В этом проекте мы будем использовать ElephantSQL, который является компанией, предоставляющей PostgreSQL как услугу. Вы можете использовать несколько типов баз данных с Laravel, например SQLite, MySQL, PostgreSQL и SQL Server. Я выбрал PostgreSQL, потому что, когда мы внедряем наш проект в Modulus, вы не сможете использовать внутреннюю базу данных, такую как указанные выше типы баз данных. Я предпочитаю использовать базу данных, которая предоставляет ее как услугу. ElephantSQL позволяет вам попробовать некоторые из хороших функций PostgreSQL со свободным планом.
Вы можете пойти и получить бесплатный план от ElephantSQL, чтобы использовать его для ваших нужд. Когда вы закончите создание своей учетной записи и базы данных, вы получите информацию о базе данных, такую как имя хоста, имя базы данных, имя пользователя и пароль. Пожалуйста, запишите эту информацию для использования в Laravel в настройки базы данных.
Pusher
Эта компания предоставляет услугу для генерации событий в режиме реального времени. Вы можете посетить веб-сайт Pusher, чтобы получить его. После успешного создания учетной записи и приложения вы сможете получить некоторые учетные данные, такие как App ID, App Secret и App Key. Мы поговорим об их использовании в следующих разделах.
Nginx
Чтобы запустить приложение PHP в Modulus, вам необходимо настроить веб-сервер для обслуживания вашего приложения. Мы будем использовать следующую конфигурацию Nginx:
1 |
server { |
2 |
listen 8080; |
3 |
|
4 |
server_name modulus_app_url; |
5 |
|
6 |
root /mnt/app/public; |
7 |
index index.html index.php; |
8 |
|
9 |
location / { |
10 |
try_files $uri $uri/ /index.php?$query_string; |
11 |
}
|
12 |
|
13 |
location ~ \.php$ { |
14 |
|
15 |
fastcgi_split_path_info ^(.+\.php)(/.+)$; |
16 |
fastcgi_pass unix:/mnt/home/php-fpm.sock; |
17 |
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
18 |
fastcgi_index index.php; |
19 |
|
20 |
include fastcgi_params; |
21 |
|
22 |
}
|
23 |
}
|
Мы завершили необходимые настройки окружения, чтобы продолжить разработку. Перейдем к архитектурной части.
Архитектура проекта с нуля
Модель
Если вы когда-либо использовали ORM, вы будете очень хорошо знакомы с этой темой. В проектах Laravel модели домена по умолчанию помещаются в папку /app
. В этом приложении мы будем выполнять операции CRUD в сообщениях, и это означает, что нам нужно создать модель Message
.
Если вы хотите создать модель, просто создайте класс, который расширяет класс Model
, который является абстрактным классом в базовом пакете Laravel Illuminate\Database\Eloquent
. Создайте файл Message.php
в папке app/
и поместите в файл следующее содержимое:
1 |
<?php
|
2 |
|
3 |
namespace App; |
4 |
|
5 |
use Illuminate\Database\Eloquent\Model; |
6 |
|
7 |
class Message extends Model |
8 |
{
|
9 |
protected $table = 'messages'; |
10 |
|
11 |
}
|
Эта модель позволит нам легко выполнять несколько операций, связанных с базой данных. Например, когда вы выполняете следующий запрос:
1 |
<?php
|
2 |
.....
|
3 |
Message::all(); |
4 |
...
|
5 |
?>
|
он предоставит вам все сообщения из базы данных. Однако как он определяет имя таблицы? Он использует значение $table
в классе модели. Когда вы создадите новое сообщение, оно автоматически сохранит вашу модель сообщений в таблице messages
. Мы подробно рассмотрим Модели в разделе «Контроллер».
Контроллер
Контроллер - это место, где определяется поведение вашего приложения. Мы будем выполнять некоторые операции с сообщением, если ChatController
существует в нашем приложении. У нас будет четыре ендпоинта для нашего приложения:
-
GET / login
: для отображения страницы входа -
GET / chat
: для отображения страницы чата -
GET / messages
: для перечисления последних пяти сообщений, отображаемых на странице чата, когда пользователь сначала открывает его -
POST / messages
: для сохранения нового сообщения
Чтобы создать контроллер, просто создайте класс в App\Http\Controllers
и сделайте этот класс наследником от класса Laravel Controller
, который находится в App\Http\Controllers
. Когда вы запрашиваете ендпоинт /login
или /chat
, они будут отображать собственные шаблоны в resources/views
. Вы можете сделать это, используя следующие действия.
1 |
class ChatController extends Controller |
2 |
{
|
3 |
public function getLogin() |
4 |
{
|
5 |
return view("login"); |
6 |
}
|
7 |
|
8 |
public function getChat() |
9 |
{
|
10 |
return view("chat"); |
11 |
}
|
12 |
|
13 |
public function saveMessage() |
14 |
{
|
15 |
if(Request::ajax()) { |
16 |
$data = Input::all(); |
17 |
$message = new Message; |
18 |
$message->author = $data["author"]; |
19 |
$message->message = $data["message"]; |
20 |
$message->save(); |
21 |
|
22 |
Pusher::trigger('chat', 'message', ['message' => $message]); |
23 |
}
|
24 |
|
25 |
}
|
26 |
|
27 |
public function listMessages(Message $message) { |
28 |
return response()->json($message->orderBy("created_at", "DESC")->take(5)->get()); |
29 |
}
|
30 |
}
|
Первое и второе действия будут отображать конкретные страницы. Третье действие - сохранение сообщений. В этом действии проверяется тип запроса. Если это запрос AJAX, он получает все тело запроса как ассоциативный массив. Этот массив используется для заполнения созданной модели Message.
Затем метод save()
непосредственно выполняется в модели для сохранения в базу данных. Всякий раз, когда новое сообщение сохраняется в базе данных, одно и то же сообщение отправляется в Pusher, вызывая событие message
. Когда вы вызываете событие, все подключенные клиенты будут уведомлены. Чтобы использовать класс Pusher
в ваших проектах Laravel, вы можете сделать следующее:
- Подключите пакеты, связанные с Pusher, с помощью
composer require vinkla/pusher
. - Добавьте пакет
Pusher Vinkla\Pusher\PusherServiceProvider::class
, вconfig/app.php
.
- Используйте классы Pusher в ваших контроллерах, например
use Vinkla\Pusher\Facades\Pusher;
, над классом контроллера.
Все у вас все в порядке с пакетами, то как насчет конфигурации Pusher? Вы должны опубликовать поставщиков в своих проектах, используя следующую команду:
1 |
php artisan vendor:publish |
Эта команда создаст конфигурационный файл config/pusher.php
, и вам необходимо предоставить необходимые учетные данные, которые вы можете найти на панели инструментов Pusher. Конфигурационный файл будет выглядеть следующим образом:
1 |
'connections' => [ |
2 |
|
3 |
'main' => [ |
4 |
'auth_key' => 'auth_key', |
5 |
'secret' => 'secret', |
6 |
'app_id' => 'app_id', |
7 |
'options' => [], |
8 |
'host' => null, |
9 |
'port' => null, |
10 |
'timeout' => null, |
11 |
],
|
12 |
|
13 |
'alternative' => [ |
14 |
'auth_key' => 'your-auth-key', |
15 |
'secret' => 'your-secret', |
16 |
'app_id' => 'your-app-id', |
17 |
'options' => [], |
18 |
'host' => null, |
19 |
'port' => null, |
20 |
'timeout' => null, |
21 |
],
|
22 |
|
23 |
]
|
Четвертый ендпоинт предназначен для получения списка последних пяти сообщений для отображения на странице чата вновь подключенным пользователям. Немного магии:
1 |
public function listMessages(Message $message) { |
2 |
return response()->json($message->orderBy("created_at", "DESC")->take(5)->get()); |
3 |
}
|
В этом коде модель Message
инжектится в экшен и выполняет операции, связанные с базой данных, с помощью $message
. Сначала мы сортируем сообщения по полю by created_at
в порядке убывания, а затем берем последние пять. Результат возвращается в формате JSON с помощью response()->json(...)
.
Мы упомянули о контроллерах и действиях, но как эти действия выполняются, когда пользователь переходит к определенному URL-адресу? Вы можете добавить конфигурацию маршрутов в файл app/Http/routes.php
. Ниже приведен пример:
1 |
<?php
|
2 |
|
3 |
Route::get('/chat', '\App\Http\Controllers\Chat\ChatController@getChat'); |
4 |
|
5 |
Route::get('/login', '\App\Http\Controllers\Chat\ChatController@getLogin'); |
6 |
|
7 |
Route::get('/messages', '\App\Http\Controllers\Chat\ChatController@listMessages'); |
8 |
|
9 |
Route::post('/messages', '\App\Http\Controllers\Chat\ChatController@saveMessage'); |
В этом использовании URI запроса и метод запроса сопоставляются с именем контроллера и именем действия.
На этом с контроллерами все. Перейдем к части « View».
Представления
В этом разделе мы использовали механизм шаблонов Blade, предоставленный Laravel. На самом деле, в наших проектах нет элементов шаблонов, но если вы хотите отправлять значения с контроллера на представления, вы можете напрямую использовать этот проект.
У нас есть две страницы отображения: login.blade.php
и chat.blade.php
. Как вы можете видеть, ключевое слово blade внутри имени файлов представлений указывает на то, что в качестве механизма шаблонов обработки будет использоваться Blade.
Первое отображение - просто для операции входа в систему, поэтому давайте поговорим о странице chat
. В этом файле представления есть некоторые сторонние библиотеки JavaScript, которые мы получаем из CDN, такие как jQuery
, jQuery Cookie
, Bootstrap
и Pusher
. У нас есть форма для отправки сообщений в чат, и Laravel помещает мета-описание на страницу:
1 |
<meta name="_token" value="token"> |
Тем не менее, мы отправляем сообщение чата через AJAX, и в заголовках запроса AJAX нет токенов. Мы предлагаем решение, используя следующий фрагмент кода:
1 |
$.ajaxSetup({ |
2 |
headers: { 'X-CSRF-Token' : $('meta[name=_token]').attr('content') } |
3 |
});
|
Всякий раз, когда вы отправляете запрос AJAX, этот токен будет помещен внутри заголовка.
Чтобы прослушать канал сообщения в режиме реального времени, мы использовали следующее:
1 |
var pusher = new Pusher('app_id'); |
2 |
var channel = pusher.subscribe('chat'); |
3 |
channel.bind('message', function(data) { |
4 |
var message = data.message; |
5 |
$(".media-list li").first().remove(); |
6 |
$(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">' |
7 |
+ message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.created_at + '</small><hr/></div></div></div></li>'); |
8 |
});
|
Прежде всего, у нас есть объект Pusher
с app_id
. А затем клиент подписывается на канал. Всякий раз, когда приходит новое событие с именем message
, функция-callback будет выполняться внутри функции bind()
. Область с сообщениями будет обновлена новыми сообщениями.
Наконец, всякий раз, когда новый пользователь открывает страницу чата, последние пять сообщений будут отображаться в области списка сообщений:
1 |
$.get("/messages", function (messages) { |
2 |
refreshMessages(messages) |
3 |
});
|
Вы можете обратиться к исходному коду, чтобы проанализировать полный исходный код страниц представлений.
Развертывание
Мы будем использовать Modulus для размещения нашего приложения.
Modulus является одним из лучших PaaS для развертывания, масштабирования и мониторинга вашего приложения на выбранном вами языке. Прежде чем приступать к развертыванию, перейдите к Modulus и создайте учетную запись.
Требования
Развертывание в Modulus очень простое. Единственное, что вам нужно сделать, это установить модуль Node.js и запустить команду. Также вы можете заархивировать свой проект и загрузить его в Modulus. В этом уроке мы предпочтем первый вариант.
Я предполагаю, что вы уже установили Node.js и npm на свой компьютер. Просто откройте инструмент командной строки и выполните npm install -g modulus
. После успешной установки войдите в свою учетную запись Modulus CLI введя команду: modulus login
. Если вы хотите войти в систему с помощью GitHub, вы можете использовать modulus login --github
.
После того, как вы вошли в систему, создайте проект с помощью этой команды: modulus project create "RealtimeChatLaravel"
. Вы создали приложение на стороне Modulus.
Последнее, что вам нужно сделать, это создать папку в корневой папке проекта sites-enabled
и поместить в нее конфигурацию Nginx, упомянутую в разделе Nginx.
Разверните свой проект в Modulus под этим приложением. Выполните команду modulus deploy
, чтобы начать развертывание, и все! Эта команда будет загружать ваши файлы проекта в Modulus, а также будет настраивать веб-сервер, используя конфигурацию Nginx, которую вы помещаете в папку sites-enabled
.
После успешного развертывания вы получите сообщение RealtimeChatLaravel running at realtime-chat-46792.onmodulus.net
. Перейдите по этому URL-адресу, чтобы увидеть рабочее приложение
Modulus CLI имеет очень полезные команды для использования в разделе развертывания и выполнения. Например, вы можете управлять логами текущего проекта с помощью modulus project logs tail
, устанавливать переменную окружения с помощью modulus env set <key> <value>
и т,д. Вы можете просмотреть полный список команд, используя modulus help
.
Вывод
Если вы создаете веб-приложение PHP, вам неизбежно придется иметь дело с веб-серверами, такими как Apache NGINX; однако, если вы используете Modulus, вы можете просто сосредоточиться на своем проекте PHP. Modulus позволяет настраивать конфигурацию вашего веб-сервера внутри вашего проекта, чтобы она повлияла на развертывание вашего кода.
В этом уроке мы сосредоточились на приложении чата реального времени и увидели, что другие аспекты приложения очень просты в обращении благодаря Modulus.