Исключение iPad из wp_is_mobile
Я столкнулся с очень раздражающей проблемой. Я создал свой сайт с медиа-запросами и is_mobile (наивно полагая, что is_mobile будет соответствовать меньшим экранам). После тестирования выяснилось, что iPad все портит (хотя, на самом деле, это я накосячил).
Все мои проблемы можно было бы легко решить, если бы удалось исключить iPad из функции wp_is_mobile. Как мне переписать эту функцию?
function wp_is_mobile() {
static $is_mobile;
if ( isset($is_mobile) )
return $is_mobile;
if ( empty($_SERVER['HTTP_USER_AGENT']) ) {
$is_mobile = false;
} elseif (
// многие мобильные устройства (все iPhone, iPad и т.д.)
(strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false
&& strpos($_SERVER['HTTP_USER_AGENT'], 'iPad') === false) // исключаем iPad
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false ) {
$is_mobile = true;
} else {
$is_mobile = false;
}
return $is_mobile;
}
Как мне это изменить?
Ответ t f заставил меня задуматься. На самом деле, я могу использовать основную функцию и адаптировать её по своему усмотрению, просто поместив всё в новую функцию. Вот что получилось:
function my_wp_is_mobile() {
static $is_mobile;
if ( isset($is_mobile) )
return $is_mobile;
if ( empty($_SERVER['HTTP_USER_AGENT']) ) {
$is_mobile = false;
} elseif (
strpos($_SERVER['HTTP_USER_AGENT'], 'Android') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') !== false
|| strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini') !== false ) {
$is_mobile = true;
} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'iPad') == false) {
$is_mobile = true;
} elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'iPad') !== false) {
$is_mobile = false;
} else {
$is_mobile = false;
}
return $is_mobile;
}

Всегда хорошо находить собственные решения, так что +1 за это. Однако я также обновил свой ответ. У меня была глупая опечатка: я проверял ===
, тогда как должен был проверить !==
— не знаю, как это произошло, но теперь я это исправил. Так что мой ответ должен работать тоже — что я ни в коем случае не говорю, чтобы вы его приняли! Просто по сути наши ответы/функции делают одно и то же — поэтому я просто хотел найти (и исправить) то, что было не так.

@tf Именно об этом я и говорил в своем комментарии! Но я собираюсь принять свой собственный ответ, потому что знаю, что он работает, а ваш код я не тестировал. Я не хочу, чтобы кто-то прочитал это и воспользовался вашим ответом, если я его не проверил. Я чувствую некоторую ответственность за эту ветку. Надеюсь, вы понимаете. Но все равно спасибо за старания!

Ребята, вам вообще удалось протестировать это вживую на iPad? Я прямо сейчас пытаюсь, но без успеха — iPad Air, локально.

Я знаю, что это старый пост, но хотел обновить его, показав правильный способ реализации предыдущих решений в WordPress. Начиная с версии 4.9.0, вместо создания дополнительной функции следует фильтровать результат wp_is_mobile(). Вот так:
function myprefix_exclude_ipad( $is_mobile ) {
if (strpos($_SERVER['HTTP_USER_AGENT'], 'iPad') !== false) {
$is_mobile = false;
}
return $is_mobile ;
}
add_filter( 'wp_is_mobile', 'myprefix_exclude_ipad' );
ОДНАКО по-настоящему правильным решением было бы переписать тему, чтобы она корректно работала на планшетах. Ведь существуют и другие производители планшетов помимо Apple.

Вы также можете использовать регулярно обновляемый класс Mobile Detect PHP для создания пользовательской функции обнаружения мобильных устройств, исключая планшеты (включая iPad). На момент написания этого ответа репозиторий на Github был последний раз обновлен 3 месяца назад для включения обнаружения новых планшетов Samsung.
Предполагая, что вы разместили необходимый файл в директории /includes/
вашей темы, вы можете добавить этот код в ваш functions.php:
require_once(get_template_directory() . '/includes/Mobile_Detect.php');
function md_is_mobile() {
$detect = new Mobile_Detect;
if( $detect->isMobile() && !$detect->isTablet() ){
return true;
} else {
return false;
}
}
Затем используйте функцию md_is_mobile()
как замену для wp_is_mobile()
.

Разве это решение не зависит от установки плагина, содержащего класс Mobile Detect?

Зависимость от класса Mobile Detect обрабатывается первой строкой приведённого блока кода; дополнительные плагины не требуются. Стоит отметить, что существуют плагины для WordPress на основе этого класса, например WP Mobile Detect, но он не обновлялся почти 2 года, поэтому лично я предпочитаю использовать PHP-класс напрямую, который, судя по всему, активно разрабатывается.

Справедливый ответ, однако вам необходимо установить файл Mobile_Detect.php, который я называю плагином.

Я немного переписал (и, на мой взгляд, оптимизировал) вашу функцию:
function wp_is_mobile() {
static $is_mobile;
if (isset($is_mobile))
return $is_mobile;
if (
! empty($_SERVER['HTTP_USER_AGENT'])
// пропускаем, если это iPad
&& false === strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')
// все остальные мобильные устройства
&& (
false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile')
|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Android')
|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Silk/')
|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Kindle')
|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry')
|| false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera Mini')
)
) $is_mobile = true;
else $is_mobile = false;
return $is_mobile;
}
// РЕДАКТИРОВАНИЕ:
Хорошо, ещё раз...
Напишем новую функцию, которая внутри использует основную функцию и расширяет её:
function my_wp_is_mobile() {
if (
! empty($_SERVER['HTTP_USER_AGENT'])
// пропускаем, если это iPad
&& false !== strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')
) return false;
return wp_is_mobile();
} // function my_wp_is_mobile
Теперь вы можете использовать вашу новую функцию my_wp_is_mobile
где угодно.

Значит, я могу просто поместить это в файл functions.php, и он автоматически перезапишет основную функцию?

Упс, извините, моя ошибка — я никогда не использовал это (и поэтому не знал, что это ядро WP). Поскольку функция не является заменяемой, вы не можете просто поместить это в ваш файл functions.php
. Я обновлю свой ответ через минуту...

Кажется, это не работает. Но разве user agent для iPad не должен возвращать true?

Хм? Я понял так, что ты хочешь исключить iPads из списка мобильных устройств - как это делает wp_is_mobile
...? Так что именно не работает (как ты хотел бы)?

К сожалению, у меня самого нет iPad, поэтому я полагаюсь на информацию от друзей. Но сейчас у меня есть дизайн, который загружает сайдбар, если user agent "!is_mobile" (не мобильный), но для iPad это не нужно, так как его разрешение достаточно большое. Друзья говорят мне, что даже при использовании if(!my_wp_is_mobile() )
сайдбар все равно не отображается. Из чего я делаю вывод, что функция не работает.

И что я имел в виду в своем комментарии: я думал, что функция проверяет "если user agent НЕ пустой И если ЛОЖЬ, что user agent - это iPad" возвращает false. Но мне кажется, мне нужно "если user agent НЕ пустой и если ИСТИНА, что user agent - это iPad"? Возможно, это связано с тем, что ты запускаешь основную функцию ядра после кастомной функции? И тогда $_SERVER['HTTP_USER_AGENT'], 'Mobile')
вернет true для iPad.
