Передача данных в JS

Август, 2022

Вопрос «Как использовать php-переменную в js?» периодически всплывает в чатах по ларе и у фреймворка даже есть небольшой функционал для этого, поэтому рассмотрим какие могут быть способы передачи данных между backend и frontend приложениями.

# AJAX

Самый очевидный и популярный способ, это сделать AJAX-запрос на api, в ответе получим необходимые данные, например, в json или html.

Подходит если данные не нужны во время первого выполнения и мы можем получить их позже в фоне.

Один из популярных примеров - это фильтр товаров. Поскольку выборка из базы данных может занять некоторое время, то для ускорения загрузки основной страницы (первого ответа сервера) такие запросы откладывают и запрашивают список товаров асинхронно.

# Тег <script>

Данный способ подходит, когда данные на frontend необходимы сразу. В html можно использовать тег <script> код внутри которого будет выполнен сразу после того как будет прочитан клиентом.

Данный код обычно располагают в <head> до подключения остальных скриптов.

1<script>
2 var app = {{ Js::from($config) }};
3 var userId = {{ Js::from(Auth::id()) }};
4 var routeHome = {{ Js::from(route('home')) }};
5</script>
highlight by torchlight.dev

Фасад Illuminate\Support\Js доступен начиная с 8.x версии, подробнее читай в документации .

Без хелпера необходимо вручную контролировать значения по умолчанию и следить за экранированием:

1<script>
2 var app = {!! $config ? json_encode($config) : '{}' !!};
3 var userId = {{ Auth::id() ?? 'null' }};
4 var routeHome = '{{ route('home') }}';
5</script>
highlight by torchlight.dev

Обрати внимание, что такие переменные являются глобальными , а это bad-практика. Тем не менее, если приходится использовать данный способ, то рекомендую свести количество переменных к минимуму и дать уникальное имя, например с префиксом имени проекта, а обращаться к ним через window

# HTML-атрибут

Аналогично предыдущему способу, только вместо JS переменной передаём значение в data-* атрибут тега, а затем, после загрузки DOM, читаем атрибут тега.

1<button data-href="{{ route('posts.create') }}">click</button>
1// js
2const button = document.querySelector('button')
3const href = button.getAttribute('data-href')
highlight by torchlight.dev

Или как массив/объект:

1<input data-params='@json($params)' />
1// js
2const input = document.querySelector('input')
3const params = JSON.parse(input.getAttribute('data-params'))
highlight by torchlight.dev

Способ подходит лучше для передачи мелких, локальных (не глобальных) данных, например, адрес, куда необходимо отправить данные после выполнения каких-либо асинхронных действий, вызываемых по клику на элемент. Ещё один пример - передача параметров для слайдера, модального окна или любого другого компонента, которые могут контролироваться backend-ом.

# Готовые решения

tighten/ziggy
Если необходимо пробросить маршруты в JS.

rmariuzzo/Laravel-JS-Localization
Если необходимо пробросить переводы (локализацию) в JS.

Inertiajs
Глобальный пакет для монолитного SPA, который использует вариант с HTML-атрибутом, описанный выше. Не стоит использовать для простого проброса данных, а только для цельных приложений, например, хорошо подходит для админок.