
🐛 WordPress и JoomSport: исправляем ошибки и допиливаем плагин под себя
Спортивные сайты на WordPress, редкий зверь. Когда федерации тенниса понадобился сайт с расписанием матчей, турнирными таблицами и профилями игроков, выбор плагинов оказался до обидного мал. JoomSport PRO стал единственным адекватным вариантом, но и он заставил попотеть.
Порог вхождения у плагина приличный: настройка под конкретный вид спорта требует времени, а местами код ведёт себя так, будто писался не для опытных пользователей WordPress. Зато у JoomSport есть сильная команда поддержки, которая отвечает на каждое обращение в хелпдеске, и это серьёзный плюс, когда допиливаешь плагин под проект.
Ниже, коллекция проверенных правок и сниппетов, собранных на реальном проекте. Они решают конкретные проблемы: от назойливого копирайта до фильтрации контента и шаблонов вывода. Все фрагменты кода актуальны для JoomSport версии 5.7.x (на июнь 2026, 5.7.8).
💡 Быстрый обзор:
- Убираем копирайт плагина: одна строка в шаблоне
- Чиним пагинацию и ошибку деления на ноль
- Добавляем поддержку миниатюр для записей JoomSport
- Пишем функцию авто-добавления эскиза в галерею
- Рассчитываем и сохраняем возраст игрока в метаполе
- Сохраняем первую букву фамилии для сортировки
- Создаём шаблоны вывода для кастомных типов записей
Убираем копирайт JoomSport
В бесплатной версии плагин выводит ссылку «powered by JoomSport» в футере страниц сезона. Мелочь, но на клиентском сайте смотрится неуместно.
Файл для правки:
1 /wp-content/plugins/joomsport-sports-league-results-management/sportleague/views/default/season.php
В районе 79-й строки найдите и удалите строку, содержащую ссылку на joomsport.com. После обновления плагина правку придётся повторить, учитывайте это при настройке автообновлений.
Исправляем ошибку пагинации
Если в логах появилось предупреждение:
Warning: Division by zero in.../class-jsport-pagination.php on line 72
, значит плагин пытается поделить на ноль при расчёте страниц. Проблема возникает, когда переменная $limit не определена или равна нулю.
Файл:
1 /wp-content/plugins/joomsport-sports-league-results-management/sportleague/classes/class-jsport-pagination.php
Найдите строку 70:
1 $npage = ceil($this->setcurrent / $limit);
Замените на:
1 if (isset($limit) && $limit > 0) { 2 $npage = ceil($this->setcurrent / $limit); 3 }
Оборачиваем деление в проверку: если $limit не задан или равен нулю, расчёт просто не выполняется, ошибка исчезает.
Добавляем поддержку миниатюр для записей JoomSport
По умолчанию кастомные типы записей JoomSport (joomsport_player, joomsport_season и другие) не поддерживают миниатюры. Без этого нормальную галерею или карточку игрока не построишь.
Добавьте в functions.php темы:
1 add_post_type_support('joomsport_player', 'thumbnail'); 2 add_post_type_support('joomsport_season', 'thumbnail');
Теперь в админке появится стандартный блок «Featured image» для игроков и сезонов. Аналогично можно добавить поддержку миниатюр для любого кастомного типа JoomSport, просто подставьте нужный slug.
Каркас для функций обработки данных JoomSport
Все дальнейшие сниппеты работают внутри одного хука save_post. Он срабатывает при сохранении записи и позволяет автоматически заполнять метаполя.
Создайте в functions.php такую обёртку:
1 function my_custom_save_post($post_id) { 2 3 function jswpla__meta_save_SDStudio($post_id) { 4 5 // Здесь размещайте функции из разделов ниже 6 7 } 8 add_action('save_post', 'jswpla__meta_save_SDStudio'); 9 } 10 add_action('save_post_joomsport_player', 'my_custom_save_post');
Хук save_post_joomsport_player обеспечивает запуск только при сохранении записей типа «игрок». Для других типов (joomsport_season, joomsport_match), поменяйте суффикс.
Авто-добавление эскиза записи в галерею
Когда игроков десятки, вручную проставлять изображение в галерею JoomSport, рутина. Вот функция, которая при сохранении записи сама подхватывает ID эскиза и добавляет его первым в галерею:
1 $thumbnail_ID = get_post_thumbnail_id($post_id); 2 $values = [$thumbnail_ID]; 3 4 $check_id_thumb = get_post_meta($post_id, 'vdw_gallery_id'); 5 $My_False = false; 6 7 foreach ($check_id_thumb as $metakey) { 8 if (strpos($values, $check_id_thumb) !== false) { 9 $My_False = true; 10 } 11 } 12 13 if (!$My_False) { 14 add_post_meta($post_id, 'vdw_gallery_id', $values); 15 }
Логика простая: берём ID эскиза, проверяем, есть ли он уже в метаполе vdw_gallery_id. Если нет, добавляем. Если есть, пропускаем, дубликатов не плодим.
Рассчитываем возраст игрока в метаполе
JoomSport хранит дату рождения игрока в метаполе _joomsport_player_ef. Чтобы вывести возраст на сайте, его нужно предварительно рассчитать и сохранить. Код основан на решении со StackExchange и документации ACF.
1 $date_of_birth = get_post_meta($post_id, '_joomsport_player_ef', false); 2 3 foreach ($date_of_birth as $metakey) { 4 $metakey_borthay = $metakey[3]; 5 } 6 7 $age = intval(date('Y', time() - strtotime($metakey_borthay))) - 1970; 8 9 delete_post_meta($post_id, 'age_field'); 10 add_post_meta($post_id, 'age_field', $age);
Дата рождения хранится в четвёртом элементе массива (индекс [3]) метаполя _joomsport_player_ef. Функция извлекает её, считает возраст и записывает в отдельное метаполе age_field, его уже можно использовать в шаблоне или для фильтрации.
Сохраняем первую букву фамилии
Для сортировки игроков по алфавиту или быстрого поиска удобно иметь отдельное поле с первой буквой фамилии. JoomSport хранит имя и фамилию в метаполе _joomsport_player_personal.
1 $val_last_name = get_post_meta($post_id, '_joomsport_player_personal', false); 2 3 foreach ($val_last_name as $metakey) { 4 $metakey_Last_Name = $metakey['last_name']; 5 } 6 7 $metakey_Last_Name = preg_split('//u', $metakey_Last_Name, -1, PREG_SPLIT_NO_EMPTY); 8 $metakey_Last_Name = $metakey_Last_Name[0]; 9 10 $check_Liter_Last_Name = get_post_meta($post_id, 'First_letter_Last_Name'); 11 $My_False_Liter_Last_Name = false; 12 13 foreach ($metakey_Last_Name as $check_liter) { 14 if (strpos($check_Liter_Last_Name, $metakey_Last_Name) !== false) { 15 $My_False_Liter_Last_Name = true; 16 } 17 } 18 19 if (!$My_False_Liter_Last_Name) { 20 update_post_meta($post_id, 'First_letter_Last_Name', $metakey_Last_Name); 21 }
preg_split с флагом PREG_SPLIT_NO_EMPTY корректно разбивает UTF-8 строку на символы, включая кириллицу. Первый символ массива фамилии сохраняется в метаполе First_letter_Last_Name.
Поиск и замена текста на всём сайте
Универсальный сниппет для массовой замены текста в контенте и excerpt'ах. Пригодится не только для JoomSport, используйте для любых глобальных правок.
1 function replace_text_wps($text) { 2 $replace = array( 3 'getimagesizefromstring' => 'excerpt', 4 'functidrgon' => 'function' 5 ); 6 $text = str_replace(array_keys($replace), $replace, $text); 7 return $text; 8 } 9 add_filter('the_content', 'replace_text_wps'); 10 add_filter('the_excerpt', 'replace_text_wps');
Добавьте свои пары в массив $replace, и замена применится ко всем записям на лету. Работает быстрее плагинов для поиска-замены, но помните: это фильтр, исходный контент в базе не меняется.
Шаблоны вывода для кастомных типов JoomSport
JoomSport регистрирует несколько кастомных типов записей, среди которых joomsport_player, joomsport_season и joomsport_match. По умолчанию они выводятся через single.php темы, и выглядит это почти всегда неаккуратно.
Решение, создать отдельный шаблон. Для типа «игрок»:
1 single-joomsport_player.php
Файл размещается в корне темы. Название строится по правилу иерархии шаблонов WordPress: single-{slug}.php. Аналогично: single-joomsport_season.php для сезонов, single-joomsport_match.php для матчей.
Содержимое файла берите из single.php вашей темы и адаптируйте под нужную структуру. Например, для темы Cactus базовый шаблон страницы игрока выглядит так:
1 <?php 2 /* Template Name: Post joomsport_player */ 3 4 get_header(); 5 6 $page_sidebar_layout = apply_filters('cactus_page_sidebar_layout', cactus_option('page_sidebar_layout')); 7 switch ($page_sidebar_layout) { 8 case 'left': 9 $aside_class = 'left-aside'; 10 break; 11 case 'right': 12 $aside_class = 'right-aside'; 13 break; 14 default: 15 $aside_class = 'no-aside'; 16 break; 17 } 18 ?> 19 20 <?php echo apply_filters('cactus_page_title_bar', '', 'page'); ?> 21 22 <div class="page-wrap"> 23 <?php do_action('cactus_before_page_wrap'); ?> 24 <div class="container"> 25 <div class="page-inner row <?php echo $aside_class; ?>"> 26 <div class="col-main"> 27 <section class="post-main" role="main" id="content"> 28 <article class="post-entry text-left"> 29 <?php do_action('cactus_before_page_content'); ?> 30 31 <?php 32 while (have_posts()) : 33 the_post(); 34 get_template_part('template-parts/page/content'); 35 the_posts_pagination(array( 36 'prev_text' => '<i class="fa fa-arrow-left"></i><span class="screen-reader-text">' . __('Previous page', 'cactus') . '</span>', 37 'next_text' => '<span class="screen-reader-text">' . __('Next page', 'cactus') . '</span><i class="fa fa-arrow-right"></i>', 38 'before_page_number' => '<span class="meta-nav screen-reader-text">' . __('Page', 'cactus') . ' </span>', 39 )); 40 endwhile; 41 ?> 42 43 <?php do_action('cactus_after_page_content'); ?> 44 </article> 45 46 <?php do_action('cactus_after_post_entry'); ?> 47 </section> 48 </div> 49 </div> 50 </div> 51 <?php do_action('cactus_after_page_wrap'); ?> 52 </div> 53 54 <?php get_footer(); ?> 55
Скопируйте этот код, замените CSS-классы и хуки на те, что использует ваша тема. Главное, структура: header, контейнер, сайдбар (опционально), основной цикл и footer.
Для быстрого старта с плагином посмотрите официальный туториал от BearDev, 11 минут, которые сэкономят пару часов настройки.
⁉️🤔 Частые вопросы
Работают ли эти правки на PRO-версии JoomSport?
Да, все сниппеты универсальны и проверены в том числе на PRO-версии. Хуки
save_post_joomsport_*и метаполя у бесплатной и платной версий идентичны. Единственный нюанс: PRO-версия добавляет свои кастомные типы записей, проверьте slug перед добавлением поддержки миниатюр.
Что делать, если после правки плагин перестал работать?
Откатите изменения: все правки делаются в
functions.phpтемы или в отдельных файлах шаблонов, ядро плагина не затрагивается. Исключение, удаление копирайта и исправление пагинации: там правятся файлы самого плагина, они слетят при обновлении. Перед любой правкой делайте резервную копию изменяемого файла.
Можно ли использовать эти функции для типов записей других плагинов?
Да, подход универсальный. Замените
joomsport_playerна slug нужного кастомного типа, а_joomsport_player_ef, на его метаполе. Код каркаса (обёртка с хукомsave_post) и логика проверок (get_post_meta→foreach→ условие) переиспользуются один в один.
Как добавить поддержку миниатюр для всех типов JoomSport разом?
Пройдитесь циклом по массиву slug'ов:
1 $joomsport_types = ['joomsport_player', 'joomsport_season', 'joomsport_match', 'joomsport_team']; 2 foreach ($joomsport_types as $type) { 3 add_post_type_support($type, 'thumbnail'); 4 }
Список всех кастомных типов плагина смотрите в его настройках или через
var_dump(get_post_types()).
Почему не стоит использовать допполя JoomSport для фильтрации?
JoomSport сбрасывает все значения дополнительных полей в один массив. Обратиться к конкретному полю со стороны фронтенда (например, при AJAX-фильтрации) практически нереально, данные склеены. Если нужна фильтрация игроков по возрасту, первой букве или любому другому критерию, сохраняйте значение в отдельное метаполе, как показано в разделах про
age_fieldиFirst_letter_Last_Name.
Ставить ли JoomSport под ваш проект?
JoomSport, нишевый, но мощный инструмент. Если вам нужен сайт спортивной лиги с таблицами, расписанием и профилями, альтернатив на WordPress откровенно мало. Плагин активно развивается: на июнь 2026 актуальная версия 5.7.8, разработчики оперативно закрывают уязвимости и добавляют фичи.
Слабое место, порог вхождения. Первая настройка требует терпения, а часть поведения плагина рассчитана скорее на разработчиков, чем на обычных пользователей. Но поддержка у beardev действительно хорошая: на каждое сообщение в хелпдеске приходит развёрнутый ответ, часто с готовым сниппетом.
Если проект спортивный и бюджет ограничен, берите JoomSport, закладывайте время на допиливание. Код из этой статьи закроет большинство типовых проблем, с которыми сталкиваются разработчики при интеграции плагина в живой сайт.



