Блог Александра Денисюка

Программирование на PHP и вёрстка сайтов

Вконтакте Твиттер Хабрахабр

Любые предложения или замечания принимаю на
почту a@denisyuk.by или на номер +375 (29) 203-79-48.
Ctrl + ↑ Позднее

Отдельная почта для «спама»

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

У меня получилась одна основная почта a@denisyuk.by для коммуникации с реальными людьми и вторая, отдельная почта, rb@inbox.ru для «спама». Эту «спамную» почту я очистил от нежелательных подписок и откровенное говно перенёс в папку «Спам». Теперь они не должны меня больше беспокоить. Ещё в эту почту я добавил несколько рассылок: Большие планы, Главред, Дизайн текста, Лига читающих, Т—Ж, Финолог. Для регистрации на сайтах я так и буду дальше использовать «спамную» почту, а для общения с людьми — новую. Таким образом, я отделил мух от котлет:

    a@denisyuk.by — для общения с людьми и пересылки документов
    rb@inbox.ru — для регистраций на сайтах и email-подписок

Обычная почта во многом конкурирует с социальными сетями, хотя последние предлагают общение в realtime-режиме. На самом деле в мире бизнеса рулит почта. Её указывают на визитках, сайтах, рекламной продукции и т. д. Наличие почты на своём домене можно прировнять к хорошим часах на вашей руке. Если вы программист, дизайнер или маркетолог и у вас ещё нет своего домена, то можете завести почту на @gmail.com, так делают многие, даже те, у кого есть свой сайт. Дело в том, что они просто не хотят заморачиваться по переносу почты и её настройке, а вы возьмите и заморочьтесь.

Файл .htaccess и RewriteRule

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

Чтобы не томиться ожиданием, давайте сразу перейдём к задаче: нужно сделать перенаправление со страницы /pages/about.php на /about, т. е. убрать в адресе папку /pages и расширение .php в названии файла. Ещё нужно позаботиться о том, чтобы в конце URL не было закрывающего слеша. Вот такую файловую структуру содержит наш пример:

┌public_html/
├──pages/
│  ├──about.php
│  ├──contact.php
│  └──subscribe.php
├──index.php
└──.htaccess

В Apache для преобразования URL’ов есть специальный модуль mod_rewrite. Он отвечает за создание ЧПУ — создаёт красивые URL для PHP-скриптов на уровне веб-сервера. Его мы и задействуем для решения нашей задачи. Для начала создадим конфигурационный файл .htaccess в корне сайта со следующим содержимым, а затем я объясню как он отработает:

# Включаем mod_rewrite
RewriteEngine On

# Убираем последний слеш
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Преобразуем /pages/about.php в /about
RewriteRule ^(\w+)$ /pages/$1.php [L,NC]

Командой RewriteEngine On мы включаем модуль mod_rewrite, а с помощью RewriteRule задаём правила преобразования адресов. RewriteRule просто преобразует входной URL по порядку в соответствии с регулярными выражениями. В конце каждого правила можно задать флаги для указания поведения mod_rewrite при обработке URL. Синтаксис прост как три копейки:

RewriteRule новый реальный [флаг1,флаг2,флаг3]

Давайте разберём первое правило из примера: ^(.*)/$ /$1 [L,R=301] — между маркерами ^ и $ мы указали начало строки с любого символа и любой длины (.*), где конец строки должен заканчиваться на слеш /. Всё, что заключено в круглые скобки (.*) образует группу символов, которую можно использовать через макрос $1.

Теперь все URL’ы, которые заканчиваются на слеш, будут переброшены на адрес без последнего слеша, где /$1 — все входные символы без последнего слеша. Флаг [L] останавливает чтение .htaccess, а [R=301] генерирует HTTP-код ответа сервера HTTP/1.1 301 Moved Permanently. После того, как правило отработало и Apache обрезал закрывающий слеш, файл .htaccess выполнится ещё раз и первое правило больше не отработает.

Второе правило: ^(\w+)$ /pages/$1.php [L,NC] — пользователь запросит адрес страницы, который имеет буквенное или цифровое содержимое от одного и больше символов (\w+). Это образует группу символов, которые мы подставим в адрес скрипта /pages/$1.php. По факту выполниться скрипт под другим URL. Флаг [L] останавливает .htaccess, а [NC] отменяет проверку регистра символов.

Все правила выполняются по порядку. Также стоит обратить внимание на значение флагов, которые могут менять поведение RewriteRule и веб-сервера. Ниже я собрал коллекцию флагов применительно для перенаправлений:

Флаг  Описание
———————————————————————————————————————————————————————————————————————————————
[C]   Chain — объединяет несколько правил в цепочку. Если первое правило
      цепочки не срабатывает, то вся цепочка игнорируется.

[F]   Forbidden — возвращает ошибку 403 Forbidden (запрещено).

[G]   Gone — возвращает ошибку 410 Gone (удалён).

[L]   Last — останавливает процесс преобразования, и текущая ссылка
      считается окончательной.

[N]   Next — запускает процесс преобразования с первого по порядку правила.

[NS]  NoSubreq — разрешает срабатывание правила только для настоящих
      запросов, игнорируя подзапросы.

[NC]  NoCase — отключает проверку регистра символов.

[P]   Proxy — даёт команду Apache выполнить подзапрос к указанной странице
      с использованием программного модуля mod_proxy, при этом пользователь
      ничего не узнает об этом подзапросе. Если модуль mod_proxy отсутствует,
      то произойдет ошибка.

[PT]  PassThrough — останавливает процесс преобразования и передает
      полученную новую ссылку дальше по цепочке.
      
[QSA] Qsappend — добавляет исходные параметры запроса (Query String)
      к замене. Если замена не включает в себя новые параметры запроса,
      то исходные параметры запроса добавляются автоматически. Если же
      включает, то без флага QSA исходные параметры запроса будут утеряны.

[R]   Redirect — останавливает процесс преобразования и возвращает
      результат браузеру клиента как редирект на новую страницу.
      По умолчанию передаётся HTTP-код 302 Moved Temporarily (перемещенно
      временно), но его можно изменить путём присвоения нового статуса
      через знак равенства [R=301]. В этом случае будет передан HTTP-код
      301 Moved Permanently (перемещено навсегда).

[S]   Skip — пропускает следующее правило, если текущее правило сработало.
      Можно указать количество последующих игнорируемых правил [S=2].

Полезные ссылки:

    Остальные флаги в документации Apache
    Как на самом деле работает mod_rewrite
    Описание основных флагов mod_rewrite
    Волшебный файл .htaccess
    Коллекция сниппетов .htaccess

Базис здорового человека

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

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

Здоровье — это состояние полного физического, духовного и социального благополучия, а не только отсутствие болезни и физических дефектов. — ВОЗ

Многие привыкли воспринимать здоровье, как готовность биологического существа выполнять механические операции, в котором все «болтики» на месте и смазаны нужным «маслом». Очень похоже на рабское мышление. Если копнуть глубже, то выясняется, что здоровье — это не только нормальное функционирование всех ваших органов, но и состояние, когда вы довольны сами собой: работа, семья, личные интересы, поставленные цели и т. д.

К сожалению, быть довольным собой не у всех получается. Причины, скорее всего, у каждого разные, но в их основании лежит один и тот же знаменатель: нет ясности ума, недостаточно силы воли, плохой сон и питание, раздражённость. Всё это влияет на вашу ФиИС [физическую и интеллектуальную силу], а также сдерживает ваш потенциал — топит резервные силы, не давая им пробудиться.

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

По моим наблюдениям, этому апатичному состоянию, предшествуют «блокаторы». Так я называю разновидности БУ [базового удовольствия]. Это, довольно-таки, индивидуальная переменная, к которой можно отнести: сладкое, музыка на фоне, тупое видео и всякая потребительская фигня. Здесь БУ имеет тотальный доступ к управлению ФиИС, а ФиИС не самостоятельная переменная и подчиняется только БУ. Чтобы повысить ФиИС, нам нужно научится управлять БУ:

Чем больше БУ, тем меньше ФиИС. Базовые удовольствия блокируют физические и интеллектуальные силы.

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

    1 заменил чашку чая стаканом воды;
    2 не сидел за монитором больше 45 минут;
    3 не ставил музыку на фон при работе за ПК;
    4 ввёл приседания и отжимания от пола;
    5 сладкое заменил глюкозой из фруктов;
    6 забыл про Ютуб и социальные сети;
    7 спал с 10 вечера до 6 утра;
    8 сменил городский транспорт на ходьбу.

ФиИС подразумевает личный свод правил, которые будут бороться против ваших источников базового удовольствия. Почему так? Просто я увидел на своём примере закономерность: когда меньше блаженства, тогда выше человеческая производительность. Вот и всё. Вот и весь секрет успешных людей — не вестись на потребительскую лабуду.

У меня не всегда получалось строго следовать своим пунктам: иногда я пил чай с сахаром как слон; сидел за компом часами на пролёт; забивал на спорт. В такие моменты эффективность спадала и хватка к поставленным задачам становилась меньше. Но в целом результат от поставленных мероприятий был более чем положительный: 1) повысилась внимательность и ясность ума; 2) скорость работы за ПК стала выше; 3) повысилась скорость обучаемости; 4) задачи из таск-менеджера улетали в миг. Всё благодаря низкому уровню БУ. Вот и всё.

Будьте здоровы!

Учимся работать с API Яндекс.Метрики

Для извлечения статистических данных из Яндекс.Метрики необходимо воспользоваться специальным разделом API очётов. Сейчас актуальна версия v1. В качестве примеров, для получения статистики посещений всего сайта и конкретной страницы, мы выгрузим табличные данные в формате JSON, а затем преобразуем их и построим два линейных графика. Ниже привожу базовую структуру GET-запроса, с которым мы будем работать:

https://api-metrika.yandex.ru/stat/v1/data ? ids=<int>
                                           & oauth_token=<string>
                                           & metrics=<string>
                                           & dimensions=<string>
                                           & filters=<string>
                                           & date1=<string>
                                           & date2=<string>
                                           & sort=<string>

Яндекс.Метрика оперирует двумя базовыми сущностями: метрики (metrics) и группировки (dimensions). Метрики определяют числовые величины, которые могут быть рассчитаны на основе сессии или хита пользователя [количество посетителей, процент отказов, глубина просмотра, …]. Группировки предназначены для выборки данных по определённым признакам [страница входа, источник трафика, дата анализа, …].

Яндекс.Метрика работает отдельно с визитами (ym:s), где s — session, и хитами (ym:pv), где pv — pageview. В запросах к API эти характеристики нельзя использовать вместе в метриках и группировках. Список всех метрик и группировок можно посмотреть в документации.

Для детальных запросов существуют фильтры сегментации (filters). Они рассчитывают результат по отдельному сегменту данных. Например, когда нужно получить какие-либо данные только из поисковых систем или вытянуть статистику посещений по конкретной странице. С помощью параметров date1 и date2 можно задать отчётный период, а sort необходим для сортировки данных по признаку из dimensions. Небольшая шпаргалка ниже:

Параметр    Описание
——————————————————————————————————————————————————
ids         Номер счётчика.
oauth_token Токен авторизации.
metrics     Список метрик через запятую.
dimensions  Список группировок через запятую.
filters     Фильтры сегментации с условием.
date1       Дата начала периода выборки.
date2       Дата окончания периода выборки.
sort        Сортировка по метрикам и группировкам.

Для начала нужно зарегистрировать своё приложение на oauth.yandex.ru и получить oauth_token. В качестве ids выступает номер вашего счётчика (его можно узнать на главной странице Яндекс.Метрики). Параметры ids, oauth_token и metrics являются обязательными в простых запросах, но если применяется filters, то metrics и dimensions можно не указывать.

Предлагаю перейти в плоскость PHP и сформировать первый боевой запрос на примере моего блога, который получит количество визитов, просмотров и уникальных посетителей на всём сайте за последнюю неделю:

<?php

$url = 'https://api-metrika.yandex.ru/stat/v1/data';

$params = [
    'ids'         => '14446750',
    'oauth_token' => 'Z4AAAAAYZjVkAAQP-FYZ6SJdSkhesN0MJ0dXOZo',
    'metrics'     => 'ym:s:visits,ym:s:pageviews,ym:s:users',
    'dimensions'  => 'ym:s:date',
    'date1'       => '7daysAgo',
    'date2'       => 'yesterday',
    'sort'        => 'ym:s:date',
];

echo file_get_contents( $url . '?' . http_build_query($params) );

Как видите, в metrics и dimensions мы указали значения для визитов (ym:s). Это значит, что данные будут сформированы в рамках сессии по каждому пользователю. Если посетитель перезагрузит одну и туже страницу сто раз, то ym:s:pageviews не будет меняться. В случае работы с хитами (ym:pv), значение ym:pv:pageviews увеличилось бы на сто. Хиты собирают статистику в рамках каждого просмотра страницы.

Дату для отчётного периода можно указать в формате YYYY-MM-DD или её относительное значение: today, yesterday, 7daysAgo (номер дня можно заменить на свой). В результате Яндекс.Метрика вернула следующие данные в формате JSON:

{
  "query" : {
    "ids" : [ 14446750 ],
    "dimensions" : [ "ym:s:date" ],
    "metrics" : [ "ym:s:visits", "ym:s:pageviews", "ym:s:users" ],
    "sort" : [ "ym:s:date" ],
    "date1" : "2017-02-14",
    "date2" : "2017-02-20",
    "limit" : 100,
    "offset" : 1,
    "group" : "Week",
    "auto_group_size" : "1",
    "quantile" : "50",
    "attribution" : "Last",
    "currency" : "RUB"
  },
  "data" : [ {
    "dimensions" : [ {
      "name" : "2017-02-14"
    } ],
    "metrics" : [ 437.0, 800.0, 376.0 ]
  }, {
    "dimensions" : [ {
      "name" : "2017-02-15"
    } ],
    "metrics" : [ 390.0, 559.0, 322.0 ]
  }, {
    "dimensions" : [ {
      "name" : "2017-02-16"
    } ],
    "metrics" : [ 243.0, 370.0, 196.0 ]
  }, {
    "dimensions" : [ {
      "name" : "2017-02-17"
    } ],
    "metrics" : [ 168.0, 274.0, 131.0 ]
  }, {
    "dimensions" : [ {
      "name" : "2017-02-18"
    } ],
    "metrics" : [ 111.0, 145.0, 75.0 ]
  }, {
    "dimensions" : [ {
      "name" : "2017-02-19"
    } ],
    "metrics" : [ 121.0, 150.0, 87.0 ]
  }, {
    "dimensions" : [ {
      "name" : "2017-02-20"
    } ],
    "metrics" : [ 132.0, 251.0, 103.0 ]
  } ],
  "total_rows" : 7,
  "total_rows_rounded" : false,
  "sampled" : false,
  "sample_share" : 1.0,
  "sample_size" : 1602,
  "sample_space" : 1602,
  "data_lag" : 74,
  "totals" : [ 1602.0, 2549.0, 988.0 ],
  "min" : [ 111.0, 145.0, 75.0 ],
  "max" : [ 437.0, 800.0, 376.0 ]
}

Секция query содержит параметры запроса, но нас больше интересует data, в которой содержатся наши статистические данные. Секция data представляет собой массив, где итеративно заполнены поля dimensions и metrics теми данными, которые были указаны в запросе. В нашем случае, поле dimensions содержит name — это название группировки ym:s:date. Поле metrics — массив с числовыми данными: ym:s:visits, ym:s:pageviews и ym:s:users.

Для обработки общих статистических данных можно использовать такие секции как: totals, min и max (в некоторых отчётах удобно анализировать сразу обобщённую информацию). Чтобы вывести данные из секции data на экран, скормим их Highcharts и построим линейный график:

Посмотреть процесс создания графика: PHP + Highcharts

Мы получили статистику по визитам, просмотрам и уникальным посетителям на всех страницах моего блога за последнюю неделю. Выглядит довольно таки неплохо. Для получения статистики конкретной страницы в Яндекс.Метрике нужно использовать filter. Вот так будет выглядеть запрос и построение графика на amCharts для просмотра главной страницы моего блога по хитам (ym:pv):

<?php

/////////////////////////////////////////////////////////
///// ПАРАМЕТРЫ GET-ЗАПРОСА ДЛЯ КОНКРЕТНОЙ СТРАНИЦЫ /////
/////////////////////////////////////////////////////////
$url = 'https://api-metrika.yandex.ru/stat/v1/data';

$params = [
    'ids'         => '14446750',
    'oauth_token' => 'Z4AAAAAYZjVkAAQP-FYZ6SJdSkhesN0MJ0dXOZo',
    'metrics'     => 'ym:pv:pageviews',
    'dimensions'  => 'ym:pv:date',
    'filters'     => rawurldecode("ym:pv:URL=='https://denisyuk.by/'"),
    'date1'       => '30daysAgo',
    'date2'       => 'yesterday',
    'sort'        => 'ym:pv:date',
];

/////////////////////////////////////////////////////////
///// ПОЛУЧИМ ДАННЫЕ В JSON И ПЕРЕВЕДЁМ ИХ В МАССИВ /////
/////////////////////////////////////////////////////////
$json = file_get_contents( $url . '?' . http_build_query($params) );
$data = json_decode($json, true)['data'];

/////////////////////////////////////////////////////////////
///// ПРЕОБРАЗУЕМ ДАННЫЕ ДЛЯ ЛИНЕЙНОГО ГРАФИКА AMCHARTS /////
/////////////////////////////////////////////////////////////
$tmpdata = [];

foreach ($data as $item) {
    $tmpdata[] = [
        'category' => $item['dimensions'][0]['name'],
        'column-1' => $item['metrics'][0],
    ];
}

////////////////////////////////////
///// ВЕРНЁМ JSON ДЛЯ AMCHARTS /////
////////////////////////////////////
$dataProvider = json_encode($tmpdata);

///////////////////////////////////////////////////////
///// ВЫВЕДЕМ HTML-КОД И ПОСТРОИМ ГРАФИК AMCHARTS /////
///////////////////////////////////////////////////////
echo <<<HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
  <script src="https://www.amcharts.com/lib/3/serial.js"></script>
  <script src="https://www.amcharts.com/lib/3/themes/patterns.js"></script>
  <script>
    AmCharts.makeChart("amcharts-container", {
      "type": "serial",
      "categoryField": "category",
      "startDuration": 1,
      "theme": "patterns",
      "categoryAxis": {
        "gridPosition": "start"
      },
      "graphs": [{
        "balloonText": "[[title]] за [[category]] — [[value]]",
        "bullet": "round",
        "title": "Просмотры",
        "id": "AmGraph-1",
        "type": "smoothedLine",
        "valueField": "column-1"
      }],
      "valueAxes": [{
        "title": "Количество"
      }],
      "titles": [{
        "text": "Просмотры https://denisyuk.by за последние 30 дней"
      }],
      "dataProvider": $dataProvider
    });
  </script>
</head>
<body>
  <div id="amcharts-container" style="max-width: 720px; height: 400px;"></div>
</body>
</html>
HTML;
//end

Обратите внимание, что значение filters мы обернули в функцию rawurldecode(). Это нужно делать, когда вы работаете со сложными фильтрами сегментации и кириллицей в запросах. Другие возможности фильтра доступны в документации: можно делать множественную выборку, использовать регулярные выражения, задействовать дополнительные операторы и др. В итоге мы получили график amCharts для статистики просмотров главной страницы по хитам:

Обновлено 23 Фев 2017: Решил добавить круговую диаграмму на Highcharts, чтобы разнообразить пост (под графиком сниппет кода для построения диаграммы). С помощью группировки ym:s:<attribution>TrafficSource и метрики ym:s:visits мы получили статистику по всем источникам трафика, а через фильтр сегментации, указав значение ym:s:visits>10, скрыли источники трафика меньше десяти, чтобы не портить график.

Посмотреть процесс создания круговой диаграммы: PHP + Highcharts

Мы рассмотрели базовые возможности API Яндекс.Метрики, которые могут пригодится для построения отчётов посещаемости своего сайта. Здесь важно понять, что все запросы формируются на основе metrics и dimensions, а через filters вычленяются конкретные данные по сайту. Если у вас остались вопросы, то задавайте их в комментариях, а я, по мере необходимости, буду редактировать или дополнять пост.

Продолжить обучение:

    Документация API очётов Яндекс.Метрики
    Становясь гуру API Яндекс.Метрики
    Получаем статистические данные, используя API Yandex Metrika
    Яндекс.Метрика для Laravel 5

Закладки разработчика сайтов — выпуск #4

Выкладываю очередную подборку ссылок по фронтедну, которые накопились в моём браузере за последние пару недель. Очень много полезной информации для верстальщиков или тех, кто хочет ими стать. Кстати говоря, свои крутые материалы по веб-разработке можете присылать мне в Твиттер или на почту, а я добавлю их в дайджест. Это принесёт вам неплохой трафик на сайт. Если ниже ничего не отображается, тогда воспользуйтесь запасной ссылкой.

Подписывайтесь на мой Твиттер, если хотите получать интересные и полезные ссылки по программированию и вёрстке сайтов до того, как они попадут в дайджест на блоге.

Ctrl + ↓ Ранее