Как безопасно передать переменную из php в js

Чтобы передать переменную из php в js, выведите ее в HTML через JSON или отправьте HTTP-запросом. PHP работает на сервере, JavaScript – в браузере. В статье вы найдете безопасные примеры для строки, числа, массива, объекта, bool и null, а также узнаете, как отправить значение обратно в PHP.

Почему PHP-переменную нельзя прочитать из JavaScript напрямую

PHP выполняет код на сервере до отправки страницы. JavaScript запускается в браузере после получения HTML.

Переменная $user остается в памяти PHP. Браузер видит готовый HTML и ответы отдельных HTTP-запросов.

Поэтому передать переменную из php в js можно через выведенный текст или HTTP-запрос. Для структурированных значений используйте json_encode: функция превращает PHP-значение в JSON с сохранением подходящего типа.

Какой способ выбрать

Выберите способ по моменту получения данных и месту их использования. Значение для первого рендера передайте в HTML, меняющиеся сведения запросите после загрузки.

СпособКогда подходитТипы данныхКэширование страницы и JSСовместимость с CSPСложность
Inline и json_encodeДанные нужны сразуВсе JSON-типыДанные связаны с HTMLИсполняемый inline-код требует разрешения, например nonceНизкая
application/jsonВнешний скрипт читает объектВсе JSON-типыHTML содержит данные, JS кэшируется отдельноПодходит при запрете исполняемого inline-кодаНизкая
Data-атрибутыЗначение относится к элементуСтроки и JSON-строкаДанные связаны с HTMLCSP влияет на скрипт, но не на атрибутНизкая
Глобальный объектДанные нужны внешнему script.jsВсе JSON-типыJS можно кэшировать отдельноОбъявление требует разрешения inline-кодаСредняя
fetchДанные меняются после загрузкиВсе JSON-типыСтраница и ответ кэшируются отдельноВнешний JS требует разрешения загрузки; запрос регулирует connect-srcСредняя

Как передать переменную из php в js через json_encode

Этот способ формирует JavaScript во время генерации страницы. Не добавляйте кавычки вокруг результата json_encode: функция уже возвращает JSON нужного типа.

Для запуска примеров нужен установленный PHP, доступный командой php в терминале.

  1. Создайте папку php-js-demo для учебных файлов.
  2. Сохраните первый PHP-пример из этого раздела в php-js-demo/index.php с кодировкой UTF-8.
  3. Откройте терминал в папке php-js-demo. Если терминал открыт в родительской папке, выполните cd php-js-demo.
  4. Запустите встроенный сервер командой php -S 127.0.0.1:8000. Терминал сообщит о запуске сервера; оставьте это окно открытым.
  5. Откройте в браузере адрес http://127.0.0.1:8000/index.php.
  6. Откройте инструменты разработчика браузера и переключитесь на консоль. Первый пример выведет имя Анна, число 28 и остальные значения из листинга.

Папка php-js-demo теперь служит корнем сайта для всех примеров. Файл script.js размещайте рядом с index.php, обработчики – внутри подпапки api. Каждый способ запускайте отдельно: заменяйте содержимое учебных файлов соответствующими листингами и обновляйте страницу.

Открытие файла напрямую с диска не запускает PHP. Встроенный сервер используйте только для локальных упражнений; после работы остановите его сочетанием Ctrl+C в терминале.

HEX-флаги заменяют символы внутри JSON-строк Unicode-последовательностями. Каждый флаг отвечает за свою группу символов:

  • JSON_HEX_TAG кодирует угловые скобки. Пользовательский текст не сможет закрыть тег </script>.
  • JSON_HEX_AMP кодирует амперсанд.
  • JSON_HEX_APOS кодирует одинарную кавычку.
  • JSON_HEX_QUOT кодирует двойную кавычку внутри значения строки, сохраняя кавычки синтаксиса JSON.

Флаг JSON_THROW_ON_ERROR превращает ошибку кодирования в исключение. Список констант и их поведение описаны в документации PHP о JSON-константах.

В JavaScript используйте const для переменных без повторного присваивания, let – для изменяемых, вместо var.

<?php
$userName = 'Анна <admin@example.com>';
$age = 28;
$roles = ['editor', 'author'];
$profile = [
    'name' => $userName,
    'active' => true,
    'middleName' => null
];

$jsonFlags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS |
    JSON_HEX_QUOT | JSON_THROW_ON_ERROR;
?>
<script>
const userName = <?= json_encode($userName, $jsonFlags) ?>;
const age = <?= json_encode($age, $jsonFlags) ?>;
const roles = <?= json_encode($roles, $jsonFlags) ?>;
const profile = <?= json_encode(
    $profile,
    $jsonFlags | JSON_UNESCAPED_UNICODE
) ?>;

console.log(userName);
console.log(age);
console.log(roles);
console.log(profile);
console.log(profile.active, profile.middleName);
</script>

В консоли появятся строка, число, массив и объект. Последний вызов выведет true и null. Флаг JSON_UNESCAPED_UNICODE оставляет кириллицу читаемой в исходном JSON.

Анна <admin@example.com>
28
["editor", "author"]
{ name: "Анна <admin@example.com>", active: true, middleName: null }
true null
Тип PHPТип JavaScript
stringstring
int, floatnumber
Последовательный массивArray
Ассоциативный массивObject
boolboolean
nullnull

Массив с последовательными индексами от нуля становится JavaScript-массивом. Массив с именованными ключами становится объектом. Большие целочисленные идентификаторы передавайте строками, чтобы JavaScript не потерял точность.

Синтаксис <?= – краткая запись echo. Оставляйте результат JSON без внешних кавычек для строки, числа, bool и null.

JSON в теге script type="application/json"

Неисполняемый JSON-блок отделяет данные от логики. Такой формат удобен для внешнего файла и политики CSP, которая запрещает исполняемые inline-скрипты. Сама политика должна разрешать загрузку внешнего файла.

Замените содержимое php-js-demo/index.php PHP-разметкой, а JavaScript сохраните в php-js-demo/script.js.

<?php
$config = [
    'apiUrl' => '/api/profile.php',
    'userId' => 17,
    'features' => ['comments', 'dark-mode']
];

$flags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS |
    JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR;
?>
<script id="app-config" type="application/json"><?= json_encode($config, $flags) ?></script>
<script src="script.js" defer></script>
const configElement = document.getElementById('app-config');
const config = JSON.parse(configElement.textContent);

console.log(config.apiUrl);
console.log(config.userId);
console.log(config.features);

После обновления страницы в консоли появятся путь /api/profile.php, число 17 и массив ["comments", "dark-mode"]. Читайте блок через JSON.parse и свойство textContent.

Не применяйте htmlspecialchars к JSON внутри raw text-элемента. HTML-сущности попадут в строку и помешают разбору JSON. HEX-флаги нужны и здесь: HTML-парсер распознает конец тега независимо от его типа.

Data-атрибуты

Data-атрибут подходит для значения, которое относится к кнопке, карточке или строке таблицы. Свойство dataset читает такие атрибуты.

Поместите PHP-разметку в php-js-demo/index.php. JavaScript добавьте в php-js-demo/script.js, подключенный после кнопки с атрибутом defer.

<?php
$userId = 17;
$userName = 'Анна "Редактор"';
$tags = ['php', 'javascript'];

$jsonFlags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS |
    JSON_HEX_QUOT | JSON_THROW_ON_ERROR;
?>
<button
    id="profile-button"
    data-user-id="<?= htmlspecialchars((string) $userId, ENT_QUOTES, 'UTF-8') ?>"
    data-user-name="<?= htmlspecialchars($userName, ENT_QUOTES, 'UTF-8') ?>"
    data-tags="<?= htmlspecialchars(
        json_encode($tags, $jsonFlags),
        ENT_QUOTES,
        'UTF-8'
    ) ?>"
>Профиль</button>
<script src="script.js" defer></script>
const button = document.getElementById('profile-button');
const userId = Number(button.dataset.userId);
const userName = button.dataset.userName;
const tags = JSON.parse(button.dataset.tags);

console.log(userId, userName, tags);

В консоли появятся число 17, строка Анна "Редактор" и массив ["php", "javascript"]. Запись data-user-id превращается в dataset.userId.

Все значения в dataset приходят строками. Преобразуйте число через Number, массив или объект – через JSON.parse. Для булева значения сравните строку с 'true': Boolean('false') тоже возвращает true.

htmlspecialchars с ENT_QUOTES кодирует одинарные и двойные кавычки для HTML-атрибута. Функция также кодирует амперсанд и угловые скобки. Передавайте через эту функцию каждое значение, которое попадает внутрь атрибута.

Переменные для внешнего JavaScript-файла

Внешний script.js прочитает настройки из объекта window.appConfig, созданного на странице. Сохраните PHP-разметку в php-js-demo/index.php, следующий JS-листинг – в php-js-demo/script.js.

<?php
$settings = [
    'seconds' => 30,
    'redirectUrl' => '/account.php',
    'isGuest' => true
];

$flags = JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS |
    JSON_HEX_QUOT | JSON_THROW_ON_ERROR;
?>
<script>
window.appConfig = <?= json_encode($settings, $flags) ?>;
</script>
<script src="script.js" defer></script>
const { seconds, redirectUrl, isGuest } = window.appConfig;
console.log(seconds, redirectUrl, isGuest);

В консоли появятся 30, путь /account.php и значение true.

Если внешний файл выполнится до создания объекта, деструктуризация вызовет TypeError, потому что window.appConfig имеет значение undefined. Обращение к необъявленному имени дает ReferenceError, а отсутствующее свойство существующего объекта возвращает undefined.

Атрибут defer откладывает выполнение внешнего классического скрипта до разбора HTML. Такие отложенные скрипты запускаются в порядке появления в документе. Блок данных ставьте выше script.js.

Модульный скрипт с type="module" без async тоже выполняется после разбора документа. Объект window.appConfig доступен и модулю. Добавлять defer модулю не требуется; подробности описаны в документации MDN о script.

Получение данных через fetch

Используйте fetch, когда данные зависят от запроса пользователя или меняются после загрузки страницы.

Создайте подпапку api внутри php-js-demo и сохраните обработчик в api/profile.php. На локальном сервере ему соответствует путь /api/profile.php.

Заголовок ответа отправляйте до любого вывода, включая HTML и пробелы перед PHP-кодом.

<?php
// /api/profile.php
header('Content-Type: application/json; charset=utf-8');

$response = [
    'name' => 'Анна',
    'notifications' => 3,
    'active' => true
];

echo json_encode(
    $response,
    JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
);

Поместите JavaScript в php-js-demo/script.js. Для этого примера замените содержимое index.php строкой <script src="/script.js" defer></script> и обновите http://127.0.0.1:8000/index.php.

async function loadProfile() {
  try {
    const response = await fetch('/api/profile.php');

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const profile = await response.json();
    console.log(profile.name);
    console.log(profile.notifications);
  } catch (error) {
    console.error('Профиль не загрузился', error);
  }
}

loadProfile();

Успешный запрос выведет имя Анна и число уведомлений 3. Проверка response.ok обнаруживает HTTP-ошибку до разбора JSON. Блок catch также обработает сетевой сбой и некорректный JSON.

HEX-флаги здесь не нужны: ответ передается отдельным JSON-документом. Если выводите полученный пользовательский текст на страницу, присваивайте его свойству textContent.

Сервер проверяет права доступа до формирования ответа. Персональные данные нельзя отдавать общей странице или общему кэшу для разных пользователей.

Как передать переменную из JavaScript в PHP

Обратное направление тоже использует HTTP-запрос. FormData подходит для отдельных полей, JSON – для объектов и массивов. Примеры возвращают полученные значения без записи в базу данных.

POST с FormData

PHP получает поля формы через массив $_POST. Не задавайте заголовок Content-Type вручную: браузер добавит границу multipart-данных.

Сохраните обработчик в php-js-demo/api/save-name.php, JavaScript – в php-js-demo/script.js. В index.php оставьте подключение <script src="/script.js" defer></script>.

<?php
// /api/save-name.php
$name = $_POST['name'] ?? '';

header('Content-Type: application/json; charset=utf-8');
echo json_encode([
    'saved' => true,
    'name' => $name
], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
async function saveName() {
  const formData = new FormData();
  formData.append('name', 'Анна');

  const response = await fetch('/api/save-name.php', {
    method: 'POST',
    body: formData
  });

  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  const result = await response.json();
  console.log(result.saved, result.name);
}

saveName().catch(error => {
  console.error('Запрос не выполнен', error);
});

После обновления http://127.0.0.1:8000/index.php в консоли появятся true и имя Анна. Поле saved здесь демонстрирует ответ сервера, но не подтверждает сохранение.

Перед реальной записью проверьте тип, формат, длину и права пользователя.

POST с JSON-телом

JSON подходит для объекта или массива. PHP читает тело через php://input, а параметр true у json_decode превращает JSON-объекты в ассоциативные массивы.

Сохраните PHP-код в php-js-demo/api/save-settings.php, JavaScript – в php-js-demo/script.js. В index.php оставьте подключение <script src="/script.js" defer></script>.

<?php
// /api/save-settings.php
header('Content-Type: application/json; charset=utf-8');

try {
    $body = file_get_contents('php://input');
    $data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $error) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid JSON'], JSON_THROW_ON_ERROR);
    exit;
}

if (!is_array($data) || !is_string($data['theme'] ?? null)) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid theme'], JSON_THROW_ON_ERROR);
    exit;
}

echo json_encode([
    'saved' => true,
    'theme' => $data['theme']
], JSON_THROW_ON_ERROR);
async function saveSettings() {
  const settings = { theme: 'dark', compact: true };

  const response = await fetch('/api/save-settings.php', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(settings)
  });

  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  const result = await response.json();
  console.log(result.saved, result.theme);
}

saveSettings().catch(error => {
  console.error('Запрос не выполнен', error);
});

После обновления страницы в консоли появятся true и строка dark. Этот обработчик тоже только возвращает данные. Если запрос изменяет состояние с авторизацией через cookie, добавьте проверку прав и защиту от CSRF.

GET-параметры подходят для коротких значений при чтении данных: PHP получает их через $_GET. HTML-форма отправляет поля без JavaScript, а форма с method="post" заполняет $_POST. JSON-тело не заполняет этот массив автоматически.

Ошибки при передаче переменных из PHP в JS

Выберите экранирование по месту вывода. Защита JavaScript не заменяет защиту HTML-атрибута.

  • Сырой echo в JavaScript. Кавычка пользователя ломает код, а текст с </script> может закрыть тег. Используйте json_encode с HEX-флагами.
  • Лишние кавычки вокруг JSON. У строки результат json_encode уже содержит внешние двойные кавычки. Подстановка в запись const data = "<?= json_encode($data) ?>"; даст две пары кавычек и синтаксическую ошибку. У числового массива вроде [1, 2] внутренних кавычек нет, поэтому внешние кавычки превратят значение в строку. Оставляйте JSON без добавленных кавычек.
  • HTML-сущности в application/json. Не применяйте htmlspecialchars к raw text-блоку, который затем читает textContent.
  • Пропущенное экранирование атрибута. Для data-* применяйте htmlspecialchars(..., ENT_QUOTES, 'UTF-8').
  • Неверный тип. Data-атрибут всегда строка. Массив из JSON нужно разобрать через JSON.parse.
  • Ассоциативный массив принят за список. Последовательный массив становится JavaScript-массивом, а именованные ключи создают объект. Пропуски в числовых индексах тоже превращают массив в объект; для списка сбросьте индексы через array_values.
  • Скрипт загружен раньше данных. Обращение к необъявленному имени вызывает ReferenceError. Деструктуризация отсутствующего window.appConfig вызывает TypeError.
  • Персональные данные попали в кэш. Не отдавайте страницу одного пользователя как общую страницу для всех.

Inline-код требует отдельного разрешения политики CSP. Если политика запрещает его, вынесите логику во внешний файл и передайте данные через JSON-блок или fetch. Разрешите загрузку внешнего скрипта, а для запросов – нужный адрес через connect-src.

Nonce разрешает конкретный исполняемый скрипт, когда значение совпадает с политикой CSP. Сервер генерирует непредсказуемое значение заново для каждого ответа. Правила nonce описаны в документации MDN по CSP.

Как выбрать способ под задачу

Для небольшой настройки, которая нужна сразу, используйте json_encode во встроенном скрипте. Этот вариант короткий, но требует разрешения inline-кода в CSP.

Для внешнего файла выберите JSON-блок или window.appConfig. JSON-блок отделяет данные от логики, а глобальный объект проще читать из нескольких скриптов.

Короткий идентификатор элемента храните в data-*. Формат подходит, когда значение живет рядом с конкретной кнопкой или карточкой.

Меняющиеся или персональные данные получайте через fetch, чтобы сервер обработал каждый запрос. Для обычной формы отправляйте FormData, для объекта или массива – JSON-тело.

Совет от нашей редакции: сначала определите место вывода, затем выберите экранирование – JSON нужен JavaScript, а htmlspecialchars нужен HTML-атрибуту.

Комментарии

Оставьте свой комментарий
С
самира

а то я не могу создать игру в однаклассниках

N
NAME

НАФИГ ТУТ ПИСАТЬ ЭТО JAVASCRIPT А НЕ JAVA

С
самира

✳

С
самира

а как зарегистрироваться в jave

N
NAME

В JAVE регестрироваться не надо