Отправляет email-рассылки с помощью сервиса Sendsay

Программирование в Web

  Все выпуски  

Программирование в Web Выпуск 10 от 12/05/2006 Основы PHP - Урок-7


 
Программирование в web

ОСНОВЫ PHP
 

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

 
У Р О К    7
Здравствуйте уважаемые подписчики!

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



Примечание: Раз вы все не против, так и буду продолжать предлагать уроки по PHP и по HTML поочередно.


ФУНКЦИИ:

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

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

<?php
function name(параметр1, параметр2..., параметрn)
{
Тело функции;
}
?>

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

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

global $life;

где $life - это переменная с именем, которое совпадает с именем переменной вне функции (инструкция global работает только внутри функций, вне функции все переменные считаются глобальными).

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

<?php
$life="Жизнь прекрасна";
function myfunc($i)
{
global $life;
$life=$i;
$i=$i+200;
return $i; //Так обозначаем возвращаемое функцией значение, то есть с помощью ключевого слова return.
}
$result=myfunc(100);
print $result;
print "<br>";
print $life;
print "<br>";
print myfunc(100)-100;
?>

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

300
100
200

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

<?php
$life="Жизнь прекрасна";
function myfunc($i)
{
$life=$i;
$i=$i+200;
return $i; //Так обозначаем возвращаемое функцией значение, то есть с помощью ключевого слова return.
}
$result=myfunc(100);
print $result;
print "<br>";
print $life;
print "<br>";
print myfunc(100)-100;
?>

Результат:

300
Жизнь прекрасна
200

Примечание: В уроках по HTML мы еще не изучали тег <br />, в дальнейшем этот пробел будет заполнен, сейчас же скажу, что этот простой тег служит для перевода строки. То есть, текст, написанные после этого тега всегда будет начинаться с новой строки. В PHP этот тег можно легко заменить специальной последовательностью (/n), которая задает команду перевести строку, то есть именно тоже самое, что делает тег <br />.

Как видите значение переменной осталось без изменений. Но это еще не все. Параметры в функцию можно передавать и по ссылке, с использованием перед параметром знака амперсэнд (&), написанным перед параметром. Это можно сделать как при объявлении функции, так и при ее вызове. В первом случае, при вызове функции уже не придется задумываться о подстановке дополнительного знака амперсэнда перед параметром, функция автоматически «поймет», что раз объявлено по ссылке, значит по ссылке и передавать, во втором случае, придется всегда подставлять при каждом вызове этот дополнительный знак амперсэнда перед параметром, что иногда может, в случае забывчивости, привести к трудноуловимым ошибкам. Что же мы выигрываем при передаче параметра по ссылке? Да таким образом мы просто-напросто влияем на значение внешней, уже существующей вне функции переменной, то есть, если внутри функции, параметр, переданны й по ссылке будет изменен, то и значение одноименной с ним внешней переменной будет также изменено (некая альтернатива объявления глобальной переменной внутри функции). Иногда, если надо, чтобы функция возвращала больше чем одно значение, такой подход становится удобным, но при этом трудноконтролируемым, ведь по забывчивости можно не учесть этих глобальных изменений и тогда в программе появится ошибка. Вобщем пользуйтесь этим с осторожностью. Вот пример передачи параметра по ссылке:

<?php
$life="Жизнь ";
function myfunc(&$life)
{
$life=$life."прекрасна";
return $life;
}
$result=myfunc($life); //При вызове функции уже нет необходимости ставить знак амперсэнда, ведь он уже присутствует в объявлении.
print $result;
print "<br>";
print $life;
?>

Результат:

Жизнь прекрасна
Жизнь прекрасна

То есть вы видите, что и существовавшая вне функции переменная $life тоже изменила свое значение. Есть еще кое-что, что вам было бы интересно знать о функциях. По аналогии с переменными, функции тоже можно вызывать динамически, присвоив имя функции какой-то переменной и потом вызывать уже через эту переменную, но применяется это очень редко, и, в основном, для того, чтобы сильнее запутать и без того запутанную программу. Поэтому вдаваться в подробности такого вызова функций я не буду. А вот как сделать, чтобы функция запоминала свое состояние? Ну например, чтобы могла подсчитать, сколько раз она была вызвана? Все просто, для этого, внутри функции надо объявить какую-то переменную и предварить ее имя инструкцией static. Вот пример:

<?php
function myfunc($text, $endtext)
{
static $count=0;
$count++;
print "$text $count $endtext";
}
myfunc("Функция была вызвана", "раз");
print "<br>";
myfunc("Функция была вызвана", "раза");
print "<br>";
myfunc("Функция была вызвана", "раза");
print "<br>";
myfunc("Функция была вызвана", "раза");
print "<br>";
myfunc("Функция была вызвана", "раз");
?>

В браузере будут выведены следующие строки:

Функция была вызвана 1 раз
Функция была вызвана 2 раза
Функция была вызвана 3 раза
Функция была вызвана 4 раза
Функция была вызвана 5 раз

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

<?php
function myfunc($text, $size=3, $color="red")
{
print "<center><font size\"$size\" color=\"$color\"></font></center>";
}
myfunc("Вот такая надпись", 5, "blue");
print "<br>";
myfunc("Вот такая надпись", 5, "red");
print "<br>";
myfunc("Вот такая надпись", 3, "green");
print "<br>";
myfunc("Вот такая надпись", 5);
print "<br>";
myfunc("Вот такая надпись");
?>

В браузере будут последовательно выведены пять строк по центру: Первая строка «Вот такая надпись» размером шрифта 5 и синего цвета, вторая строка такого же размера, но красного цвета, третья строка размером в 3 и зеленого цвета, четвертая строка будет использовать третий параметр по умолчанию и будет выведена размером в 5 и красного цвета, а пятая строка уже использует последние два параметра по умолчанию, то есть размер будет равен 3, а цвет - красный. Заметьте, что отсекаем параметры справа налево, но в данном случае запятые не нужны. Вообще, что касается вышесказанного о количестве параметров, еще раз рекомендую никогда не отсекать параметры, если не заданы в объявлении функции значения по умолчанию. Хоть по спецификации PHP это допустимо, по вышеприведенным правилам, но у меня лично очень часто при обрезании выдается ошибка если не указаны значения параметров по умолчанию, возможно это просто ошибка версии интерпретатора.


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

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

 

 
Объявления!!!

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

И еще. В будущем, когда будет возникать много вопросов, я, в каждом выпуске буду публиковать блоки вопросов-ответов, где каждый сможет задать свой вопрос и каждый сможет дать ответ на заданные вопросы. Также будет еще один блок, в котором будут публиковаться советы из вашего личного опыта, если вы им (опытом) пожелаете поделиться. Правда, при этом, надо будет не спешить и не забегать вперед, все советы должны касаться уже пройденного материала, а не того, который будет дан в будущем. Также будет открыт блок задач и решений. То есть, это будет нечто вроде домашнего задания или вопросов для повторения. Буду приводить задачу, а вы будете ее решать средствами PHP и присылать мне, после чего, ваши решения будут также публиковаться в выпусках рассылки. Естественно, что при этом будут публиковаться только разные и только правильные решения. Сами понимаете, что одинаковые решения п убликовать не имеет смысла, иначе это превратится в бесконечный повтор одного и того же кода, а неправильные решения будут запутывать остальных читателей рассылки. Все эти вопросы, ответы, решения, советы и так далее шлите на тот же самый мой адрес, с соответствующей темой. Ваши сообщения без темы я, скорее всего, просто не смогу прочесть по той или иной причине. Если вы будете давать ответ на задачу, в теме также указывайте и номер задачи или номера нескольких задач, на которую или которые даете ответ.

И последнее в этом выпуске. Многие из вас присылают мне запросы на отправку им того или иного, не полученного ранее, выпуска рассылки. У меня не всегда есть возможность это сделать. Поэтому предлагаю вам для начала посмотреть нужный выпуск в архиве рассылки. Рассылка выходит сразу на трех рассыльных сервисах, и по некоторым причинам (мне не известным) некоторые сервисы не принимают адресов, в которых встречаются именя конкурирующих рассыльных сервисов, по этой причине я опубликую только одну ссылку на архив рассылки только одного рассыльного сервиса, а именно Content.mail.ru. Вот ссылка на на этот архив рассылки - http://content.mail.ru/pages/p_21931.html. В общем-то это объявление наверное лишнее, ведь в каждом выпуске каждой рассылки, вне зависимости от того, на каком сервисе она выходит, всегда указан этот самый адрес архива рассылки. На сабскрайб.ру и на контент.мэйл.ру этот адрес указывается в самом низу выпуска, а на мэйллист.ру - в самом верху выпуска. Так что, при достаточном внимании, вы сами легко сможете найти нужную ссылку на архив рассылки.

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

 

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

 
Наш проект
Автор рассылки — Anatolick
Архив рассылки — http://content.mail.ru/pages/p_21931.html
Сайт проекта — «Russian discussions Zone»
Движок для сайтов — «Tanat-Engine»
Дискуссионный лист — «Все для Всех о РС»
Дискуссионный лист — «File Info Masters»
Дискуссионный лист — «Напряги мозги»
Дискуссионный лист — «Ищем все…»
Дискуссионный лист — «Все обо Всем по Email»
Дискуссионный лист — «Внимание! Розыск…»
Дискуссионный лист — «Английский для Всех и каждого»
Группа стандартизации в Web — W3C.org
 

В избранное