Недомыслие. Всеобъемлющая история шаблонов Несчастный user info php

  • 20.06.2020

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

Поиск по шаблону позволяет не только находить определенные фрагменты текста, но и заменять их другими фрагментами. Одним из стандартных примеров поиска по шаблону являются команды поиска/замены в текстовых редакторах -- например, в MS Word, Emacs и в моем любимом редакторе vi. Всем пользователям UNIX хорошо известны такие программы, как sed, awk и grep; богатство возможностей этих программ в значительной степени обусловлено средствами поиска по шаблону. Механизмы поиска по шаблону решают четыре основные задачи:

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

Появление Web породило необходимость в более быстрых и эффективных средствах поиска данных, которые бы позволяли пользователям со всего мира находить нужную информацию среди миллиардов web-страниц. Поисковые системы, онлайновые финансовые службы и сайты электронной коммерции -- все это стало бы абсолютно бесполезным без средств анализа гигантских объемов данных в этих секторах. Действительно, средства обработки строковой информации являются жизненно важной составляющей практически любого сектора, так или иначе связанного с современными информационными технологиями. В этой главе основное внимание посвящено средствам обработки строк в PHP. Мы рассмотрим некоторые стандартные строковые функции (в языке их больше 60!), а из приведенных определений и примеров вы получите сведения, необходимые для создания web-приложений. Но прежде чем переходить к специфике PHP, я хочу познакомить вас с базовым механизмом, благодаря которому становится возможным поиск по шаблону. Речь идет о регулярных выражениях.

Регулярные выражения

Регулярные выражения лежат в основе всех современных технологий поиска по шаблону. Регулярное выражение представляет собой последовательность простых и служебных символов, описывающих искомый текст. Иногда регулярные выражения бывают простыми и понятными (например, слово dog), но часто в них присутствуют служебные символы, обладающие особым смыслом в синтаксисе регулярных выражений, -- например, <(?)>.*<\/.?>.

В PHP существуют два семейства функций, каждое из которых относится к определенному типу регулярных выражений: в стиле POSIX или в стиле Perl. Каждый тип регулярных выражений обладает собственным синтаксисом и рассматривается в соответствующей части главы. На эту тему были написаны многочисленные учебники, которые можно найти как в Web, так и в книжных магазинах. Поэтому я приведу лишь основные сведения о каждом типе, а дальнейшую информацию при желании вы сможете найти самостоятельно. Если вы еще не знакомы с принципами работы регулярных выражений, обязательно прочитайте краткий вводный курс, занимающий всю оставшуюся часть этого раздела. А если вы хорошо разбираетесь в этой области, смело переходите к следующему разделу.

Синтаксис регулярных выражений (POSIX)

Структура регулярных выражений POSIX чем-то напоминает структуру типичных математических выражений -- различные элементы (операторы) объединяются друг с другом и образуют более сложные выражения. Однако именно смысл объединения элементов делает регулярные выражения таким мощным и выразительным средством. Возможности не ограничиваются поиском литерального текста (например, конкретного слова или числа); вы можете провести поиск строк с разной семантикой, но похожим синтаксисом -- например, всех тегов HTML в файле.

Простейшее регулярное выражение совпадает с одним литеральным символом -- например, выражение g совпадает в таких строках, как g , haggle и bag. Выражение, полученное при объединении нескольких литеральных символов, совпадает по тем же правилам -- например, последовательность gan совпадает в любой строке, содержащей эти символы (например, gang, organize или Reagan).

Оператор | (вертикальная черта) проверяет совпадение одной из нескольких альтернатив. Например, регулярное выражение php | zend проверяет строку на наличие php или zend.

Квадратные скобки

Квадратные скобки () имеют особый смысл в контексте регулярных выражений -- они означают «любой символ из перечисленных в скобках». В отличие от регулярного выражения php, которое совпадает во всех строках, содержащих литеральный текст php, выражение совпадает в любой строке, содержащей символы р или h. Квадратные скобки играют важную роль при работе с регулярными выражениями, поскольку в процессе поиска часто возникает задача поиска символов из заданного интервала. Ниже перечислены некоторые часто используемые интервалы:

  • -- совпадает с любой десятичной цифрой от 0 до 9;
  • -- совпадает с любым символом нижнего регистра от а до z;
  • -- совпадает с любым символом верхнего регистра от А до Z;
  • -- совпадает с любым символом нижнего или верхнего регистра от а до Z.

Конечно, перечисленные выше интервалы всего лишь демонстрируют общий принцип. Например, вы можете воспользоваться интервалом для обозначения любой десятичной цифры от 0 до 3 или интервалом для обозначения любого символа нижнего регистра от b до v. Короче говоря, интервалы определяются совершенно произвольно.

Квантификаторы

Существует особый класс служебных символов, обозначающих количество повторений отдельного символа или конструкции, заключенной в квадратные скобки. Эти служебные символы (+, * и {...}) называются квантификаторами. Принцип их действия проще всего пояснить на примерах:

  • р+ означает один или несколько символов р, стоящих подряд;
  • р* означает ноль и более символов р, стоящих подряд;
  • р? означает ноль или один символ р;
  • р{2} означает два символа р, стоящих подряд;
  • р{2,3} означает от двух до трех символов р, стоящих подряд;
  • р{2,} означает два и более символов р, стоящих подряд.

Прочие служебные символы

Служебные символы $ и ^ совпадают не с символами, а с определенными позициями в строке. Например, выражение р$ означает строку, которая завершается символом р, а выражение ^р -- строку, начинающуюся с символа р.

  • Конструкция [^a-zA-Z] совпадает с любым символом, не входящим в указаные интервалы (a-z и A-Z).
  • Служебный символ. (точка) означает «любой символ». Например, выражение р.р совпадает с символом р, за которым следует произвольный символ, после чего опять следует символ р.

Объединение служебных символов приводит к появлению более сложных выражений. Рассмотрим несколько примеров:

  • ^.{2}$ -- любая строка, содержащая ровно два символа;
  • (.*) -- произвольная последовательность символов, заключенная между <Ь> и (вероятно, тегами HTML для вывода жирного текста);
  • p(hp)* -- символ р, за которым следует ноль и более экземпляров последовательности hp (например, phphphp).

Иногда требуется найти служебные символы в строках вместо того, чтобы использовать их в описанном специальном контексте. Для этого служебные символы экранируются обратной косой чертой (\). Например, для поиска денежной суммы в долларах можно воспользоваться выражением \$+, то есть «знак доллара, за которым следует одна или несколько десятичных цифр». Обратите внимание на обратную косую черту перед $. Возможными совпадениями для этого регулярного выражения являются $42, $560 и $3.

Стандартные интервальные выражения (символьные классы)

Для удобства программирования в стандарте POSIX были определены некоторые стандартные интервальные выражения, также называемые символьными классами (character classes). Символьный класс определяет один символ из заданного интервала -- например, букву алфавита или цифру:

  • [[:alpha:]] -- алфавитный символ (aA-zZ);
  • [[:digit:]]-цифра (0-9);
  • [[:alnum:]] -- алфавитный символ (aA-zZ) или цифра (0-9);
  • [[:space:]] -- пропуски (символы новой строки, табуляции и т. д.).

Функции PHP для работы с регулярными выражениями (POSIX-совместимые)

В настоящее время PHP поддерживает семь функций поиска с использованием регулярных выражений в стиле POSIX:

  • еrеg();
  • еrеg_rерlасе();
  • eregi();
  • eregi_replace();
  • split();
  • spliti();
  • sql_regcase().

Описания этих функций приведены в следующих разделах.

Функция еrеg() ищет в заданной строке совпадение для шаблона. Если совпадение найдено, возвращается TRUE, в противном случае возвращается FALSE. Синтаксис функции ereg():

int ereg (string шаблон, string строка [, array совпадения])

Поиск производится с учетом регистра алфавитных символов. Пример использования ereg() для поиска в строках доменов.соm:

$is_com - ereg("(\.)(com$)", $email):

// Функция возвращает TRUE, если $email завершается символами ".com"

// В частности, поиск будет успешным для строк

// "www.wjgilmore.com" и "[email protected]"

Обратите внимание: из-за присутствия служебного символа $ регулярное выражение совпадает только в том случае, если строка завершается символами.com. Например, оно совпадет в строке "www.apress.com", но не совпадет в строке "www.apress.com/catalog".

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

Листинг 8.1. Вывод элементов массива $regs

$url = "http://www.apress.com";

// Разделить $url на три компонента: "http://www". "apress" и "com"

$www_url = ereg("^(http://www)\.([[:alnum:]+\.([[:alnum:]]+)". $url, $regs);

if ($www_url) : // Если переменная $www_url содержит URL

echo $regs; // Вся строка "http://www.apress.com"

print "
";

echo $regs[l]; // "http://www"

print "
";

echo $regs; // "apress"

print "
";

echo $regs; // "com" endif;

При выполнении сценария в листинге 8.1 будет получен следующий результат:

http://www.apress.com http://www apress com

Функция ereg_replace() ищет в заданной строке совпадение для шаблона и заменяет его новым фрагментом. Синтаксис функции ereg_replace():

string ereg_replace (string шаблон, string замена, string строке)

Функция ereg_replace() работает по тому же принципу, что и ereg(), но ее возможности расширены от простого поиска до поиска с заменой. После выполнения замены функция возвращает модифицированную строку. Если совпадения

отсутствуют, строка остается в прежнем состоянии. Функция ereg_replace(), как и еrеg(), учитывает регистр символов. Ниже приведен простой пример, демонстрирующий применение этой функции:

$copy_date = "Copyright 1999":

$copy_date = ereg_replace("(+)". "2000", $copy_date);

print $copy_date: // Выводится строка "Copyright 2000"

У средств поиска с заменой в языке PHP имеется одна интересная возможность -- возможность использования обратных ссылок на части основного выражения, заключенные в круглые скобки. Обратные ссылки похожи на элементы необязательного параметра-массива совпадения функции еrеg() за одним исключением: обратные ссылки записываются в виде \0, \1, \2 и т. д., где \0 соответствует всей строке, \1 -- успешному совпадению первого подвыражения и т. д. Выражение может содержать до 9 обратных ссылок. В следующем примере все ссылки на URL в тексте заменяются работающими гиперссылками:

$url = "Apress (http://www.apress.com");

$url = ereg_replace("http://(()*)", "\\0", $url);

// Выводится строка:

// Apress (http://www.apress.com)

Функция eregi() ищет в заданной строке совпадение для шаблона. Синтаксис функции eregi():

int eregi (string шаблон, string строка [, array совпадения])

Поиск производится без учета регистра алфавитных символов. Функция eregi() особенно удобна при проверке правильности введенных строк (например, паролей). Использование функции eregi() продемонстрировано в следующем примере:

$password = "abc";

if (! eregi("[[:alnum:]]{8.10}, $password) :

print "Invalid password! Passwords must be from 8 through 10 characters in length.";

// В результате выполнения этого фрагмента выводится сообщение об ошибке.

// поскольку длина строки "abc" не входит в разрешенный интервал

// от 8 до 10 символов.

Функция eregi_replасе() работает точно так же, как ereg_replace(), за одним исключением: поиск производится без учета регистра символов. Синтаксис функции ereg_replace():

string eregi_replace (string шаблон, string замена, string строка)

Функция split() разбивает строку на элементы, границы которых определяются по заданному шаблону. Синтаксис функции split():

array split (string шаблон, string строка [, int порог])

Необязательный параметр порог определяет максимальное количество элементов, на которые делится строка слева направо. Если шаблон содержит алфавитные символы, функция spl it() работает с учетом регистра символов. Следующий пример демонстрирует использование функции split() для разбиения канонического IP-адреса на триплеты:

$ip = "123.345.789.000"; // Канонический IP-адрес

$iparr = split ("\.", $ip) // Поскольку точка является служебным символом.

// ее необходимо экранировать.

print "$iparr
"; // Выводит "123"

print "$iparr
"; // Выводит "456"

print "$iparr
"; // Выводит "789"

print "$iparr
"; // Выводит "000"

Функция spliti() работает точно так же, как ее прототип split(), за одним исключением: она не учитывает регистра символов. Синтаксис функции spliti():

array spliti (string шаблон, string строка [, int порог])

Разумеется, регистр символов важен лишь в том случае, если шаблон содержит алфавитные символы. Для других символов выполнение spliti() полностью аналогично split().

Вспомогательная функция sql_regcase() заключает каждый символ входной строки в квадратные скобки и добавляет к нему парный символ. Синтаксис функции sql_regcase():

string sql_regcase (string строка)

Если алфавитный символ существует в двух вариантах (верхний и нижний регистры), выражение в квадратных скобках будет содержать оба варианта; в противном случае исходный символ повторяется дважды. Функция sql_regcase() особенно удобна при использовании PHP с программными пакетами, поддерживающими регулярные выражения в одном регистре. Пример преобразования строки функцией sql_regcase():

$version = "php 4.0";

print sql_regcase($version);

// Выводится строка [..]

Синтаксис регулярных выражений в стиле Perl

Преобразование строки к верхнему и нижнему регистру

В PHP существует четыре функции, предназначенных для изменения регистра строки:

  • strtolower();
  • strtoupper();
  • ucfirst();
  • ucwords().

Все эти функции подробно описаны ниже.

strtolower()

Функция strtolower() преобразует все алфавитные символы строки к нижнему регистру. Синтаксис функции strtolower():

string strtolower(string строка)

Неалфавитные символы функцией не изменяются. Преобразование строки к нижнему регистру функцией strtolower() продемонстрировано в следующем примере:

$sentence = strtolower($sentence);

// "cooking and programming php are my two favorite pastimes!"

Строки можно преобразовывать не только к нижнему, но и к верхнему регистру. Преобразование выполняется функцией strtoupper(), имеющей следующий синтаксис:

string strtoupper (string строка)

Неалфавитные символы функцией не изменяются. Преобразование строки к верхнему регистру функцией strtoupper() продемонстрировано в следующем примере:

$sentence = "cooking and programming PHP are my two favorite pastimes!";

$sentence = strtoupper($sentence);

// После вызова функции $sentence содержит строку

// "COOKING AND PROGRAMMING PHP ARE MY TWO FAVORITE PASTIMES!"

Функция ucfirst() преобразует к верхнему регистру первый символ строки -- при условии, что он является алфавитным символом. Синтаксис функции ucfirst():

string ucfirst (string строка)

Неалфавитные символы функцией не изменяются. Преобразование первого символа строки функцией ucfirst() продемонстрировано в следующем примере:

&sentence = "cooking and programming PHP are my two favorite pastimes!";

$sentence = ucfirst($sentence);

// После вызова функции $sentence содержит строку

// "Cooking and programming PHP are mу two favorite pastimes!"

Функция ucwords() преобразует к верхнему регистру первую букву каждого слова в строке. Синтаксис функции ucwords():

string ucwords (string строка")

Неалфавитные символы функцией не изменяются. «Слово» определяется как последовательность символов, отделенная от других элементов строки пробелами. В следующем примере продемонстрировано преобразование первых символов слов функцией ucwords():

$sentence = "cooking and programming PHP are my two favorite pastimes!";

$sentence = ucwords($sentence);

// После вызова функции $sentence содержит строку

// "Cooking And Programming PHP Are My Two Favorite Pastimes!"

Проект: идентификация браузера

Каждый программист, пытающийся создать удобный web-сайт, должен учитывать различия в форматировании страниц при просмотре сайта в разных браузерах и операционных системах. Хотя консорциум W3 (http://www.w3.org) продолжает публиковать стандарты, которых должны придерживаться программисты при создании web-приложений, разработчики браузеров любят дополнять эти стандарты своими маленькими «усовершенствованиями», что в конечном счете вызывает хаос и путаницу. Разработчики часто решают эту проблему, создавая разные страницы для каждого типа браузера и операционной системы -- при этом объем работы значительно увеличивается, но зато итоговый сайт идеально подходит для любого пользователя. Результат -- хорошая репутация сайта и уверенность в том, что пользователь посетит его снова.

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

Приведенный ниже проект (sniffer.php) показывает, как использовать функции PHP для работы с регулярными выражениям с целью получения информации по запросам. Программа определяет тип и версию браузера и операционной системы, после чего выводит полученную информацию в окне браузера. Но прежде чем переходить к непосредственному анализу программы, я хочу представить один из главных ее компонентов -- стандартную переменную PHP $HTTP_USER_AGENT. В этой переменной в строковом формате хранятся различные сведения о браузере и операционной системе пользователя -- именно то, что нас интересует. Эту информацию можно легко вывести на экран всего одной командой:

echo $HTTP USER_AGENT;

При работе в Internet Explorer 5.0 на компьютере с Windows 98 результат будет выглядеть так:

Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)

Для Netscape Navigator 4.75 выводятся следующие данные:

Mozilla/4.75 (Win98; U)

Sniffer.php извлекает необходимые данные из $HTTP_USER_AGENT при помощи функций обработки строк и регулярных выражений. Алгоритм программы на псевдокоде:

  • Определить две функции для идентификации браузера и операционной системы: browser_info() и opsys_info(). Начнем с псевдокода функции browser_info().
  • Определить тип браузера, используя функцию егед(). Хотя эта функция работает медленнее упрощенных строковых функций типа strstr(), в данном случае она удобнее, поскольку регулярное выражение позволяет определить версию браузера.
  • Воспользоваться конструкцией if/elseif для идентификации следующих браузеров и их версий: Internet Explorer, Opera, Netscape и браузер неизвестного типа.
  • Вернуть информацию о типе и версии браузера в виде массива.
  • Функция opsys_info() определяет тип операционной системы. На этот раз используется функция strstr(), поскольку тип ОС определяется и без применения регулярных выражений.
  • Воспользоваться конструкцией if/elseif для идентификации следующих систем: Windows, Linux, UNIX, Macintosh и неизвестная операционная система.
  • Вернуть информацию об операционной системе.

Листинг 8.3. Идентификация типа браузера и операционной системы клиента

Файл: sniffer.php

Назначение: Идентификация типа/версии браузера и платформы

// Функция: browser_info

// Назначение: Возвращает тип и версию браузера

function browser_info ($agent) {

// Определить тип браузера

// Искать сигнатуру Internet Explorer

if (ereg("MSIE (.{1,2})", $agent, $version))

$browse_type = "IE";

$browse version = $version;

// Искать сигнатуру Opera

elseif (ereg("Opera (.{1,2})". $agent, $version)):

$browse_type = "Opera":

$browse_version = $version:

// Искать сигнатуру Netscape. Проверка браузера Netscape

// *должна* выполняться после проверки Internet Explorer и Opera,

// поскольку все эти браузеры любят сообщать имя

// Mozilla вместе с настоящим именем.

elseif (ereg("Mozilla/(.{1,2})". $agent, $version)) :

$browse_type = "Netscape";

$browse_version = $version;

// Если это не Internet Explorer, Opera или Netscape.

// значит, мы обнаружили неизвестный браузер,

$browse_type = "Unknown";

$browse_version = "Unknown";

// Вернуть тип и версию браузера в виде массива

return array ($browse_type, $browse_version);

} // Конец функции browser_info

// Функция: opsys_info

// Назначение: Возвращает информацию об операционной системе пользователя

function opsys_info($agent) {

// Идентифицировать операционную систему

// Искать сигнатуру Windows

if (strstr ($agent. "win")) :

$opsys = "windows";

// Искать сигнатуру Linux

elseif (strstr($agent, "Linux")) :

$opsys = "Linux";

// Искать сигнатуру UNIX

elseif (strstr (Sagent, "Unix")) :

$opsys = "Unix";

// Искать сигнатуру Macintosh

elseif (strstr ($agent, "Mac")) :

$opsys = "Macintosh";

// Неизвестная платформа else:

$opsys = "Unknown";

// Вернуть информацию об операционной системе

list ($browse_type. $browse_version) = browser_info ($HTTP_USER_AGENT); Soperating_sys = opsysjnfo ($HTTP_USER_AGENT);

print "Browser Type: $browse_type
";

print "Browser Version: $browse_version
";

print "Operating System: $operating_sys
":

Вот и все! Например, если пользователь работает в браузере Netscape 4.75 на компьютере с системой Windows, будет выведен следующий результат:

Browser Type: Netscape

Browser Version: 4.75

Operating System: Windows

В следующей главе вы научитесь осуществлять переходы между страницами и даже создавать списки стилей (style sheets) для конкретных операционной системы и браузера.

Итоги

В этой главе был изложен довольно обширный материал. Какой прок от языка программирования, если в нем нельзя работать с текстом? Мы рассмотрели следующие темы:

  • общие сведения о регулярных выражениях в стилях POSIX и Perl;
  • стандартные функции PHP для работы с регулярными выражениями;
  • изменение длины строки;
  • определение длины строки;
  • альтернативные функции PHP для обработки строковой информации;
  • преобразование простого текста в HTML и наоборот;
  • изменение регистра символов в строках.

Следующая глава открывает вторую часть книги -- кстати, мою любимую. В ней мы начнем знакомиться со средствами PHP, ориентированными на Web, рассмотрим процесс динамического создания содержимого, включение файлов и построение общих шаблонов. В дальнейших главах части 2 рассматриваются работа с формами HTML, базы данных, отслеживание данных сеанса и нетривиальные средства работы с шаблонами. Держитесь -- начинается самое интересное!

февраль 5 , 2017

Я не знаю ни одного php-фреймворка. Это печально и стыдно, но законом пока не запрещено. А при этом поиграться с REST API хочется. Проблема в том, что php по умолчанию поддерживает только $_GET и $_POST. А для RESTful-сервиса надобно уметь работать еще и с PUT, DELETE и PATCH. И не очень очевидно, как культурно обработать множество запросов вида GET http://site.ru/users, DELETE http://site.ru/goods/5 и прочего непотребства. Как завернуть все подобные запросы в единую точку, универсально разобрать их на части и запустить нужный код для обработки данных?

Почти любой php-фреймворк умеет делать это из коробки. Например, Laravel, где роутинг реализован понятно и просто. Но что если нам не нужно прямо сейчас заниматься изучением новой большой темы, а хочется просто быстро завести проект с поддержкой REST API? Об этом и пойдет речь в статье.

Что должен уметь наш RESTful-сервис?

1. Поддерживать все 5 основных типов запросов: GET, POST, PUT, PATCH, DELETE.
2. Разруливать разнообразные маршруты вида
POST /goods
PUT /goods/{goodId}
GET /users/{userId}/info
и прочие сколь угодно длинные цепочки.

Внимание: это статья не про основы REST API
Я предполагаю, что Вы уже знакомы с REST-подходом и понимаете, как это работает. Если нет, то в интернетах много замечательных статей по основам REST - я не хочу дублировать их, моя идея - показать, как с REST работать на практике.

Какой функционал мы будем поддерживать?

Рассмотрим 2 сущности - товары и пользователи.

Для товаров возможности следующие:

  • 1. GET /goods/{goodId} — Получение информации о товаре
  • 2. POST /goods — Добавление нового товара
  • 3. PUT /goods/{goodId} — Редактирование товара
  • 4. PATCH /goods/{goodId} — Редактирование некоторых параметров товара
  • 5. DELETE /goods/{goodId} — Удаление товара

По пользователям для разнообразия рассмотрим несколько вариантов с GET

  • 1. GET /users/{userId} — Полная информация о пользователе
  • 2. GET /users/{userId}/info — Только общая информация о пользователе
  • 3. GET /users/{userId}/orders — Список заказов пользователя

Как это заработает на нативном PHP?

Первое, что мы сделаем - это настроим.htaccess так, чтобы все запросы перенаправлялись на файл index.php. Именно он и будет заниматься извлечением данных.

Второе - определимся, какие данные нам нужны и напишем код для их получения - в index.php.
Нас интересуют 3 типа данных:

  • 1. Метод запроса (GET, POST, PUT, PATCH или DELETE)
  • 2. Данные из URL-a, например, users/{userId}/info - нужны все 3 параметра
  • 3. Данные из тела запроса
И третье, напишем код, который запускает нужные функции. Функции разбиты по файлам, все по феншую, добавить новые пути и методы для RESTful-сервиса будет очень просто.

.htaccess

Создадим в корне проекта файл.htaccess

RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.+)$ index.php?q=$1

Этими загадочными строками мы повелеваем делать так:
1 - направить все запросы любого вида на царь-файл index.php
2 - сделать строку в URL-е доступной в index.php в get-параметре q. То есть данные из URL-а вида /users/{userId}/info мы достанем из $_GET["q"].

index.php

Рассмотрим index.php строка за строкой. Для начала получим метод запроса.

// Определяем метод запроса $method = $_SERVER["REQUEST_METHOD"];

Затем данные из тела запроса

// Получаем данные из тела запроса $formData = getFormData($method);

Для GET и POST легко вытащить данные из соответствующих массивов $_GET и $_POST. А вот для остальных методов нужно чуть извратиться. Код для них вытаскивается из потока php://input , код легко гуглится, я всего лишь написал общую обертку - функцию getFormData($method)

// Получение данных из тела запроса function getFormData($method) { // GET или POST: данные возвращаем как есть if ($method === "GET") return $_GET; if ($method === "POST") return $_POST; // PUT, PATCH или DELETE $data = array(); $exploded = explode("&", file_get_contents("php://input")); foreach($exploded as $pair) { $item = explode("=", $pair); if (count($item) == 2) { $data = urldecode($item); } } return $data; }

То есть мы получили нужные данные, скрыв все детали в getFormData - ну и отлично. Переходим к самому интересному - роутингу.

// Разбираем url $url = (isset($_GET["q"])) ? $_GET["q"] : ""; $url = rtrim($url, "/"); $urls = explode("/", $url);

Выше мы узнали, что.htaccess подложит нам параметры из URL-a в q-параметр массива $_GET. То есть в $_GET["q"] попадет примерно такая строка: users/10 . Независимо от того, каким методом мы запрос дергаем.

А explode("/", $url) преобразует нам эту строку в массив, с которым уже можно работать. Таким образом, составляйте сколько угодно длинные цепочки запросов, например,
GET /goods/page/2/limit/10/sort/price_asc
И будьте уверены, получите массив

$urls = array("goods", "page", "2", "limit", "10", "sort", "price_asc");

Теперь у нас есть все данные, нужно сделать с ними что-нибудь полезное. А сделают это всего лишь 4 строки кода

// Определяем роутер и url data $router = $urls; $urlData = array_slice($urls, 1); // Подключаем файл-роутер и запускаем главную функцию include_once "routers/" . $router . ".php"; route($method, $urlData, $formData);

Улавливаете? Мы заводим папку routers, в которую складываем файлы, манипулирующие одной сущностью: товарами или пользователями. При этом договариваемся, что название файлов совпадают с первым параметром в urlData - он и будет роутером, $router. А из urlData этот роутер нужно убрать, он нам больше не нужен и используется только для подключения нужного файла. array_slice($urls, 1) и вытащит нам все элементы массива, кроме первого.

Теперь осталось подключить нужный файл-роутер и запустить функцию route с тремя параметрами. Что же это за function route? Условимся, что в каждом файле-роутере будет определена такая функция, которая по входным параметрам определит, какое действие инициировал пользователь, и выполнит нужный код. Сейчас это станет понятнее. Рассмотрим первый запрос - получение данных о товаре.

GET /goods/{goodId}

Файл routers/goods.php

// Роутер function route($method, $urlData, $formData) { // Получение информации о товаре // GET /goods/{goodId} if ($method === "GET" && count($urlData) === 1) { // Получаем id товара $goodId = $urlData; // Вытаскиваем товар из базы... // Выводим ответ клиенту echo json_encode(array("method" => "GET", "id" => $goodId, "good" => "phone", "price" => 10000)); return; } // Возвращаем ошибку header("HTTP/1.0 400 Bad Request"); echo json_encode(array("error" => "Bad Request")); }

Содержимое файла - это одна большая функция route, которая в зависимости от переданных параметров выполняет нужные действия. Если метод GET и в urlData передан 1 параметр (goodId), то это запрос о получении данных о товаре.

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

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

Давайте попробуем на примере: откройте консоль браузера и выполните код

$.ajax({url: "/examples/rest/goods/10", method: "GET", dataType: "json", success: function(response){console.log("response:", response)}})

Код отправит запрос на сервер, где я развернул подобное приложение и выведет ответ. Убедитесь, что интересующий наш маршрут /goods/10 действительно отработал. На вкладке Network Вы заметите такой же запрос.
И да, /examples/rest - это корневой путь нашего тестового приложения на сайт

Если Вам привычнее пользоваться curl-ом в консоли, то запустите в терминале это - ответ будет тот же самый, да еще и с заголовками от сервера.

Curl -X GET https://сайт/examples/rest/goods/10 -i

В конце функции мы написали такой код.

// Возвращаем ошибку header("HTTP/1.0 400 Bad Request"); echo json_encode(array("error" => "Bad Request"));

Он значит, что если мы ошиблись с параметрами или запрашиваемый маршрут не определен, то вернем клиенту 400-ю ошибку Bad Request. Добавьте, например, к URL-у что-то вроде goods/10/another_param и увидите ошибку в консоли и ответ 400 - кривой запрос не прошел.

По http-кодам ответов сервера
Мы не будем заморачиваться с выводом разных кодов, хотя по REST-у это и стоит делать. Клиентских ошибок много. Даже в нашем простом случае уместна 405 в случае неправильно переданного метода. Намеренно не хочу усложнять.
В случае успеха сервер у нас всегда вернет 200 ОК. По хорошему, при создании ресурса стоит отдавать 201 Created. Но опять-таки в плане упрощения эти тонкости мы отбросим, а в реальном проекте Вы их легко реализуете сами.

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

POST /goods

Добавление нового товара

// Добавление нового товара // POST /goods if ($method === "POST" && empty($urlData)) { // Добавляем товар в базу... // Выводим ответ клиенту echo json_encode(array("method" => "POST", "id" => rand(1, 100), "formData" => $formData)); return; }

urlData сейчас пустой, но зато используется formData - мы ее просто выведем клиенту.

Как сделать "правильно"?
Согласно канонам REST в post-запросе следует отдавать обратно только id созданной сущности или url, по которому эту сущность можно получить. То есть в ответе будет или просто число - {goodId} , или /goods/{goodId} .
Почему я написал "правильно" в кавычках? Да потому, что REST - это набор не жестких правил, а рекомендаций. И как будете реализовывать именно Вы, зависит от Ваших предпочтений или уже принятых соглашений на конкретном проекте.
Просто имейте в виду, что другой программист, читающий код и осведомленный о REST-подходе, будет ожидать в ответе на post-запрос id созданного объекта или url, по которому можно get-запросом вытащить данные об этом объекте.

Тестим из консоли

$.ajax({url: "/examples/rest/goods/", method: "POST", data: {good: "notebook", price: 20000}, dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X POST https://сайт/examples/rest/goods/ --data "good=notebook&price=20000" -i

PUT /goods/{goodId}

Редактирование товара

// Обновление всех данных товара // PUT /goods/{goodId} if ($method === "PUT" && count($urlData) === 1) { // Получаем id товара $goodId = $urlData; // Обновляем все поля товара в базе... // Выводим ответ клиенту echo json_encode(array("method" => "PUT", "id" => $goodId, "formData" => $formData)); return; }

Здесь уже все данные используются по-полной. Из urlData вытаскивается id товара, а из formData - свойства.

Тестим из консоли

$.ajax({url: "/examples/rest/goods/15", method: "PUT", data: {good: "notebook", price: 20000}, dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X PUT https://сайт/examples/rest/goods/15 --data "good=notebook&price=20000" -i

PATCH /goods/{goodId}

Частичное обновление товара

// Частичное обновление данных товара // PATCH /goods/{goodId} if ($method === "PATCH" && count($urlData) === 1) { // Получаем id товара $goodId = $urlData; // Обновляем только указанные поля товара в базе... // Выводим ответ клиенту echo json_encode(array("method" => "PATCH", "id" => $goodId, "formData" => $formData)); return; }

Тестим из консоли

$.ajax({url: "/examples/rest/goods/15", method: "PATCH", data: {price: 25000}, dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X PATCH https://сайт/examples/rest/goods/15 --data "price=25000" -i

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

DELETE /goods/{goodId}

Удаление товара

// Удаление товара // DELETE /goods/{goodId} if ($method === "DELETE" && count($urlData) === 1) { // Получаем id товара $goodId = $urlData; // Удаляем товар из базы... // Выводим ответ клиенту echo json_encode(array("method" => "DELETE", "id" => $goodId)); return; }

Тестим из консоли

$.ajax({url: "/examples/rest/goods/20", method: "DELETE", dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X DELETE https://сайт/examples/rest/goods/20 -i

С DELETE-запросом все понятно. Теперь давайте рассмотрим работу с пользователями - роутер users и соответственно, файл users.php

GET /users/{userId}

Получение всех данных о пользователе. Если GET-запрос вида /users/{userId} , то мы вернем всю информацию о пользователе, если дополнительно указывается /info или /orders , то соответственно, только общую информацию или список заказов.

// Роутер function route($method, $urlData, $formData) { // Получение всей информации о пользователе // GET /users/{userId} if ($method === "GET" && count($urlData) === 1) { // Получаем id товара $userId = $urlData; // Вытаскиваем все данные о пользователе из базы... // Выводим ответ клиенту echo json_encode(array("method" => "GET", "id" => $userId, "info" => array("email" => "[email protected]", "name" => "Webdevkin"), "orders" => array(array("orderId" => 5, "summa" => 2000, "orderDate" => "12.01.2017"), array("orderId" => 8, "summa" => 5000, "orderDate" => "03.02.2017")))); return; } // Возвращаем ошибку header("HTTP/1.0 400 Bad Request"); echo json_encode(array("error" => "Bad Request")); }

Тестим из консоли

$.ajax({url: "/examples/rest/users/5", method: "GET", dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X GET https://сайт/examples/rest/users/5 -i

GET /users/{userId}/info

Общая информация о пользователе

// Получение общей информации о пользователе // GET /users/{userId}/info if ($method === "GET" && count($urlData) === 2 && $urlData === "info") { // Получаем id товара $userId = $urlData; // Вытаскиваем общие данные о пользователе из базы... // Выводим ответ клиенту echo json_encode(array("method" => "GET", "id" => $userId, "info" => array("email" => "[email protected]", "name" => "Webdevkin"))); return; }

Тестим из консоли

$.ajax({url: "/examples/rest/users/5/info", method: "GET", dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X GET https://сайт/examples/rest/users/5/info -i

GET /users/{userId}/orders

Получение списка заказов пользователя

// Получение заказов пользователя // GET /users/{userId}/orders if ($method === "GET" && count($urlData) === 2 && $urlData === "orders") { // Получаем id товара $userId = $urlData; // Вытаскиваем данные о заказах пользователя из базы... // Выводим ответ клиенту echo json_encode(array("method" => "GET", "id" => $userId, "orders" => array(array("orderId" => 5, "summa" => 2000, "orderDate" => "12.01.2017"), array("orderId" => 8, "summa" => 5000, "orderDate" => "03.02.2017")))); return; }

Тестим из консоли

$.ajax({url: "/examples/rest/users/5/orders", method: "GET", dataType: "json", success: function(response){console.log("response:", response)}})

Curl -X GET https://сайт/examples/rest/users/5/orders -i

Итоги и исходники

Исходники из примеров статьи -

Как видим, организовать поддержку REST API на нативном php оказалось не так уж и сложно и вполне законными способами. Главное - это поддержка маршрутов и нестандартных для php методов PUT, PATCH и DELETE.

Основной код, реализовывающий эту поддержку, уместился в 3 десятка строк index.php. Остальное - это уже обвязка, которую можно реализовать как угодно. Я предложил это сделать в виде подключаемых файлов-роутеров, имена которых совпадают с сущностями Вашего проекта. Но можно подключить фантазию и найти более интересное решение.

1 year ago | 9.8K

В программированию, очень часто встречается задача, когда нужно обратиться к другому сайту через HTTP или HTTPS. В этой статье мы рассмотрим простой способ, как с помощью языка программирования PHP выполнить данную задачу.

Для чего обращаться с помощью PHP через HTTP или HTTPS к другому сайту?

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

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

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

Пример обращения к другому сайту с помощью PHP

В этом простом примере, мы будем использовать стандартную функцию PHP под названием file_get_contents().

В ответ от сервера VK, вы увидите следующую информацию:

{ - response: [ - { - id: 210700286, - first_name: "Lindsey", - last_name: "Stirling", - bdate: "21.9.1986" - } - ] }

где, мы получили Имя, Фамилию и дату рождения пользователя с ID 210700286.

Как теперь мы может с помощью PHP получить эту информацию и преобразовать ее в массив, для удобной дальнейшей работы?

С помощью языка программирования PHP и функции file_get_contents(), это сделать очень просто!

$user_id - это переменная, в которую вы записываете ID пользователя VK,

$info - в этой переменной мы сохраняем результат обращения к API сайта VK.COM

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

Вывод

Как вы видите, с помощью PHP вы можете очень легко делать запросы к HTTP и HTTPS сайтам и мы рассмотрели лишь одну функцию языка программирования PHP с помощью которой можно получить данные из внешнего сайта.

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

Во втором уроке мы напишем еще два класса и полностью закончим внутреннюю часть скрипта.

План

Цель серии уроков создать простое приложение, которое позволяет пользователям регистрироваться, входить, выходить и менять настройки. Класс, который будет содержать всю информации о пользователе будет называться User и он будет определен в файле User.class.php. Класс, который будет отвечать за вход\выход будет называться UserTools (UserTools.class.php).

Немного про именование классов

Правильным тоном является называть файлы с описанием класса таким же именем как и сам класс. Таким образом легко определить цель каждого файла в папке с классами.

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

Класс Пользователей (User.class.php)

Этот класс будет определять каждого пользователя. С ростом данного приложения определение "Пользователь" может существенно измениться. К счастью, ООП программирование позволяет легко добавлять дополнительные атрибуты пользователей.

Конструктор

В этом классе мы будем использовать конструктор - это функция, которая автоматически вызывается при создании очередной копии класса. Это позволяет нам автоматически публиковать некоторые атрибуты после создания проекта. В этом классе конструктор будет брать единственный аргумент: ассоциативный массив, который содержит один ряд из таблицы users нашей БД.

require_once "DB.class.php"; class User { public $id; public $username; public $hashedPassword; public $email;
public $joinDate;
//Конструктор вызывается при создании нового объекта //Takes an associative array with the DB row as an argument. function __construct($data) { $this->id = (isset($data["id"])) ? $data["id"] : ""; $this->username = (isset($data["username"])) ? $data["username"] : ""; $this->hashedPassword = (isset($data["password"])) ? $data["password"] : ""; $this->email = (isset($data["email"])) ? $data["email"] : ""; $this->joinDate = (isset($data["join_date"])) ? $data["join_date"] : ""; }
public function save($isNewUser = false) { //create a new database object. $db = new DB(); //if the user is already registered and we"re //just updating their info. if(!$isNewUser) { //set the data array $data = array("username" => ""$this->username"", "password" => ""$this->hashedPassword"",
"email" => ""$this->email"");
//update the row in the database $db->update($data, "users", "id = ".$this->id); }else { //if the user is being registered for the first time. $data = array("username" => ""$this->username"", "password" => ""$this->hashedPassword"", "email" => ""$this->email"", "join_date" => """.date("Y-m-d H:i:s",time())."""); $this->id = $db->insert($data, "users"); $this->joinDate = time(); } return true; } } ?>

Объяснение

Первая часть кода, вне зоны класса, обеспечивает подключение класса в БД (поскольку в классе User есть функция, которая требует этот класс).

Вместо переменных класса “protected” (использовались в 1-м уроке) мы определяем их как “public”. Это означает, что любой код вне класса имеет доступ к этим переменным при работе с объектом User.

Конструктор берет массив, в котором колонки в таблице являются ключами. Мы задаем переменную класса используя $this->variablename. В примере данного класса, мы прежде всего проверяем существует ли значение определенного ключа. Если да, тогда мы приравниваем переменную класса к этому значению. В противном случае - пустая строка. Код использует краткую форму записи оборота if:

$value = (3 == 4) ? "A" : "B";

В данном примере мы проверяем равняется ли 3 четырем! Если да - тогда $value = “A”, нет - $value = “B”. В нашем примере результат $value = “B”.

Сохраняем Информацию о Пользователях в БД

Функция сохранения используется для внесения изменений в таблицу БД с текущими значениями в объекте User. Эта функция использует класс БД, который мы создали в первом уроке. Используя переменные класса, устанавливается массив $data. Если данные о пользователе сохраняются впервые, тогда $isNewUser передается как $true (по умолчанию false). Если $isNewUser = $true, тогда вызывается функция insert() класса DB. В противном случае вызывается функция update(). В обоих случаях информация от объекта user будет сохранена в БД.

Класс UserTools.class.php

Этот класс будет содержать функции, которые имеют отношение к пользователям: login(), logout(), checkUsernameExists() и get(). Но с расширением данного приложения, Вы можете добавить еще множество других.

//UserTools.class.php require_once "User.class.php"; require_once "DB.class.php";
class UserTools {
//Log the user in. First checks to see if the //username and password match a row in the database. //If it is successful, set the session variables //and store the user object within.
public function login($username, $password)
{
$hashedPassword = md5($password); $result = mysql_query("SELECT * FROM users WHERE username = "$username" AND password = "$hashedPassword""); if(mysql_num_rows($result) == 1) { $_SESSION["user"] = serialize(new User(mysql_fetch_assoc($result))); $_SESSION["login_time"] = time(); $_SESSION["logged_in"] = 1; return true; }else{ return false; } }
//Log the user out. Destroy the session variables. public function logout() { unset($_SESSION["user"]); unset($_SESSION["login_time"]); unset($_SESSION["logged_in"]); session_destroy(); } //Check to see if a username exists. //This is called during registration to make sure all user names are unique. public function checkUsernameExists($username) { $result = mysql_query("select id from users where username="$username""); if(mysql_num_rows($result) == 0) { return false; }else{ return true; }
}
//get a user //returns a User object. Takes the users id as an input public function get($id) { $db = new DB(); $result = $db->select("users", "id = $id"); return new User($result); } }
?>

Функция login()

Функция login() понятна по названию. Она берет аргументы пользователя $username и $password и проверяет их соответствие. Если все совпадает, создает объект User со всей информацией и сохраняет его в сессии. Обратите внимание, что мы только используем функцию PHP serialize(). Она создает сохраненный вариант объекта, который можно легко отменить с помощью unserialize(). Также время логина будет сохранено. Это может использоваться в дальнейшем для предоставления пользователям информации о длительности пребывания на сайте.

Вы также можете заметить, что мы выставляем $_SESSION["logged_in"] на 1. Это позволяет нам легко проверить на каждой странице залогинен ли пользователь. Достаточно проверить только эту переменную.

Функция logout()

Также простая функция. Функция PHP unset() очищает переменные в памяти, в то время как session_destroy() удалит сессию.

Функция checkUsernameExists()

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

Функция get()

Эта функция берет уникальный id пользователя и делает запрос к БД с помощью класса DB, а именно функции select(). Она возьмет ассоциативный массив с рядом информации о пользователе и создаст новый объект User, передавая массив конструктору.

Где можно это использовать? К примеру, если Вы создадите страницу, которая должна отображать специфические профили пользователей, Вам необходимо будет динамически брать эту информацию. Вот так Вы можете это сделать: (допустим УРЛ http://www.website.com/profile.php?userID=3)

//note: you will have to open up a database connection first. //see Part 1 for further information on doing so. //You"ll also have to make sure that you"ve included the class files.
$tools = new UserTools(); $user = $tools->get($_REQUEST["userID"]); echo "Username: ".$user->username.""; echo "Joined On: ".$user->joinDate."";

Легко! Правда?

Последний штрих серверной части: global.inc.php

global.inc.php необходим для каждой страницы сайта. Почему? Таким образом мы разместим все обычные операции, которые нам понадобятся на странице. К примеру, мы начнем session_start(). Соединение с БД также откроется.

require_once "classes/UserTools.class.php";
require_once "classes/DB.class.php";
//connect to the database $db = new DB(); $db->connect();
//initialize UserTools object $userTools = new UserTools(); //start the session
session_start();
//refresh session variables if logged in if(isset($_SESSION["logged_in"])) { $user = unserialize($_SESSION["user"]); $_SESSION["user"] = serialize($userTools->get($user->id)); } ?>

Что он делает?

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

После соединения, мы начинаем функцию session_start(). Функция создает сессию или продолжает текущую, если пользователь уже залогинен. Поскольку наше приложение рассчитано на то, чтобы пользователи входили\выходили, эта функция обязательна на каждой странице.

Далее мы проверяем залогинен ли юзер. Если да - мы обновим $_SESSION["user"], чтобы отображать самую последнюю информацию о юзере. К примеру, если пользователь меняет свой емейл, в сессии будет храниться еще старый. Но с помощью авто обновления такого не случится.

На этом вторая часть подошла к концу! Завтра ожидайте заключительный урок по этой теме.

Всего наилучшего!

Получает объект WP_User, который содержит все данные указанного пользователя.

Данные, возвращаемые функций полностью соответствуют полям таблиц БД: wp_users и wp_usermeta (описание таблиц ).

Это pluggable функция - т.е. её можно заменить из плагина. Это значит, что она будет работать (подключается) только после подключения всех плагинов, а до этого момента функция еще не определена... Поэтому нельзя вызывать эту и зависящие от неё функции прямо из кода плагина. Их нужно вызывать через хук plugins_loaded или позднее, например хук init .

Замена функции (переопределение) - в плагине можно создать функцию с таким же названием, тогда она заменит текущую функцию.

✈ 1 раз = 0.000296с = быстро | 50000 раз = 0.78с = очень быстро | PHP 7.1.2RC1, WP 4.7.2

Хуков нет.

Возвращает

WP_User/false. Объект данных или false, если не удалось найти указанного пользователя.

Использование

get_userdata($userid); $userid(число) (обязательный) ID пользователя, данные которого нужно получить.
По умолчанию: нет

Примеры

#1 Как выводить данные из полученного объекта данных

$user_info = get_userdata(1); echo "Имя пользователя: " . $user_info->user_login . "\n"; echo "Уровень доступа: " . $user_info->user_level . "\n"; echo "ID: " . $user_info->ID . "\n"; /* Выведет: Имя пользователя: admin Уровень доступа: 10 ID: 1 */

#1.2 Данные в переменную

Еще одни пример, только тут запишем данные сначала в переменные, а затем выведем из на экран:

$user = get_userdata(1); $username = $user->user_login; $first_name = $user->first_name; $last_name = $user->last_name; echo "$first_name $last_name зашел(а) на сайт под логином: $username."; /* Объект $user: WP_User Object( => stdClass Object( => 80 => kogian => $P$BJFHKJfUKyWv1TwЛОВАЕnYU0JGNsq. => kogian => [email protected] => http://example.com/ => 2016-09-01 00:34:42 => => => kogian) => 80 => Array( => 1) => wp_capabilities => Array( => subscriber) => Array( => 1 => 1 => 1) => => 1) */

#2 Методы класса

Получаемый объект с помощью get_userdata() - это экземпляр класса и у него есть методы, которые можно использовать. Иногда это может пригодится. Вот простой пример получения опции пользователя, с помощью метода $user->get() :

$user = get_userdata(1); echo $username = $user->get("user_login");

Список некоторых методов:

    get($key) - вернет значение опции;

    has_prop($key) - проверяет установлена ли указанная опция;

    has_cap($cap) - проверяет имеет ли пользователь указанную возможность или роль;

    get_role_caps() - получает все возможности роли пользователя и объединяет их с индивидуальными возможностями пользователя;

    add_role($role) - добавляет роль к пользователю;

    remove_role($role) - удаляет роль у пользователя;

  • set_role($role) - устанавливает роль пользователя;

Заметки

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

  • display_name

user_meta

  • user_description

    wp_capabilities (массив)

    admin_color (тема админ панели. По умолчанию - свежая (fresh))

    closedpostboxes_page

  • source_domain

Также надо отметит, что с версии 3.2., возвращаемые данные немного изменились: возвращается объект WP_User . Данные в объекте разбиваются на группы: data , caps , roles (раньше данные возвращались в общем списке).

Однако, благодаря "волшебным" (служебным) методам PHP данные можно получить как и прежде, например, сейчас данные хранятся так: get_userdata(1)->data->rich_editing , но получить их можно так: get_userdata(1)->rich_editing , несмотря на то, что var_dump() не покажет эту взаимосвязь.

Код get userdata : wp-includes/pluggable.php WP 5.2.2