Поиск

Переменные и функции

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

Область действия переменных и глобальные переменные

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

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

function FunctionName (SArgument) {
global $Variable;
statement(s);

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

Мы затронули эту тему, потому что на самом деле необязательно применять разные имена. Для удобства можно использовать одно и то же имя в строке функции и в строке вызова (тогда легко запомнить передаваемые аргументы), но помните, что это разные переменные. То, что происходит со значением переменной внутри функции, остается в функции. И наоборот: изменения пе ременной вне функции не действуют на переменную с тем же именем внутри функции. Но, если вы сделали переменную глобальной с помощью инструкции global, она становится одной и той же переменной и внутри, и снаружи. Использование инструкции global

  1. Откройте файл numbers.php в текстовом редакторе (листинг 9.6).
  2. Уберите аргументы $Price и $TaxRate из функции CalculateTotal, что бы строка 2 выглядела так:
  3. function CalculateTotal ($HowMany, $SavingsT {

    Переменные $Price и $TaxRate будут введены в функцию как $Cost и $Тах с помощью инструкции global, поэтому нет необходимости использовать их как аргументы.

  4. Добавьте две глобальные инструкции.
  5. global $Cost;
    global $Tax;

    Они «Прикажут» функции использовать переменные $Cost и $Тах, которые уже существуют вне ее.

  6. Отредактируйте оставшуюся часть функции, заменив переменную $Price на $Cost, $TaxRate на $Тах, a $TheCost на $TotalCost.
  7. $Тах++; // $Тах составляет 1.06. *
    $TotalCost ~ ($Cost * $HowMany);
    if ( ($TotalCost < 50) AND ($Savings) ) {
    print ("Your $$Savings will not apply because
    —the total value of the sale is under !\n<P>");
    } if ($TotalCost >= 50) {
    $TotalCost = $TotalCost $Savings;
    }.
    $TotalCost = $TotalCost * $Tax;
    return $TotalCost;

    Так как теперь функцией используются разные имена переменных, необхо димо соответствующим образом изменить вычисления. Чтобы лучше понять область действия переменной, мы поменяли также переменную $TheCost на $TotalCost. Запомните, что $TotalCost в функции это совсем не та перемен ная, как переменная с тем же именем, но находящаяся вне функции

  8. Ниже в сценарии, после строки $Тах = 0.06; (строка 29), распечатайте текущее значение переменной. Оно будет меняться в ходе дальнейшего выполнения сценария.
  9. print ("The tax value is currently $$Tax .\n<P>");

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

  10. Измените строку вызова функции CalculateTotal ( ) , чтобы переменные
  11. $Тах и $Cost больше не передавались как аргументы.
    $TotalCost = CalculateTotal ($Quantity, $Discount);

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

  12. Еще раз распечатайте значение переменной $Тах.
  13. print ("After calling the function, the tax value
    is now $$Tax .\n<P>");

    Если бы не было инструкции global, то значения, распечатанные здесь и выше, были бы одинаковыми. Но, поскольку глобальная переменная $Тах была модифицирована в функции, распечатанные значения будут разными.

  14. Сохраните сценарий (листинг 9.7), загрузите его на сервер и протестируй те в браузере (рис. 9.5). Не забудьте отправить в сценарий значение коли чества (и значение скидки, если захотите), добавив его к адресу URL или через HTMLформу.

Листинг 9.7 т Так как функции CalculateTotal требуются значения пере менных $Cost и $Тах, они легко могут быть включены с помощью инструкции global. Помните, переменные больше нельзя передавать как аргументы это может запутать программиста и вызвать определенные ошибки в работе при ложения.

1 <?php
2 function CalculateTotal ($HowMany, $Savings) {
3 global $Cost;
4 global $Tax;
5 $Tax++; // $Tax составляет 1.06.
6 $TotalCost = ($Cost * $HowMany);
7 if ( ($TotalCost < 50) AND ($Savings) ) {
8 print ("Your $$Savings will not apply because the total value
of the sale is under ! \n<P>" ) ;
9 }
10 if ($TotalCost >= 50) {
11 $TotalCost = $TotalCost $Savings;
12 } . .
13 $TotalCost = $TotalCost * $Tax;
14 return $TotalCost;
15 } // Конец функции CalculateTotal.
16 function CalculatePayments ($Amount, $NumberPayments) {
17 $ Payments = round ($ Amount , 2) / $Number Payments;
18 $Payraents = sprintf ("%01.2f", $Payrnents);
/19 return $Payments;
20 } // Конец функции CalculatePayments.
21 ?> •
22 <HTML>
23 <HEAD>
24 <TITLE>Calculation Functions</TITLE>
25 </HEAD>
26 <BODY>
27 <?php
28 $Cost = 20.00;
29 $Tax = 0.06;
30 print ("The tax value IB currently $$Tax . \n<P>n);
31 if ($Quantity) {
32 $Quantity = abs ($Quantifey) ;
33 $Discount = abs($Discount) ;
34 $TotalCost = CalculateTotal ($Quantity, $Discount);
35 print ("After calling the function, the tax value is now $$Tax
36 // Печать результатов.
37 print ("You requested to purchase $Quantity widget (s) at $$Cost
each.\n<P>") ;
38 print ("The total with tax, minus your $$Discount, comes to $");
39 printf ("%01.2f", $TotalCost);
40 print (".\n<P>You may purchase the widget (s) in 12 monthly
installments of $");
41 print (CalculatePayments ($TotalCost, "12"));
42 print (" each.\n<P>") ;
43 } else {
44 print ("Please make sure that you have entered both a quantity
and an applicable discount and then resubmit.\n");
45 }
46 ?>
47 </BODY>
48 </HTML>
Задание значений аргументов по умолчанию

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

В качестве примера возьмем функцию CalculatePayments ( ) (листинг 9.7). Как количество ежемесячных платежей можно задать значение 12 по умолча нию, создав функцию и используя следующий синтаксис:

function CalculatePayments ($Amount, $NumberPayments = "12") {

Вызов функции с помощью кода CalculatePayments ($Amounts) ; не приве дет ни к каким проблемам, а строка CalculatePayments ($Amounts, " 2 4 " ) ; за менит значение переменной $NumberPayments со значения по умолчанию, рав ного 12, на фактическое, равное 24.

Значение аргумента по умолчанию используется, если логика программы подразумевает определенное значение, которое все же можно изменить. Одна ко необходимо помнить, что аргументы по умолчанию должны всегда быть написаны после других стандартных аргументов (то есть не имеющих значения по умолчанию). Это делается потому, что значения аргументам в РНР присваи ваются напрямую в порядке их получения из строки вызова. Следовательно, невозможно опустить значение для первого аргумента и задать значение вто рому (это показывает, что вы послали одно значение, которое будет автомати чески присвоено первому аргументу, а не второму). Рассмотрим пример того, как не надо вызывать функцию. Допустим, функция определена следующим образом:

function CalculateTotal ($HowMany, $Price = "20.00", $TaxRate = "0.06") {

Мы вызовем ее такой строкой:

CalculateTotal (3, "0.07");

При этом мы собираемся задать аргументу $HowMany значение 3, желая оста вить показатель $ Price равным 20.00 и надеясь изменить величину $TaxRate на 0.07. Увы, у нас ничего не выйдет. Переменная $HowMany действительно по лучит значение 3, $Price 0.07, a $TaxRate останется равным 0.06. Помнится, мы хотели получить несколько иной результат. Добиться нужного результата можно следующим образом:

CalculateTotal (3, "20.00", "0.07");

Теперь в свете того, что мы узнали о задании значений аргументов по умол чанию, изменим страницу numbers.php (листинг 9.7).

Написание функции, которая использует значения по умолчанию

  1. Откройте файл numbers.php в текстовом редакторе (листинг 9.7).
  2. Теперь добавьте значение по умолчанию цеременной $ Savings в функцию CalculateTotal ( ) .
  3. function CalculateTotal ($HowMany, SSavings = "0") {
  4. Мы указали 0 как значение по умолчанию переменной $Savings. Если ни какой аргумент не будет передан в функцию, это будет значить, что скид ка не применяется. Отредактируйте вторую функцию, задав 12 как значе ние по умолчанию аргумента $NumberPayments.
  5. function CalculatePayments ($Amount, $NumberPayments = "12") {

    Если в функцию CalculatePayments ((отправлено два аргумента, вместо значения по умолчанию аргумент $NumberPayments получит второе значение.

  6. Сотрите две строки в основном теле сценария* которые распечатывают значение $Тах. Они больше не нужны.
  7. Измените вызов функции CalculatePayments ( ) так, чтобы аргументы для количества платежей больше не посылались.
  8. print (CalculatePayments($TotalCost));

    Вызов функции CalculatePayments О передает теперь только значение $TotalCost как аргумент, так как $NumberPayments имеет значение по умолчанию. Здесь можно было бы передать и значение $NumberPayments, если бы вы реши ли использовать другое количество, ежемесячных платежей.

  9. Сохраните сценарий (листинг 9.8), загрузите его на сервер и протестируй те в браузере (рис. 9.6). Не забудьте послать в сценарий значение количе ства (и значение скидки, если захотите), добавив его к адресу URL или через HTMLформу.
  10. Листинг 9.8 т Обновленная страница numbers.php. Задание значения по умолчанию в функции делает аргумент опциональным.

    1 <?php
    2 function CalculateTotal ($HowMany, $Savinge = "0") {
    3 global $Cost;
    .4 global $Tax;
    5 $Tax++; // $Tax составляет 1.06.
    6 $TotalCost = ($Cost * $HowMany);
    7 if ( ($TotalCost < 50) AND ($Savings) ) {
    8 print ("Your $$Savings will not apply because the total
    value of the sale is under !\n<P>");
    9 ' }
    10 if ($TotalCost >= 50) {
    11 $TotalCost = $TotalCost $Savings;
    12 }
    13 $TotalCost = $TotalCost * $Tax;
    14 return $TotalCost;
    15 } // Конец функции CalculateTotal.
    16 function CalculatePayments ($Amount, $NumberPayments = "12") {
    17 $Payments = round($Amount, 2) / $NumberPayments;
    18 $Payments = sprintf ("%01.2f", $Payments);
    19 return $Payments;
    20 } // Конец функции CalculatePayments.
    21 ?>
    22 <HTML>
    23 <HEAD>
    24 <TITLE>Calculation Functions</TITLE>
    25 </HEAD>
    26 <BODY>
    27 <?php
    28 $Cost = 20.00;
    29 $Tax =0.06;
    30 if ($Quantity) {
    31 $Quantity = abs($Quantity);
    32 $Discount = abs($Discount);
    33 $TotalCost = CalculateTotal ($Quantity, $Discount);
    34 // Печать результатов.
    35 print ("You requested to purchase SQuantity widget(s) at $$Cost
    each.\n<P>");
    36 print ("The total with tax, minus your $$Discount, comes to $");
    37 printf ("%01.2f", $TotalCost);
    38, print (".\n<P>You may purchase the widget(s) in 12 monthly
    installments of $");
    39 print (CalculatePayments($TotalCost));
    40 print (" each.\n<P>");
    41 } else {
    42 print ('"Please make sure that you have entered both a quantity
    and an applicable discount and then resubmit.\n");
    43 }
    44 ?>
    45 </BODY>
    46 </HTML>
    Во всех примерах этой главы мы посылаем аргументы в функции по значению. Из этого следует, что в функцию посылается копия значения переменной, а не сама переменная. Можно также передавать аргументы по ссылке, что позволяет моди фицировать переменную в функции, не делая ее глобальной, но это слишком сложная тема, которая не рассматривается в данной книге. Некоторая дополни тельная информация содержится в приложении С.
    В разных школах используются разные соглашения по именам аргументов функ ций. С одной стороны, применение в функции того же имени, что и имя перемен ной вне функции, позволяет легче запомнить, как соотносятся переменные. С дру гой стороны, использование тех же имен аргументов в функциях может сделать их излишне привязанными к остальному скрипту. Допустим и гибридный метод, при котором в начало имен функций просто добавляется строчная буква f, например $fHowMany и SfTaxRate. Некоторые программисты обозначают глобальные пе ременные как $gVariable. Присваивая имена, важно оставаться последователь ным и не отступать от принятой ранее логики.