Статьи

Обнаружение устройства на стороне сервера с помощью браузера

Обеспечение возможности адаптации веб-сайтов к нескольким устройствам, в частности к мобильным устройствам, становится все более важным и сложным. Разнообразие способов, с помощью которых люди просматривают веб-страницы. Во многом это было вызвано ростом использования мобильных устройств для доступа в Интернет, хотя это также относится и к таким устройствам, как планшеты, интернет-телевидение и т. Д.

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

Альтернативное решение проблемы состоит в том, чтобы использовать обнаружение устройства на стороне сервера, а затем предпринять определенные действия на основе этой информации. Одна из возможностей — просто перенаправить запросы на мобильный сайт на другой URL. Другой возможностью является адаптация макета — или даже контента — программным способом, так как он генерируется на сервере.

Основой этой статьи является использование подхода на стороне сервера, который подробно рассматривает проект Browser Capabilities Project или Browscap для краткости, чтобы предоставить информацию, на которой основываются эти решения.

Введение в строки пользовательских агентов

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

Когда вы делаете HTTP-запрос на получение страницы из веб-браузера, он включает в себя фрагмент информации, называемый строкой пользовательского агента . Это предоставляет информацию о том, кто делает запрос и включает в себя множество элементов.

Обычно строка пользовательского агента указывает, какой браузер используется — именно так службы аналитики могут определить, используете ли вы Chrome, Firefox, Safari, IE или один из множества других браузеров. Кроме того, он также может предоставить информацию о версии запрашивающего приложения. Это отлично подходит для определения сокращающегося числа пользователей IE6, например.

Конечно, браузер — это на самом деле просто определенный тип приложения. Помните, что HTTP-запросы не просто выдаются, когда ваш веб-браузер обращается к веб-странице или другому ресурсу. Запрос может быть от веб-сканера, программы чтения каналов (например, RSS), средства проверки, библиотеки, такой как cURL, или одного из потенциально бесконечного числа клиентов веб-служб.

Строка агента пользователя также используется для предоставления информации об операционной системе. Windows, Linux или Mac? iOS или Android? Это тоже квалифицируется с номерами версий.

Строка пользовательского агента часто также предоставляет информацию об используемом физическом устройстве, будь то настольный компьютер, ноутбук, мобильный телефон, планшет и т. Д.

Давайте посмотрим на некоторые примеры строк пользовательских агентов:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Firefox/24.0

— Это говорит о том, что запрос был сделан Firefox (точнее версия 24) с Mac на базе Intel.

Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25

— Safari на iPad (работает под управлением iOS6)

Opera/9.80 (J2ME/MIDP; Opera Mini/9.80 (S60; SymbOS; Opera Mobi/23.348; U; en) Presto/2.5.25 Version/10.54

— Версия 9 Opera Mini на мобильном телефоне на базе Java

Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30

— Мобильное Safari на телефоне Android

Вы можете просмотреть сотни строк пользовательских агентов онлайн по адресу useragentstring.com/pages/useragentstring.php .

Доступ к данным браузера

Учитывая количество переменных, количество возможных версий и, конечно, постоянно расширяющийся диапазон используемых физических устройств, вы поймете, что количество различных перестановок довольно велико и растет с каждым днем. Проект « Возможности браузера» является попыткой каталогизировать эти перестановки. Вы можете думать об этом как о базе данных строк пользовательских агентов, которая связывает их с некоторой информацией, которую мы можем извлечь из них.

На самом деле это не просто база данных, основанная на строке пользовательского агента; это набор правил и шаблонов, используемых для извлечения релевантных фрагментов информации, с перекрестными ссылками на известные браузеры, устройства и другую информацию.

PHP предлагает встроенную оболочку для данных Browscap в виде функции get_browser() . (См. Php.net/get-browser ). Однако есть два ключевых недостатка его использования. Поскольку PHP не поставляется с browscap.ini данных browscap.ini , вам нужно будет загрузить его вручную и настроить php.ini чтобы он указывал на соответствующее местоположение. Что еще более важно, потому что база данных регулярно обновляется, вам нужно будет заменить ее вручную, когда это произойдет.

К счастью, есть библиотеки, которые решают обе эти проблемы и не требуют дополнительной настройки. Есть несколько из них, но я рекомендую github.com/browscap/browscap-php .

Интеграция библиотеки Browscap

Я собираюсь использовать Slim Framework для следующих примеров. Вы можете предпочесть другую среду или вообще ее нет, но поскольку эта статья посвящена Browscap, я не хочу увязать в основах, таких как автозагрузка, маршрутизация или промежуточное ПО. Код для этой статьи доступен, чтобы вы могли следовать.

Самый простой способ начать работу — использовать Composer для загрузки зависимостей. Начнем с двух: Slim Framework и библиотеки Browscap. Создайте каталог проекта и в его корне файл composer.json чтобы указать эти зависимости:

 { "require": { "slim/slim": "2.2.*", "browscap/browscap-php": "1.0.*@dev" } } 

(Примечание. На момент написания статьи текущей версией Slim Framework является 2.3.0. Однако я намеренно использую 2.2.x для совместимости с библиотекой представления макета, которую мы будем использовать позже.)

Затем запустите композитор:

  php composer.phar установить 

Теперь у вас должна быть папка vendor в корне вашего проекта, содержащая обе библиотеки, а также автозагрузчик. Создайте общую папку в корне проекта и в этом файле index.php . Начните с включения автозагрузчика:

 <?php require '../vendor/autoload.php'; 

Давайте теперь создадим голое приложение Slim, которое очень просто:

 $app = new SlimSlim(); $app->get('/', function () { print 'Hello World'; }); $app->run(); 

На этом этапе вы, вероятно, захотите убедиться, что все установлено правильно, перейдя на новую страницу индекса.

Далее мы собираемся настроить библиотеку Browscap. Это решает три ключевые задачи:

  • загрузка фактического файла данных ( browscap.ini )
  • обработка данных для повышения эффективности поиска
  • поддержание данных в актуальном состоянии

Поскольку библиотека должна загружать и создавать некоторые файлы, нам нужен каталог кеша. Давайте сделаем это просто и создадим каталог кэша в корне проекта — просто не забудьте сделать его доступным для записи веб-сервером.

Мы указываем каталог кеша при создании экземпляра класса Browscap :

 use phpbrowscapBrowscap; // create a new Browscap object (loads or creates the cache) $bc = new Browscap('../cache'); 

Давайте проверим это, захватывая информацию и выбрасывая ее прямо на экран:

 // get information about the current browser's user agent $current_browser = $bc->getBrowser(); echo '<pre>'; print_r($current_browser); echo '</pre>'; 

Это может занять некоторое время для запуска в первый раз, поскольку библиотека должна загрузить INI-файл и выполнить некоторую обработку над ним — к счастью, последующие запросы будут значительно быстрее.

Если вы посмотрите в каталог кеша, вы увидите два файла; browscap.ini — это исходный файл данных, а cache.php — те же данные, но оптимизированные для более быстрого поиска. Разные библиотеки по-разному обрабатывают и оптимизируют данные INI. Возможно, вы захотите попробовать несколько из них и выполнить тесты производительности, чтобы определить, какой из них наиболее эффективен.

Интерпретация данных браузера

Вот пример вывода из кода в предыдущем разделе:

  stdClass Object
 (
     [browser_name] => Mozilla / 5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit / 537.36 (KHTML, как Gecko) Chrome / 27.0.1453.116 Safari / 537.36
     [browser_name_regex] => ^ mozilla / 5.0 (. * intel mac os x. *) applewebkit /.* (khtml, как gecko). * chrome / 27 .. * safari /.*$
     [browser_name_pattern] => Mozilla / 5.0 (* Intel Mac OS X *) AppleWebKit / * (KHTML, как Gecko) * Chrome / 27. * Safari / *
     [Parent] => Chrome 27.0
     [Платформа] => MacOSX
     [Win32] => 
     [Комментарий] => Chrome 27.0
     [Browser] => Chrome
     [Версия] => 27.0
     [MajorVer] => 27
     [MinorVer] => 0
     [Бета] => 1
     [Frames] => 1
     [IFrames] => 1
     [Таблицы] => 1
     [Cookies] => 1
     [JavaScript] => 1
     [JavaApplets] => 1
     [CssVersion] => 3
     [Platform_Version] => неизвестно
     [Альфа] => 
     [Win16] => 
     [Win64] => 
     [BackgroundSounds] => 
     [VBScript] => 
     [ActiveXControls] => 
     [isMobileDevice] => 
     [isSyndicationReader] => 
     [Crawler] => 
     [AolVersion] => 0
 ) 

То, что вы на самом деле увидите здесь, будет, конечно, зависеть от вашей машины, используемого вами браузера и того, какие версии. Но обратите внимание, что ключевые элементы информации были извлечены в свойства возвращаемого объекта, например:

  • browser_name — это исходная строка агента пользователя. Обратите внимание на двусмысленность — здесь упоминаются и Chrome, и Safari; Который из них?
  • Browser говорит нам, что я использую Chrome
  • Version — это версия Chrome, которую я использую
  • Platform говорит нам, что я использую Apple Macintosh

Кроме того, есть ряд характеристик моей установки, которые определены.

Tables , Cookies , Frames , IFrames , Javascript , JavaApplets , BackgroundSounds , VBScript и ActiveXControls предоставляют некоторую информацию о возможностях моего браузера — возможно, более полезную, чем другие в настоящее время!

Мы можем получить еще больше информации о возможностях браузера от CssVersion , который определяет максимальную версию спецификации CSS, которую поддерживает браузер.

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

isMobileDevice интересный и, пожалуй, самый полезный. То, что на самом деле представляет собой мобильное устройство, открыто для интерпретации, но в целом это даст нам все важные различия, скажем, между настольным компьютером и мобильным телефоном.

Работа с « isMobileDevice случаями» isMobileDevice выходит за рамки этой статьи и, более того, часто зависит от проекта. Например, должен ли планшет iPad или Android получить рабочий стол мобильной версии сайта — или должна быть конкретная версия планшета?

Мы вызвали getBrowser() без каких-либо дополнительных аргументов в примере, что означает, что строка пользовательского агента будет взята из запроса. Если вы хотите поиграть или провести дополнительное тестирование, вы можете передать строку пользовательского агента в качестве первого параметра, например:

 $current_browser = $bc->getBrowser( "Opera/9.80 (J2ME/MIDP; Opera Mini/9.80 (S60; SymbOS; Opera Mobi/23.348; U; en) Presto/2.5.25 Version/10.54" ); 

Кроме того, передача true в качестве третьего аргумента заставит функцию возвращать данные Browscap в виде массива, а не объекта, в качестве формата по умолчанию.

Использование Browscap для перенаправления на мобильный сайт

Теперь давайте посмотрим на некоторые практические примеры того, как вы можете использовать данные Browscap. Предположим, у вас есть отдельный мобильный веб-сайт, возможно, на поддомене, например, m.example.com, или, возможно, вы используете другой домен верхнего уровня, например, example.mobi. Вы можете просто перехватить все запросы к сайту рабочего стола и перенаправить мобильных посетителей на соответствующий сайт, используя хук. В этом случае мы используем slim.before , который вызывается до запуска приложения Slim:

 $app->hook('slim.before', function () use ($app) { // create a new Browscap object (loads or creates the cache) $bc = new Browscap('../cache'); // get information about the current browser's user agent $current_browser = $bc->getBrowser(); // redirect to the mobile site if this is mobile if ($current_browser->isMobileDevice) { $url = 'http://m.example.com'; $app->response()->redirect($url, 301); } }); 

Конечно, это не очень полезно в самом деле; запрос, скажем, http://example.com/about будет перенаправлен на http://m.example.com , то есть на домашнюю страницу мобильного сайта. Однако, если вы знаете, что структура сайта мобильного сайта совпадает со структурой сайта рабочего стола, вы можете сделать ее немного более полезной, проанализировав запрошенный URL-адрес:

 if ($current_browser->isMobileDevice) { $path = $app->request()->getResourceUri(); $url = 'http://m.example.com' . $path; $app->response()->redirect($url, 301); } 

Использование Browscap для переключения макетов

Другое распространенное использование данных Browscap — переключение макетов на стороне сервера для настольных и мобильных сайтов. Давайте возьмем наше приложение на основе Slim и сделаем именно это.

Первое, что нужно сделать, это обновить файл composer.json чтобы указать новую зависимость, небольшую удобную библиотеку, которую мы будем использовать для реализации макетов: github.com/petebrowne/slim-layout-view .

 { "require": { "slim/slim": "2.2.*", "browscap/browscap-php": "1.0.*@dev", "petebrowne/slim-layout-view": "0.1.*" } } 

Теперь запустите:

  обновление php composer.phar 

Это должно установить код для нового класса View, который обернет вывод нашего приложения в представление макета.

Теперь в корне вашего проекта создайте каталог templates . Внутри этого каталога layouts и в этих двух файлах — desktop.php и mobile.php .

Если говорить проще, то desktop.php будет выглядеть примерно так:

 <!DOCTYPE html> <html> <body> <h1>This is the Desktop Layout</h1> <?php echo $yield ?> </body> </html> 

mobile.php будет выглядеть примерно так:

 <!DOCTYPE html> <html> <body> <h1>This is the Mobile Layout</h1> <?php echo $yield ?> </body> </html> 

Это очень простые примеры, но их достаточно, чтобы проверить переключение раскладки.

Теперь измените экземпляр Slim на:

 $app = new SlimSlim(array( 'view' => 'SlimLayoutView', 'templates.path' => '../templates', 'layout' => 'layouts/desktop.php' )); 

Здесь мы говорим Slim использовать макеты, указав каталог шаблонов, который мы создали минуту назад, и по умолчанию используем наш макет рабочего стола.

Теперь создайте файл в шаблонах с именем home.php , например:

 <p>Hello World!</p> 

И измените свой маршрут на:

 $app->get('/', function () use ($app) { $app->render('home.php'); }); 

Посетите страницу, и вы должны увидеть заголовок «Это макет рабочего стола», а затем «Hello World!».

Хорошо, теперь нам нужно добавить возможность динамического переключения макетов для мобильных устройств. Для этого мы собираемся создать промежуточное программное обеспечение. Это промежуточное программное обеспечение будет запущено в течение жизненного цикла запроса и будет отвечать за обнаружение мобильного посетителя и, соответственно, за переключение макета.

Для создания промежуточного программного обеспечения мы просто расширяем SlimMiddleware и определяем метод call() . Имейте в виду, что каждое промежуточное ПО также несет ответственность за вызов следующего в Slim.

Вот наш скелет промежуточного программного обеспечения:

 class LayoutSwitcherMiddleware extends SlimMiddleware { public function call() { // get reference to application $app = $this->app; // call the next middleware $this->next->call(); } } 

Теперь нам нужно добавить это в приложение, поэтому сразу после создания экземпляра платформы Slim добавьте следующую строку:

 $app->add(new DeviceSwitcherMiddleware()); 

Если вы заходите на страницу, должен работать переключатель устройств — не стесняйтесь выводить что-то, чтобы убедиться, что это так.

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

Для этого добавьте эти строки перед строкой $this->next->call() :

 // create a new Browscap object (loads or creates the cache) $bc = new Browscap('../cache'); // get information about the current browser's user agent $current_browser = $bc->getBrowser(); // switch to the corresponding layout if this is mobile if (!$current_browser->isMobileDevice) { $app->config('layout', 'layouts/mobile.php'); } 

Если вы заходите на страницу с помощью мобильного устройства, вы должны увидеть используемый макет мобильного телефона.

На практике макеты вашего рабочего стола и мобильного устройства могут включать отдельные таблицы стилей, по-разному обрабатывать навигацию, включать или исключать регионы и т. Д.

Орлиные глаза среди вас заметят, что я сделал большой, но общий надзор. Это мое мнение — я надеюсь, что оно распространено — хотя по умолчанию все хорошо обслуживать мобильный веб-сайт, у мобильного пользователя всегда должна быть возможность посетить настольную версию сайта, если он того пожелает. Я не буду вдаваться в подробности, но одним из подходов может быть предоставление ссылки с флагом — например ? Desktop = true , который устанавливает cookie, который переопределяет автоматическое переключение макета.

Комбинирование серверной компоновки с RWD

Хотя переключение компоновки на стороне сервера и адаптивный веб-дизайн — это два разных подхода к одной и той же проблеме, нет никаких причин, по которым их нельзя использовать в унисон. Например, нет никаких причин, по которым вы не можете иметь разные макеты для разных групп устройств, но поддерживайте их адаптивность — в конце концов, даже среди того, что вы можете классифицировать для мобильных устройств, возможные различия в таких вещах, как разрешение экрана, могут быть огромными.

Другой пример — программный сайт

Знание того, какую операционную систему кто-то использует при просмотре веб-сайта, также может быть полезным. Предположим, вы создаете простой веб-сайт для продвижения приложения, доступного для Windows, Mac и Linux. На таких сайтах принято упрощать страницу загрузки такого сайта, чтобы попытаться угадать, какую версию ищет пользователь. Например, если вы заходите на сайт с помощью Mac, на нем будет видна соответствующая ссылка для скачивания — не забывая, конечно, что люди все же могут захотеть скачать альтернативные версии.

Вот один из способов, которым вы можете сделать это в файле шаблона:

 <?php if (!strncmp($current_browser->Platform, 'Win', 3)): ?> <p><a href="/downloads/windows.zip" class="btn btn-large btn-primary">Download for Windows</a></p> <p>Alternatively, download for <a href="/downloads/mac.dmg">Mac</a> or <a href="/downloads/linux.tar.gz">Linux</a>.</p> <?php elseif (!strncmp($current_browser->Platform, 'Mac', 3)): ?> <p><a href="/downloads/mac.dmg" class="btn btn-large btn-primary">Download for Mac</a></p> <p>Alternatively, download for <a href="/downloads/windows.zip">Windows</a> or <a href="/downloads/linux.tar.gz">Linux</a>.</p> <?php elseif ($current_browser->Platform == 'Linux'): ?> <p><a href="/downloads/linux.tar.gz" class="btn btn-large btn-primary">Download for Linux</a></p> <p>Alternatively, download for <a href="/downloads/windows.zip">Windows</a> or <a href="/downloads/mac.dmg">Mac</a>.</p> <?php else: ?> <p>Select your version:</p> <ul> <li><a href="/downloads/windows.zip">Windows</a></li> <li><a href="/downloads/mac.dmg">Mac</a></li> <li><a href="/downloads/linux.tar.gz">Linux</a></li> </ul> <?php endif; ?> 

Вы найдете реализацию этого (со стилями и значками) в сопроводительном коде.

Машина Windows может быть обозначена множеством строк, например, Win2000, WinXP, WinVista, Win7 … Таким образом, мы пытаемся идентифицировать Windows, посмотрев на начало строки. Другим способом было бы проверить флаги Win16, Win32 и Win64 в данных устройства Browscap. Конечно, если вы ориентируетесь на разные версии Windows, например, на разделение версий Vista и Windows 7, вы можете проверить наличие WinVista и Win7 соответственно.

Последний пример

Это довольно очевидно!

 $current_browser = $bc->getBrowser(); if (($current_browser->Browser == 'IE') && ($current_browser->MajorVer == 6)) { header('Location: http://www.ie6countdown.com/'); exit; } 

Резюме

В этой статье я представил идею обнаружения устройств на стороне сервера, подробно рассмотрев проект Browser Capabilities Project (Browscap). Я показал, как его можно использовать в качестве альтернативы или даже в дополнение к методам на стороне клиента для адаптации веб-сайтов для нескольких устройств, таких как адаптивный веб-дизайн. Хотя в моих примерах используется фреймворк Slim, принципы остаются неизменными независимо от того, какой подход вы предпочитаете.

Я также дал вам несколько идей о том, как еще вы можете использовать данные Browscap — если вы можете думать о других, обязательно сообщите мне об этом в комментариях!

Изображение через Fotolia