Скрытые возможности PHP?
Я знаю, что это звучит как вопрос для обсуждения, но позвольте мне объяснить, откуда я.
Вне колледжа я устроился на работу в магазин PHP. Я проработал там полтора года и подумал, что научился всему, что можно было узнать о программировании.
Затем я получил работу в качестве единоличного цеха внутренней разработки в крупной корпорации, где вся работа была на C#. В своей приверженности этой должности я начал читать тонну блогов и книг и быстро понял, как неправильно я думал, что знаю все. Я узнал о модульном тестировании, внедрении зависимостей и шаблонах декораторов, принципе проектирования слабой связи, обсуждении композиции по наследованию и так далее, и тому подобное - я все еще очень поглощаю все это. Излишне говорить, что мой стиль программирования полностью изменился за последний год.
Теперь я ловлю себя на том, что подбираю проект php, выполняющий некоторое кодирование для запуска друга, и я чувствую себя полностью ограниченным в отличие от программирования на C#. Меня действительно беспокоит то, что на все переменные в области видимости класса нужно ссылаться путем добавления '$this->' . Меня раздражает, что ни одна из IDE, которые я пробовал, не имеет очень хорошего интеллекта и что мои методы модульных тестов SimpleTest должны начинаться со слова "test". Это сводит меня с ума, что динамическая типизация мешает мне неявно указывать, какой тип параметра ожидает метод, и что вам нужно написать оператор switch для выполнения перегрузок метода. Я не могу смириться с тем, что вы не можете иметь вложенные пространства имен и вынуждены использовать оператор:: для вызова конструктора базового класса.
Теперь я не собираюсь начинать дебаты по PHP против C#, скорее хочу сказать, что я уверен, что есть некоторые функции PHP, о которых я либо не знаю, либо знаю, но не могу их использовать должным образом. Я нахожусь в моей C# вселенной и испытываю проблемы с видением за пределами стеклянной чаши.
Итак, я спрашиваю, какие ваши любимые функции PHP? Что вы можете сделать в этом, чего вы не можете или более сложны в языках.Net?
78 ответов
Документация Документация получает мой голос. Я не сталкивался с более подробной онлайн-документацией по языку программирования - все остальное, что мне нужно собрать из разных веб-сайтов и справочных страниц.
Массивы. Судя по ответам на этот вопрос, я не думаю, что люди полностью понимают, насколько просты и полезны массивы в PHP. Массивы PHP действуют как списки, карты, стеки и общие структуры данных одновременно. Массивы реализованы в языковом ядре и используются повсеместно, что приводит к хорошей локализации кэша ЦП. И Perl, и Python используют отдельные языковые конструкции для списков и карт, что приводит к большему количеству копий и потенциально запутанным преобразованиям.
Обработчики потоков позволяют расширять "файловую систему" с помощью логики, которую, насколько я знаю, довольно трудно сделать в большинстве других языков.
Например, с помощью обработчика потока MS-Excel вы можете создать файл MS Excel следующим образом:
$fp = fopen("xlsfile://tmp/test.xls", "wb");
if (!is_resource($fp)) {
die("Cannot open excel file");
}
$data= array(
array("Name" => "Bob Loblaw", "Age" => 50),
array("Name" => "Popo Jijo", "Age" => 75),
array("Name" => "Tiny Tim", "Age" => 90)
);
fwrite($fp, serialize($data));
fclose($fp);
Магические методы - это резервные методы, которые вызываются, когда вы вызываете метод, который не существует, или присваиваете или читаете свойство, которое не существует, среди прочего.
interface AllMagicMethods {
// accessing undefined or invisible (e.g. private) properties
public function __get($fieldName);
public function __set($fieldName, $value);
public function __isset($fieldName);
public function __unset($fieldName);
// calling undefined or invisible (e.g. private) methods
public function __call($funcName, $args);
public static function __callStatic($funcName, $args); // as of PHP 5.3
// on serialize() / unserialize()
public function __sleep();
public function __wakeup();
// conversion to string (e.g. with (string) $obj, echo $obj, strlen($obj), ...)
public function __toString();
// calling the object like a function (e.g. $obj($arg, $arg2))
public function __invoke($arguments, $...);
// called on var_export()
public static function __set_state($array);
}
Разработчик C++ здесь может заметить, что PHP позволяет перегружать некоторые операторы, например ()
или же (string)
, На самом деле PHP позволяет перегружать еще больше, например, []
оператор ( ArrayAccess), foreach
языковая конструкция ( Iterator и IteratorAggregate) и count
функция ( счетная).
Стандартный класс - это аккуратный контейнер. Я только узнал об этом недавно.
Вместо использования массива для хранения нескольких атрибутов
$person = array();
$person['name'] = 'bob';
$person['age'] = 5;
Вы можете использовать стандартный класс
$person = new stdClass();
$person->name = 'bob';
$person->age = 5;
Это особенно полезно при доступе к этим переменным в строке
$string = $person['name'] . ' is ' . $person['age'] . ' years old.';
// vs
$string = "$person->name is $person->age years old.";
У включаемых файлов может быть возвращаемое значение, которое вы можете назначить переменной.
// config.php
return array(
'db' => array(
'host' => 'example.org',
'user' => 'usr',
// ...
),
// ...
);
// index.php
$config = include 'config.php';
echo $config['db']['host']; // example.org
Вы можете воспользоваться тем, что or
оператор имеет более низкий приоритет, чем =
сделать это:
$page = (int) @$_GET['page']
or $page = 1;
Если значение первого присваивания оценивается как true
, второе назначение игнорируется. Другой пример:
$record = get_record($id)
or throw new Exception("...");
__autoload()
(класс-) файлы с помощью set_include_path()
,
В PHP5 теперь нет необходимости указывать длинные списки операторов include_once при выполнении приличного ООП.
Просто определите небольшой набор каталогов, в которых разумно структурированы файлы библиотеки классов, и установите путь автоматического включения:
set_include_path(get_include_path() . PATH_SEPARATOR . '../libs/');`
Теперь __autoload()
Режим дня:
function __autoload($classname) {
// every class is stored in a file "libs/classname.class.php"
// note: temporary alter error_reporting to prevent WARNINGS
// Do not suppress errors with a @ - syntax errors will fail silently!
include_once($classname . '.class.php');
}
Теперь PHP будет автоматически включать необходимые файлы по требованию, сохраняя время анализа и память.
Легкость Самая большая особенность заключается в том, как легко новым разработчикам сесть и написать "рабочие" сценарии и понять код.
Хуже всего то, как легко новым разработчикам сесть и написать "рабочие" скрипты и подумать, что они понимают код.
Открытость сообщества, окружающего PHP, и огромное количество PHP-проектов, доступных в виде открытого исходного кода, намного менее пугающе для тех, кто входит в мир разработки и, как вы, может стать ступенькой к более зрелым языкам.
Я не буду обсуждать технические вещи, которые есть у многих до меня, но если вы посмотрите на PHP как на сообщество, а не на веб-язык, сообщество, которое явно охватило вас, когда вы начали разрабатывать, преимущества действительно говорят сами за себя.
Переменные переменные и функции без сомнения!
$foo = 'bar';
$bar = 'foobar';
echo $$foo; //This outputs foobar
function bar() {
echo 'Hello world!';
}
function foobar() {
echo 'What a wonderful world!';
}
$foo(); //This outputs Hello world!
$$foo(); //This outputs What a wonderful world!
То же самое относится и к параметрам объекта ($some_object->$some_variable);
Очень очень хорошо. Сделать кодирование с помощью циклов и шаблонов очень просто, и это быстрее и более под контролем, чем eval (Спасибо @Ross & @Joshi Spawnbrood!). T
Вы можете использовать функции с неопределенным числом аргументов, используя func_get_args()
,
<?php
function test() {
$args = func_get_args();
echo $args[2]; // will print 'd'
echo $args[1]; // will print 3
}
test(1,3,'d',4);
?>
Я люблю удаленные файлы. Для веб-разработки эта функция исключительно полезна.
Нужно работать с содержимым веб-страницы? Просто
$fp = fopen('http://example.com');
и у вас есть готовый дескриптор файла, как и любой другой обычный файл.
Или как насчет чтения удаленного файла или веб-страницы прямо в строку?
$str = file_get_contents('http://example.com/file');
Полезность этого метода трудно переоценить.
Хотите проанализировать удаленное изображение? Как насчет того, чтобы сделать это через FTP?
$imageInfo = getimagesize('ftp://user:password@ftp.example.com/image/name.jpg');
Почти любая функция PHP, которая работает с файлами, может работать с удаленным файлом. Вы можете даже include()
или же require()
кодировать файлы удаленно таким образом.
Это очень быстро, так сильно, что вы будете поражены. Внутренне он, вероятно, использует некоторую сумасшедшую структуру типа b-дерева, чтобы упорядочить ваши совпадения по их общим префиксам. Я использую его с более чем 200 строк поиска и замены, и он все еще проходит через 1 МБ менее чем за 100 мс. Для всех, кроме тривиально небольших строк, strtr() даже значительно быстрее, чем strtolower(), делает то же самое, даже принимая во внимание набор символов. Вероятно, вы могли бы написать целый анализатор, используя последовательные вызовы strtr, и это было бы быстрее, чем обычное сопоставление с регулярным выражением, выяснить тип токена, вывести то или иное, следующий тип регулярного выражения.
Я писал нормализатор текста для разделения текста на слова, нижнего регистра, удаления знаков препинания и т. Д., И strtr был моим швейцарским армейским ножом, он выбивал штаны из регулярных выражений или даже str_replace().
Одна не очень известная особенность PHP extract()
, функция, которая распаковывает ассоциативный массив в локальное пространство имен. Это, вероятно, существует для аблобинации автоглобалов, но очень полезно для шаблонов:
function render_template($template_name, $context, $as_string=false)
{
extract($context);
if ($as_string)
ob_start();
include TEMPLATE_DIR . '/' . $template_name;
if ($as_string)
return ob_get_clean();
}
Теперь вы можете использовать render_template('index.html', array('foo' => 'bar'))
и только $foo
со значением "bar"
появляется в шаблоне.
Range() сам по себе не скрыт, но я все еще вижу много людей, повторяющих:
for ($i=0; $i < $x; $i++) {
// code...
}
когда они могли бы использовать:
foreach (range(0, 12) as $number) {
// ...
}
И вы можете делать простые вещи, как
foreach (range(date("Y"), date("Y")+20) as $i)
{
print "\t<option value=\"{$i}\">{$i}</option>\n";
}
Веб-пространство с поддержкой PHP обычно дешевле, чем что-либо с (asp).net. Вы могли бы назвать это функцией;-)
static
ключевое слово полезно вне точки зрения ООП. Вы можете быстро и легко реализовать "запоминание" или кэширование функций с помощью чего-то простого:
<?php
function foo($arg1)
{
static $cache;
if( !isset($cache[md5($arg1)]) )
{
// Do the work here
$cache[md5($arg1)] = $results;
}
return $cache[md5($arg1)];
}
?>
static
Ключевое слово создает переменную, которая сохраняется только в рамках этой функции после выполнения. Этот метод отлично подходит для функций, которые попадают в базу данных, как get_all_books_by_id(...)
или же get_all_categories(...)
что вы будете звонить более одного раза во время загрузки страницы.
Предостережение: убедитесь, что вы нашли лучший способ сделать ключ для своего хэша, практически в любых обстоятельствах md5(...)
выше НЕ является хорошим решением (проблемы со скоростью и длиной вывода), я использовал его в иллюстративных целях. sprintf('%u', crc32(...))
или же spl_object_hash(...)
может быть намного лучше в зависимости от контекста.
Одна приятная особенность PHP - это CLI. Это не так "рекламируется" в документации, но если вам нужны обычные скрипты / консольные приложения, использование cron + php cli очень быстро развивается!
Тогда "и печатать" трюк
<?php $flag and print "Blah" ?>
Будет повторять бла, если $flag равен true. НЕ РАБОТАЕТ С ЭХО.
Это очень удобно в шаблоне и заменить?: это не очень легко читать.
Вы можете использовать минус в именах переменных следующим образом:
class style
{
....
function set_bg_colour($c)
{
$this->{'background-color'} = $c;
}
}
Зачем использовать это? Понятия не имею: может быть, для модели CSS? Или какой-то странный JSON, который вам нужно вывести. Это странная особенность:)
Вероятно, не многие знают, что в качестве значений по умолчанию для параметров функции можно указать постоянные "переменные":
function myFunc($param1, $param2 = MY_CONST)
{
//code...
}
Строки могут быть использованы, как если бы они были массивами:
$str = 'hell o World';
echo $str; //outputs: "hell o World"
$str[0] = 'H';
echo $str; //outputs: "Hell o World"
$str[4] = null;
echo $str; //outputs: "Hello World"
СинтаксисHEREDOC - моя любимая скрытая функция. Всегда трудно найти, так как вы не можете Google для <<<, но он избавляет вас от необходимости избегать больших кусков HTML и все еще позволяет вам отбрасывать переменные в поток.
echo <<<EOM
<div id="someblock">
<img src="{$file}" />
</div>
EOM;
Единственная наиболее полезная вещь в PHP-коде состоит в том, что, если я не совсем понимаю функцию, которую я вижу, я могу посмотреть ее с помощью браузера и набрав:
В прошлом месяце я видел функцию "диапазон" в некотором коде. Это одна из сотен функций, которые мне никогда не удавалось использовать, но они оказались действительно полезными:
Этот URL является псевдонимом для http://us2.php.net/manual/en/function.range.php. Эта простая идея - сопоставить функции и ключевые слова с URL-адресами- потрясающая.
Я хотел бы, чтобы другие языки, фреймворки, базы данных, операционные системы имели такой же простой механизм поиска документации.
Быстрая блокировка комментариев
/*
die('You shall not pass!');
//*/
//*
die('You shall not pass!');
//*/
Эти комментарии позволяют вам переключаться, если блок кода комментируется одним символом.
Мой список... большинство из них подпадают под "скрытые функции", а не "любимые функции" (надеюсь!), И не все они полезны, но... да.
// swap values. any number of vars works, obviously
list($a, $b) = array($b, $a);
// nested list() calls "fill" variables from multidim arrays:
$arr = array(
array('aaaa', 'bbb'),
array('cc', 'd')
);
list(list($a, $b), list($c, $d)) = $arr;
echo "$a $b $c $d"; // -> aaaa bbb cc d
// list() values to arrays
while (list($arr1[], $arr2[], $arr3[]) = mysql_fetch_row($res)) { .. }
// or get columns from a matrix
foreach($data as $row) list($col_1[], $col_2[], $col_3[]) = $row;
// abusing the ternary operator to set other variables as a side effect:
$foo = $condition ? 'Yes' . (($bar = 'right') && false) : 'No' . (($bar = 'left') && false);
// boolean False cast to string for concatenation becomes an empty string ''.
// you can also use list() but that's so boring ;-)
list($foo, $bar) = $condition ? array('Yes', 'right') : array('No', 'left');
Вы также можете вкладывать троичные операторы, иногда это удобно.
// the strings' "Complex syntax" allows for *weird* stuff.
// given $i = 3, if $custom is true, set $foo to $P['size3'], else to $C['size3']:
$foo = ${$custom?'P':'C'}['size'.$i];
$foo = $custom?$P['size'.$i]:$C['size'.$i]; // does the same, but it's too long ;-)
// similarly, splitting an array $all_rows into two arrays $data0 and $data1 based
// on some field 'active' in the sub-arrays:
foreach ($all_rows as $row) ${'data'.($row['active']?1:0)}[] = $row;
// slight adaption from another answer here, I had to try out what else you could
// abuse as variable names.. turns out, way too much...
$string = 'f.> <!-? o+';
${$string} = 'asdfasf';
echo ${$string}; // -> 'asdfasf'
echo $GLOBALS['f.> <!-? o+']; // -> 'asdfasf'
// (don't do this. srsly.)
${''} = 456;
echo ${''}; // -> 456
echo $GLOBALS['']; // -> 456
// I have no idea.
Хорошо, я сейчас остановлюсь:-)
Хм, это было какое-то время..
// just discovered you can comment the hell out of php:
$q/* snarf */=/* quux */$_GET/* foo */[/* bar */'q'/* bazz */]/* yadda */;
Итак, только что обнаружил, что вы можете передать любую строку в качестве имени метода, если вы заключите ее в фигурные скобки. Вы не можете определить какую-либо строку как метод увы, но вы можете перехватить их с помощью __call() и обрабатывать их по мере необходимости. Хммм....
class foo {
function __call($func, $args) {
eval ($func);
}
}
$x = new foo;
$x->{'foreach(range(1, 10) as $i) {echo $i."\n";}'}();
Нашел этот маленький драгоценный камень в комментариях Reddit:
$foo = 'abcde';
$strlen = 'strlen';
echo "$foo is {$strlen($foo)} characters long."; // "abcde is 5 characters long."
Вы не можете вызывать функции внутри {} напрямую, как это, но вы можете использовать переменные-удерживающие-имя-функции и вызывать их! (* и * вы также можете использовать переменные переменные)
Манипуляция массивом.
Тонны инструментов для работы с массивами и манипулирования ими. Возможно, он не уникален для PHP, но я никогда не работал с языком, который делал это так просто.
Я немного похож на вас, я кодирую PHP более 8 лет. Я должен был пройти курс обучения.NET/C# около года назад, и мне действительно понравился язык C# (ненавистный ASP.NET), но он сделал меня лучшим разработчиком PHP.
PHP как язык довольно беден, но я очень быстр в этом, и стек LAMP потрясающий. Конечный продукт намного перевешивает сумму частей.
Тем не менее, в ответ на ваш вопрос:
Мне нравится SPL, класс коллекций в C# мне понравился, как только я начал с ним. Теперь я могу взять свой пирог и съесть его.
Эндрю
Я немного удивлен, что никто еще не упомянул об этом, но один из моих любимых приемов с массивами - использование оператора плюс. Это немного похоже array_merge()
но немного проще. Я обнаружил, что обычно это то, что я хочу. По сути, он берет все записи в RHS и заставляет их появиться в копии LHS, перезаписывая по мере необходимости (т.е. это некоммутативно). Очень полезно для запуска с массива "по умолчанию" и добавления нескольких реальных значений в одно попадание, при этом оставляя значения по умолчанию на месте для значений, не предоставленных.
Требуемый пример кода:
// Set the normal defaults.
$control_defaults = array( 'type' => 'text', 'size' => 30 );
// ... many lines later ...
$control_5 = $control_defaults + array( 'name' => 'surname', 'size' => 40 );
// This is the same as:
// $control_5 = array( 'type' => 'text', 'name' => 'surname', 'size' => 40 );
Быстро и грязно по умолчанию.
Язык наполнен полезными ярлыками, что делает PHP идеальным кандидатом для (небольших) проектов, которые имеют короткий срок выхода на рынок. Не то, чтобы чистый код PHP был невозможен, это просто требует дополнительных усилий и опыта.
Но я люблю PHP, потому что он позволяет мне выразить то, что я хочу, не набирая эссе.
PHP:
if (preg_match("/cat/","one cat")) {
// do something
}
ДЖАВА:
import java.util.regex.*;
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat")
if (m.find()) {
// do something
}
И да, это включает в себя не печатать Int.
Вот один, мне нравится, как намного проще установить значения по умолчанию для параметров функции, которые не указаны:
function MyMethod($VarICareAbout, $VarIDontCareAbout = 'yippie') { }