Advertisement
  1. Code
  2. PHP

Создаем приложение чата реального времени на Modulus и Laravel 5

Scroll to top
Read Time: 10 min
This post is part of a series called Getting Started with Modulus.
Real-Time Chat With Modulus and Node.js
Build a Real-Time Chat Application With Modulus and Python
Sponsored Content

This sponsored post features a product relevant to our readers while meeting our editorial guidelines for being objective and educational.

Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)

В этом уроке я покажу вам, как реализовать приложение чата реального времени на Laravel 5, PostgreSQL и Pusher. Затем мы вместе задеплоим это приложение на Modulus.

Мы будем использовать Laravel 5 для службы back-end, HTML5 и jQuery для простого внешнего приложения PostgreSQL для базы данных и Pusher для обмена данными между сервером и клиентами в режиме реального времени. Общая архитектура будет выглядеть так:

Application ArchitectureApplication ArchitectureApplication Architecture

Сценарий

  1. Пользователь открывает приложение чата в браузере и предоставляет псевдоним для продолжения.
  2. Пользователь вводит текст и нажимает кнопку «Отправить».
  3. Сообщение будет обрабатываться службой, написанной с использованием Laravel 5, и оно будет сохранена в базе данных.
  4. Сохраненное сообщение будет отправлено в Pusher, чтобы инициировать новое событие сообщения для трансляции этого сообщения на подключенных клиентов.
  5. Новое сообщение будет получено клиентами, а список сообщений чата будет обновлен для всех подключенных клиентов.

В этом сценарии мы рассмотрим очень полезные темы, даже если это очень простое приложение.

Подготовка окружения

Настройка проекта Laravel

Давайте сначала установим Laravel, чтобы мы могли написать чат-сервис для нашего приложения. Мы будем использовать Composer для установки Laravel и связанных с ним пакетов. Дополнительную информацию об установке Composer см. на веб-сайте Composer. После установки Composer откройте командную строку и выполните следующую команду для установки Laravel 5:

композитор глобальный требует "laravel / installer = ~ 1.1"

Вы увидите следующий результат:

Laravel Installation with ComposerLaravel Installation with ComposerLaravel Installation with Composer

Мы готовы создать проект Laravel. Выполните следующий код для создания структуры проекта для приложения чата.

laravel new RealtimeChatLaravel

Это создаст шаблонный проект Laravel, и вы увидите следующую структуру папок:

Laravel Boilerplate Project StructureLaravel Boilerplate Project StructureLaravel Boilerplate Project Structure

База данных

Наше приложение будет взаимодействовать с базой данных, и это будет 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 существует в нашем приложении. У нас будет четыре ендпоинта для нашего приложения:

  1. GET / login: для отображения страницы входа
  2. GET / chat: для отображения страницы чата
  3. GET / messages: для перечисления последних пяти сообщений, отображаемых на странице чата, когда пользователь сначала открывает его
  4. 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, вы можете сделать следующее:

  1. Подключите пакеты, связанные с Pusher, с помощью composer require vinkla/pusher.
  2. Добавьте пакет Pusher Vinkla\Pusher\PusherServiceProvider::class, в config/app.php.
  3. Используйте классы 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.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.