WordPress модуль для Яндекс.Карт: проекты на карте с ACF и кластеризацией
Если тебе нужно показать реализованные проекты на карте — например, установленное оборудование в разных городах — обычные решения либо слишком сложные, либо не дают нужной гибкости. Модуль проектов для WordPress решает эту задачу просто: кастомный тип записи для проектов, ACF поля для координат и адресов, интеграция с Яндекс.Картами с кластеризацией меток. Всё готово к использованию, легко переносится в другой сайт. (GitHub)
Главное преимущество: проекты не имеют публичных страниц — они используются только для отображения на карте. Это идеально для случаев, когда нужно показать локации без создания отдельных страниц для каждого проекта.
Задача: что нужно было решить
Типичная ситуация: у тебя есть список реализованных проектов (например, установленное оборудование), и нужно показать их на карте с информацией:
- координаты (широта/долгота)
- адрес
- тип и модель оборудования
- описание проекта
При этом:
- проекты должны управляться через админку WordPress
- карта должна автоматически группировать близкие метки (кластеризация)
- решение должно быть переносимым в другой сайт
- если проектов нет — показывать тестовые данные для демонстрации
Архитектура решения
Модуль состоит из четырёх основных файлов:
- projects.php — регистрация кастомного типа записи и таксономии
- projects-acf.php — ACF поля для координат и данных проектов
- projects-map.php — функции для работы с картой, подключение скриптов
- projects-loader.php — главный файл, который подключает всё остальное
Почему именно такая структура
Разделение на файлы делает модуль:
- понятным — каждый файл отвечает за свою задачу
- переносимым — можно скопировать папку и подключить в другом сайте
- расширяемым — легко добавить новые поля или функции
Шаг 1: Регистрация кастомного типа записи
Файл: projects.php
<?php
add\_action('init', function(){
register\_post\_type('projects', array(
'labels' => array(
'name' => 'Проекты',
'singular\_name' => 'Проект',
'add\_new' => 'Добавить новый',
'add\_new\_item' => 'Добавить новый проект',
'edit\_item' => 'Редактировать проект',
'menu\_name' => 'Проекты',
),
'public' => false, // Проекты только для карты
'publicly\_queryable' => false, // Нельзя открыть отдельную страницу
'show\_in\_nav\_menus' => false, // Не показывать в меню
'supports' => ['title', 'editor', 'thumbnail'],
'show\_ui' => true, // Показывать в админке
'has\_archive' => false, // Нет архива
'show\_in\_rest' => true,
'menu\_icon' => 'dashicons-location-alt'
));
});
Важно: 'public' => false означает, что проекты не имеют публичных URL. Они используются только для карты, что идеально для локаций без отдельных страниц.
Регистрация таксономии для типов оборудования
add\_action('init', function(){
register\_taxonomy('project-equipment', ['projects'], [
'label' => 'Тип оборудования',
'public' => false, // Таксономия не публичная
'show\_ui' => true,
'show\_in\_rest' => true,
'hierarchical' => true,
'show\_admin\_column' => true
]);
});
Шаг 2: ACF поля для координат и данных
Файл: projects-acf.php
ACF поля создаются программно через acf_add_local_field_group(). Это удобно, потому что поля автоматически создаются при активации темы — не нужно настраивать их вручную.
<?php
if(function\_exists('acf\_add\_local\_field\_group')):
acf\_add\_local\_field\_group(array(
'key' => 'group\_projects\_fields',
'title' => 'Поля проекта',
'fields' => array(
array(
'key' => 'field\_project\_latitude',
'label' => 'Широта (Latitude)',
'name' => 'project\_latitude',
'type' => 'text',
'required' => 1,
'placeholder' => '55.751574',
),
array(
'key' => 'field\_project\_longitude',
'label' => 'Долгота (Longitude)',
'name' => 'project\_longitude',
'type' => 'text',
'required' => 1,
'placeholder' => '37.573856',
),
array(
'key' => 'field\_project\_address',
'label' => 'Адрес',
'name' => 'project\_address',
'type' => 'text',
),
array(
'key' => 'field\_project\_equipment\_type',
'label' => 'Тип оборудования',
'name' => 'project\_equipment\_type',
'type' => 'text',
),
array(
'key' => 'field\_project\_equipment\_model',
'label' => 'Модель оборудования',
'name' => 'project\_equipment\_model',
'type' => 'text',
),
),
'location' => array(
array(
array(
'param' => 'post\_type',
'operator' => '==',
'value' => 'projects',
),
),
),
));
endif;
Почему программное создание полей:
- Поля создаются автоматически при активации темы
- Не нужно настраивать их вручную в админке
- Легко перенести модуль в другой сайт
Шаг 3: Функция получения проектов для карты
Файл: projects.php
/\*\*
- Получить все проекты для карты
- @return array Массив проектов с координатами
\*/
function get\_projects\_for\_map() {
$projects = get\_posts(array(
'post\_type' => 'projects',
'posts\_per\_page' => -1,
'post\_status' => 'publish'
));
$projects\_data = array();
foreach ($projects as $project) {
$latitude = get\_field('project\_latitude', $project->ID);
$longitude = get\_field('project\_longitude', $project->ID);
$address = get\_field('project\_address', $project->ID);
$equipment\_type = get\_field('project\_equipment\_type', $project->ID);
$equipment\_model = get\_field('project\_equipment\_model', $project->ID);
// Пропускаем проекты без координат
if (empty($latitude) || empty($longitude)) {
continue;
}
$projects\_data[] = array(
'id' => $project->ID,
'title' => get\_the\_title($project->ID),
'latitude' => floatval($latitude),
'longitude' => floatval($longitude),
'address' => $address ?: '',
'equipment\_type' => $equipment\_type ?: '',
'equipment\_model' => $equipment\_model ?: '',
'description' => wp\_strip\_all\_tags(get\_the\_excerpt($project->ID))
);
}
return $projects\_data;
}
Что делает функция:
- Получает все опубликованные проекты
- Извлекает ACF поля (координаты, адрес, оборудование)
- Пропускает проекты без координат
- Возвращает массив, готовый для передачи в JavaScript
Шаг 4: Подключение Яндекс.Карт и скриптов
Файл: projects-map.php
/\*\*
- Подключение скриптов и стилей для карты проектов
\*/
function enqueue\_projects\_map\_assets() {
// Подключаем только на странице с шаблоном карты
if (is\_page\_template('template-projects-map.php')) {
// Получаем API ключ из настроек ACF
$yandex\_api\_key = get\_field('yandex\_maps\_api\_key', 'options') ?: '';
if (empty($yandex\_api\_key)) {
$yandex\_api\_key = 'YOUR\_API\_KEY'; // Замените на ваш API ключ
}
// Регистрируем API Яндекс.Карт
wp\_register\_script(
'yandex-maps-api',
'https://api-maps.yandex.ru/2.1/?apikey=' . esc\_attr($yandex\_api\_key) . '&lang=ru\_RU',
array(),
'2.1',
false
);
// Получаем данные проектов
$projects\_data = get\_projects\_map\_data();
// Передаем данные в JavaScript
wp\_localize\_script('yandex-maps-api', 'projectsMapData', array(
'projects' => $projects\_data
));
// Подключаем скрипты
wp\_enqueue\_script('yandex-maps-api');
wp\_enqueue\_script(
'projects-map-js',
get\_template\_directory\_uri() . '/inc/modules/projects/assets/js/projects-map.js',
array('yandex-maps-api'),
'1.0.0',
true
);
// Подключаем стили
wp\_enqueue\_style(
'projects-map-css',
get\_template\_directory\_uri() . '/inc/modules/projects/assets/css/projects-map.css',
array(),
'1.0.0'
);
}
}
add\_action('wp\_enqueue\_scripts', 'enqueue\_projects\_map\_assets');
Важные моменты:
- Скрипты подключаются только на странице с шаблоном карты
- API ключ берётся из настроек ACF (можно настроить в админке)
- Данные проектов передаются в JavaScript через wp_localize_script()
Шаг 5: JavaScript для инициализации карты
Файл: assets/js/projects-map.js
(function () {
"use strict";
document.addEventListener("DOMContentLoaded", function () {
if (
typeof ymaps !== "undefined" &&
typeof projectsMapData !== "undefined"
) {
ymaps.ready(function () {
var projectsData = projectsMapData.projects || [];
// Создаем карту
var myMap = new ymaps.Map("yandex-map", {
center: [55.751574, 37.573856], // Москва по умолчанию
zoom: 5,
controls: ["zoomControl", "typeSelector", "fullscreenControl"],
});
// Создаем кластеры для меток
var clusterer = new ymaps.Clusterer({
preset: "islands#invertedBlueClusterIcons",
groupByCoordinates: false,
clusterDisableClickZoom: true,
clusterHideIconOnBalloonOpen: false,
geoObjectHideIconOnBalloonOpen: false,
});
// Добавляем метки для каждого проекта
projectsData.forEach(function (project) {
var placemark = new ymaps.Placemark(
[project.latitude, project.longitude],
{
balloonContentHeader:
"<strong>" + escapeHtml(project.title) + "</strong>",
balloonContentBody:
(project.equipment\_type
? "<p><strong>Тип оборудования:</strong> " +
escapeHtml(project.equipment\_type) +
"</p>"
: "") +
(project.equipment\_model
? "<p><strong>Модель:</strong> " +
escapeHtml(project.equipment\_model) +
"</p>"
: "") +
(project.address
? "<p><strong>Адрес:</strong> " +
escapeHtml(project.address) +
"</p>"
: "") +
(project.description
? "<p>" + escapeHtml(project.description) + "</p>"
: ""),
hintContent: escapeHtml(project.title),
},
{
preset: "islands#blueIcon",
}
);
clusterer.add(placemark);
});
myMap.geoObjects.add(clusterer);
// Устанавливаем границы карты, чтобы показать все метки
if (projectsData && projectsData.length > 0) {
myMap.setBounds(clusterer.getBounds(), {
checkZoomRange: true,
duration: 300,
});
}
});
}
});
// Функция для экранирования HTML (защита от XSS)
function escapeHtml(text) {
if (!text) return "";
var map = {
"&": "&",
"<": "<",
">": ">",
'"': """,
"'": "'",
};
return text.replace(/[&<>"']/g, function (m) {
return map[m];
});
}
})();
Что делает код:
- Инициализирует карту Яндекс.Карт
- Создаёт кластеры для группировки близких меток
- Добавляет метки для каждого проекта с балунами
- Автоматически подстраивает границы карты под все метки
- Экранирует HTML для защиты от XSS
Шаг 6: Fallback данные для демонстрации
Если проектов нет в базе данных, модуль автоматически использует тестовые данные. Это удобно для демонстрации функционала.
Файл: projects-map.php
/\*\*
- Получить данные проектов для карты (с fallback на тестовые данные)
\*/
function get\_projects\_map\_data() {
// Пытаемся получить данные из базы
if (function\_exists('get\_projects\_for\_map')) {
$projects\_data = get\_projects\_for\_map();
if (!empty($projects\_data)) {
return $projects\_data;
}
}
// Если проектов нет, возвращаем тестовые данные
return array(
array(
'id' => 1,
'title' => 'Крематор КД-300',
'latitude' => 55.751574,
'longitude' => 37.573856,
'address' => 'г. Москва, ул. Красная площадь, д. 1',
'equipment\_type' => 'Крематор',
'equipment\_model' => 'КД-300',
'description' => 'Установлен крематор КД-300 для утилизации отходов.'
),
// ... другие тестовые проекты
);
}
Зачем это нужно:
- Можно показать карту клиенту до добавления реальных проектов
- Удобно для тестирования и разработки
- Не нужно создавать тестовые записи в базе
Использование: создание страницы с картой
- Создай шаблон страницы
Файл: template-projects-map.php (в корне темы)
<?php
/\*\*
- Template Name: Карта проектов
\*/
get\_header();
?>
<div class="projects-map-page">
<?php
// Вывод заголовка и описания из ACF
$header = get\_field('header');
$description = get\_field('description');
if ($header) {
echo '<h1>' . esc\_html($header) . '</h1>';
}
if ($description) {
echo '<div class="projects-map-description">' . wp\_kses\_post($description) . '</div>';
}
// Вывод карты
if (function\_exists('render\_projects\_map')) {
render\_projects\_map();
}
?>
</div>
<?php
get\_footer();
Создай страницу в WordPress
Перейди в Страницы → Добавить новую
Название: "Реализованные проекты"
Выбери шаблон: Карта проектов
Заполни поля ACF (заголовок, описание)
Опубликуй страницу
Добавь проекты
Перейди в Проекты → Добавить новый
Заполни обязательные поля:
- Название проекта: например, "Крематор КД-300"
- Широта: 55.751574
- Долгота: 37.573856
- Адрес: "г. Москва, ул. Красная площадь, д. 1"
- Тип оборудования: "Крематор"
- Модель оборудования: "КД-300"
- Опубликуй проект
Перенос модуля в другой сайт
Модуль легко переносится в другой сайт:
- Скопируй папку модуля
cp -r projects /path/to/new/theme/inc/modules/
- Подключи модуль в functions.php
require\_once get\_template\_directory() . '/inc/modules/projects/projects-loader.php';
Установи ACF (если ещё не установлен)
Настрой API ключ
- Получи ключ на developer.tech.yandex.ru
- Установи в настройках темы: Настройки контента → Настройки Яндекс.Карт
Создай шаблон страницы (см. раздел "Использование")
Создай страницу с картой и добавь проекты
Кастомизация
Изменение внешнего вида карты
Файл: assets/css/projects-map.css
.projects-map\_\_container {
width: 100%;
height: 600px;
margin: 20px 0;
}
.projects-map\_\_map {
width: 100%;
height: 100%;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
Изменение настроек карты
Файл: assets/js/projects-map.js
// Изменить центр карты
center: [59.934280, 30.335098], // Санкт-Петербург
// Изменить масштаб
zoom: 10,
// Изменить иконки меток
preset: 'islands#redIcon'
Добавление дополнительных полей
- Добавь поле в ACF (projects-acf.php)
- Добавь поле в функцию get_projects_for_map() (projects.php)
- Используй поле в JavaScript (assets/js/projects-map.js)
Безопасность
Модуль включает базовые меры безопасности:
- ✅ Проверка прав доступа — все функции проверяют права доступа
- ✅ Экранирование данных — все выходные данные экранируются через esc_html(), esc_attr(), wp_kses_post()
- ✅ Валидация координат — проверка корректности координат перед добавлением на карту
- ✅ Защита от XSS — экранирование HTML в JavaScript через функцию escapeHtml()
Частые проблемы и решения
Проблема: Карта не отображается
- Решение: Проверь API ключ Яндекс.Карт, проверь консоль браузера на ошибки
Проблема: Метки не появляются на карте
- Решение: Убедись, что проекты опубликованы и имеют координаты
Проблема: Поля ACF не отображаются
- Решение: Убедись, что ACF установлен и активирован
Проблема: Скрипты не подключаются
- Решение: Проверь, что страница использует шаблон template-projects-map.php
Итог
Модуль проектов для WordPress — это готовое решение для отображения локаций на карте:
- ✅ Кастомный тип записи для управления проектами
- ✅ ACF поля для координат и данных
- ✅ Интеграция с Яндекс.Картами с кластеризацией меток
- ✅ Адаптивный дизайн
- ✅ Fallback данные для демонстрации
- ✅ Легкий перенос в другой сайт
Если тебе нужно показать реализованные проекты на карте без создания отдельных страниц для каждого проекта — этот модуль решает задачу просто и эффективно.
Ссылки
- WordPress модуль для Яндекс.Карт на GitHub
- Документация Яндекс.Карт API
- ACF (Advanced Custom Fields) — плагин для кастомных полей
- Получить API ключ Яндекс.Карт — регистрация и получение ключа
Top comments (0)