Чат веб-разработчиков
Функции в PHP: урок с примерами

Функции в PHP

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

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

Например, нам нужен косинус числа 3.14. Легко! Для этого в PHP есть функция cos.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Есть очень много функций для работы со строками. Например, можно в строке заменить одни символы другими, для этого есть функция str_replace. Например, давайте в строке “abracadabra” заменим все буквы “a” на “o”.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Документация по стандартной библиотеке функций (SPL) доступна на официальном сайте - http://php.net/manual/ru/funcref.php. Большинство из них имеет описание на русском языке. Разумеется, все их запомнить невозможно, однако нужно уметь их находить. И это, как правило, не составляет труда. Например, если вбить в google “заменить символы в строке php” то в выдаче будет ссылка на официальную документацию, там и смотрите.

Поиск функций в PHP

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

Пользовательские функции: пишем свою первую функцию

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

Код доступен только после покупки курса PHP для начинающих.

У функции обязательно должно быть имя. У всех функций должны быть разные имена и имя вашей функции не может называться так же, как и встроенная в PHP функция. Аргументов может быть сколько угодно, в том числе и 0. Функция может что-то возвращать, для этого перед результатом пишется слово return. После него функция завершает свою работу. А может и не возвращать, а, например, изменять свои аргументы, или выводить информацию на экран. Именуются функции так же, как и переменные - camelCase`ом. Подробнее об этом я писал тут - https://webshake.ru/post/726. Именовать их нужно так же осмысленно – то что функция делает, то и нужно писать в имени.

Давайте рассмотрим пример создания простейшей функции в PHP. Пусть она принимает на вход два числа и возвращает их сумму.

Код доступен только после покупки курса PHP для начинающих.

Окей, функцию написали, теперь можно её вызвать и посмотреть на результат её работы.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Как мы видим, функция успешно отработала. Вот так, написав её лишь один раз мы можем передавать в неё разные аргументы, и получать разные значения. Использовать функцию можно только после кода её определения!

Области видимости

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

Код доступен только после покупки курса PHP для начинающих.

Данный код абсолютно рабочий. Здесь переменные $x и $y внутри функции getSum живут сами по себе, а переменные с такими же именами за пределами функции – отдельно, и они ничего друг о друге не знают. При вызове функции значение передаваемого аргумента будет скопировано в локальную переменную, а после выхода из функции это значение будет удалено. То есть здесь при вызове getSum мы просто копируем значения 3 и 5 в локальные переменные $x и $y. С этого момента внутри функции внешние переменные перестают существовать, и она знает только о своих переменных.

Параметры функции: передача аргументов по ссылке и по значению

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

Передача параметров по ссылке

Однако можно передать аргумент по ссылке. Делается это при помощи знака & перед именем аргумента.

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

То есть для значения переменной $a внутри функции появилось ещё одно имя - $x. Сейчас оба этих имени указывают на одно и то же значение. И если мы изменим значение переменной внутри функции, то оно изменится также и снаружи!

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

Код доступен только после покупки курса PHP для начинающих.

Будет выведено:

Код доступен только после покупки курса PHP для начинающих.

Здесь при вызове функции значение переменной $a было просто скопировано в локальную переменную $x. Внутри функции мы изменили $x, прибавив к нему число 5, а затем работа функции была завершена. Локальная переменная $x перестала существовать, а мы никак не повлияли на переменную $a.

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

Начинаем использовать тайп-хинтинг (type hinting) в PHP 7

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

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

После выполнения мы увидим следующее:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Теперь дробное число не будет приведено к целому, и мы получим другой результат:

Код доступен только после покупки курса PHP для начинающих.

В этом курсе мы всегда будем использовать указание типов. Это помогает писать более строгий код и позволяет допускать меньше ошибок. Посудите сами – если мы работаем с конкретным типом, мы более уверены в том, как будет работать тот или иной код.

Строгая типизация

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

Код доступен только после покупки курса PHP для начинающих.

Она указывается в начале PHP-файла. Наш код примет следующий вид:

Код доступен только после покупки курса PHP для начинающих.

При этом, если его сейчас запустить, то произойдёт ошибка с типом TypeError.
Ошибка при передаче некорректного типа

Как тут написано, первый аргумент, переданный в getSum() обязан быть типа integer, а передан с типом float. Это и есть строгая типизация в PHP. Использовать её в рамках данного курса мы не будем, да и в профессиональной разработке на PHP этот функционал пока не используют. Но не рассказать о ней я не мог, вполне возможно, что это могут спросить при собеседовании на работу. А сейчас убираем строку _declare(stricttypes=1); из нашего кода и идём дальше.

Функции без аргументов

Как я говорил, функция может вообще не иметь аргументов. Таковой, например, является стандартная функция rand() – она просто возвращает случайное число.

Давайте её попробуем в действии:

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Давайте запустим ещё раз этот же самый код:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Функция внутри функции

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

Код доступен только после покупки курса PHP для начинающих.

Здесь мы использовали функцию cos() из стандартной библиотеки внутри нашей собственной функции. А можно ли вызывать свои же функции из других своих функций? Да легко!

Код доступен только после покупки курса PHP для начинающих.

Здесь мы определили 2 разные функции, и во второй начали использовать первую. Разумеется, эти примеры довольно искусственны. И вы можете подумать, что использовать здесь функции излишне. Ведь можно же просто заменить этот код следующим выражением:

Код доступен только после покупки курса PHP для начинающих.

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Код данной функции можно упростить, так как если $x не больше $y, то мы в любом случае вернём $y. Поэтому можно убрать блок else:

Код доступен только после покупки курса PHP для начинающих.

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

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

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Выполнилось первое условие и вызвался return $x. Всё, до return $y дело не дошло.
Упрощение заключается в том, что чем меньше уровней вложенности в коде, тем проще его читать и понимать. Видите, как плотно пересекается весь изученный материал? В данном случае с темой условий в PHP.

Рекурсивные функции

Рекурсия в картинках

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

Например, нам нужно возвести число в степень. Предположим, у нас для этого есть определённая функция. Назовём её power. И пусть она принимает 2 аргумента:

  • число, которое нужно возвести;
  • степень, в которую нужно возвести.

То есть, для того, чтобы возвести число 2 в третью степень, нам нужно вызвать эту функцию следующим образом:

Код доступен только после покупки курса PHP для начинающих.

Согласитесь, что power(2, 3) равносильно 2 * power(2, 3 - 1). То есть мы можем умножить число, возводимое в степень, на вызов этой функции, и уменьшить при этом степень на единицу.

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

Получаем, что

Код доступен только после покупки курса PHP для начинающих.

Тогда для возведения 2 в степень 3 получим:

  1. power(2, 3) = 2 * power(2, 2)
  2. power(2, 2) = 2 * power(2, 1)
  3. power(2, 1) = 2

Число в первой степени равно самому этому числу. Здесь нам нужно остановиться.

Давайте реализуем это с помощью кода:

Код доступен только после покупки курса PHP для начинающих.

Да, функция будет вызывать сама себя. Таким образом, можно прийти к тому, что рекурсия полезна, когда вычисление функции можно свести к её более простому вызову, а его – ещё к более простому, и так далее, пока значение не станет очевидно. Чтобы понять, как всё работает пошагово, можно добавить вызов var_dump в начале функции и посмотреть, какие аргументы ей передаются на каждом из шагов.

Код доступен только после покупки курса PHP для начинающих.

Вывод получится следующим:

Код доступен только после покупки курса PHP для начинающих.

Таким образом, мы видим, что функция была вызвана трижды, и мы видим, какими были значения аргументов на каждом вызове. Надеюсь, тут всё понятно. Если же нет (а при изучении рекурсии это происходит довольно часто) – пишите ваши вопросы в комментариях, помогу. А ещё можете пошагово разбирать ход программы на листочке – тоже часто помогает.

Давайте для закрепления разберём ещё один пример с рекурсией. Например, мы будем передавать в функцию какое-то число $n, а она будет считать сумму всех чисел от единицы до этого числа. Назовём эту функцию getSumOfNumbersFromZero($n).

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

Код доступен только после покупки курса PHP для начинающих.

Как можно догадаться, этот вызов можно представить как

Код доступен только после покупки курса PHP для начинающих.

Или в общем случае

Код доступен только после покупки курса PHP для начинающих.

И так до тех пор, пока $n не станет равен 1.

Давайте реализуем это с помощью рекурсивной функции:

Код доступен только после покупки курса PHP для начинающих.

Запускаем:

Код доступен только после покупки курса PHP для начинающих.

Всё верно! Ну, хватит рекурсии, а то я уже слышу, как у вас закипают мозги.
Очень надеюсь, что вам понравился урок. Если это так – буду рад, если вы поделитесь им в социальных сетях или расскажете друзьям. Это лучшая поддержка проекта. Спасибо тем, кто это делает. Если у вас возникли какие-то вопросы или замечания – напишите об этом в комментариях. А сейчас – делаем домашнее задание, варианты ваших решений можете писать в комментариях, я их проверю и скажу, всё ли правильно. Всем пока!

Читайте также
Комментарии


omk
omk

В 3 задаче про факториал. (произведение целых чисел от ЕДИНИЦЫ до переданного)

ivashkevich
ivashkevich

Глаз-алмаз :)
Спасибо, исправил.

omk
omk

Решение последней задачи:

<?php
function numbers(int $x) {
    if ($x == 0) {
        echo $x;
        return 0;
    }
    $y = numbers($x - 1);
    echo ', ' . $x;
    return $y;
}

numbers(5);
ivashkevich
ivashkevich

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

<?php
function numbers(int $x) {
    if ($x == 0) {
        echo $x;
        return;
    }
    numbers($x - 1);
    echo ', ' . $x;
}

numbers(5);

По поводу бонуса написал на почту. Так держать!

vadymbilyi@gmail.com
vadymbilyi@gmail.com

А если переданное значение будет отрицательное. Например -10, тогда данная функция не сработает)

vadymbilyi@gmail.com
vadymbilyi@gmail.com

я сделал так. Учитывая что значение может быть также и отрицательное.

<?php
function integer0 (int $x)
 {
    if ($x == 0){
        return 0;
    }
    elseif ($x > 0){
        return integer0 ($x-1) . ' '. $x;
    }
    else {return $x . ' ' . integer0 ($x+1);}
 }

 $b = -25;
 echo integer0 ($b);
?>
ivashkevich
ivashkevich

отличный вариант!

PHPStudent
PHPStudent

Ребята, вы молодцы. Огромное Вам спасибо. Подскажите когда будет продолжение курса?

ivashkevich
ivashkevich

Привет, спасибо!
На выходных появится новый урок, будет интересная тема =)

PHPStudent
PHPStudent

Спасибо, жду с нетерпением! =)

PHPStudent
PHPStudent

Не могу понять, а как программа в последней задаче пробегает от 0 до нужного значения.

ivashkevich
ivashkevich

А на листочке уже пробовали пошагово разобрать?
Вот представьте:

  1. передали в функцию число 3
  2. сравнили с 0, условие выполнилось? Нет
  3. На следующей строке происходит вызов этой же функции, выполнение текущего вызова "останавливается" и ждёт пока выполнится следующий
  4. В функцию передалось число 2

Дойдите так до 0, и напишите, стало ли понятно.

PHPStudent
PHPStudent

Извините но не понимаю. Если я устанавливаю первоначальное значение числа например 5 то почему стартует с 0?

ivashkevich
ivashkevich

Потому что именно при нуле сработает первый echo. Затем мы выполним return и вернемся на уровень выше, где в функцию была передана единица. После вызова функции с передачей в неё нуля идет строка, которая выведет единицу. И так далее. Если сейчас нет понимания - ничего страшного. Тема рекурсии не сразу дается. Дождитесь следующего урока, там точно станет понятнее, обещаю =)

mik05bk@gmail.com
mik05bk@gmail.com

Я вот, что-то не понимаю. Почему в функцию передается 1, потом 2 и т.д.?

ivashkevich
ivashkevich

Нет, в функцию передаётся как раз в обратном порядке: 5, 4, 3...
Посмотрите следующий урок про отладку приложений, должно стать понятнее. Там тоже будет рекурсия.

Anril34
Anril34
<?php
function minimumNumber(float $x, float $y, float $z)
{
    if ($x > $y)
    {
        $minimum = $y;
    } else {
        $minimum = $x;
    }
    if ($minimum > $z)
    {
        return $z;
    } else {
        return $minimum;
    }
}
$x = 9;
$y = 5.1;
$z = 99.3;
echo 'Минимальное число: ' . minimumNumber($x, $y, $z);
ivashkevich
ivashkevich

Всё верно =)

humanidis@gmail.com
humanidis@gmail.com

Какой код корректней использовать для решения этой задачи? Вышеуказанный или

<?php
    function getMin(float $x, float $y, float $z){
        if ($x < $y && $x < $z){
            return $x;
        }else if ($y < $z){
            return $y;
        }else{
            return $z;
        }
    }

    $a = 7;
    $b = 10;
    $c = 22;

    echo getMin($a, $b, $c);
?>
ivashkevich
ivashkevich

Я бы выбрал Ваш вариант, но тот тоже вполне имеет право на существование. elseif пишется слитно.

Verbum
Verbum

Catchable fatal error: Argument 1 passed to getMin() must be an instance of float, integer given, called

spacepancake
spacepancake

Не могу понять как работает это выражение :( $x * power($x, $n - 1), т.е я понимаю, что под этим скрывается 2 * power(2, 2), но как происходит умножения двойки на функцию с двумя аргументами? Как двойка выбирает на какой аргумент умножать? Действительно мозги закипают!)

ivashkevich
ivashkevich

Посмотрите следующий урок, должно стать понятнее :)

spacepancake
spacepancake

Благодарю! Кстати отличный курс, прошёл на одном дыхании. THUMBS UP

ivashkevich
ivashkevich

Спасибо! Но это только треть, от того что я запланировал :)

phenomg
phenomg

1)

function minimal($x, $y, $z) {
   if ($x > $y) {
     if($y > $z) { 
       return $z;
     }
     else return $y;
   }
   elseif ($x > $z) {
     return $z;
   }
   else {
     return $x;
   }
} 

$a = (float) 7.5;
$b = (float) 5.2;
$c = (float) 21.0;

echo "Минимальное число: " . minimal($a, $b, $c);
ivashkevich
ivashkevich

А зачем вы сделали приведение к float при определении переменных? И нужно добавить приведение к типу в аргументах функции. А в целом - алгоритм верный.

phenomg
phenomg

2)

function x2(&$x, &$y) {
    $x *= 2;
    $y *= 2;
} 

$a = 5;
$b = 20;

echo "Первое число: $a. Второе число: $b. <br/>";

x2($a, $b);

echo "Первое число после выполнения функции: $a. Второе число после выполнения функции: $b. <br/>";
ivashkevich
ivashkevich

Всё хорошо, только добавьте типы для аргументов функции =)

kolesnikow_y@mail.ru
kolesnikow_y@mail.ru
function getMin(float $x, float $y, float $z) {
    if(($z > $x)&&($x < $y)){//если min x
        return $x;
    } elseif(($z > $y)&&($y < $x)) {//если min y
        return $y;
    }
    return $z;
}
trialex3
trialex3

ПО поводу последней задачи так и не разобрался. Вижу решение, но как это все работает вместе - хз. Будем думать.

vasyaproject
vasyaproject

А я первую функцию с одной & писал - это неверно?

function minArg(float $x, float $y, float $z) 
{
    if ($x < $y & $x < $z){
        return $x;
    } elseif ($y < $x & $y < $z){
        return $y;
    } else {
        return $z;
    }
}
echo minArg(6.6, 4.9, 4.5);
ivashkevich
ivashkevich

Конечно, неверно. Это совершенно другой оператор.

Tays
Tays

По поводу последнего задания. Почему уменьшаем на единицу, а выводится с увеличением?

function numS(int $a){
    if($a == 0){
        echo $a;
                echo '<br>';
                return 0;
    } 
        {
        $n = numS($a - 1);
                echo $a;
        echo '<br>';
        return $n;
} 
}
numS(7);
ivashkevich
ivashkevich

А вы запустите код в отладчике, и всё поймёте =) Вы же смотрели урок про отладку с помощью XDebug?
P.S. код после блока if {...} не надо заключать в фигурные скобки. Это бессмысленно. Просто продолжайте писать функцию дальше без скобок.

WarLikeLaux
WarLikeLaux

Первое задание
enter image description here

ivashkevich
ivashkevich

Предпочтительнее - оформлять код с помощью markdown-разметки, вот так:
```
код
```

Как и у большинства начинающих - проблема с отступами и оформлением. Почитайте про Reformat Code в PhpStorm. Закрывающий тег в конце не нужен.
Задание сделано неверно, перечитайте внимательно.

WarLikeLaux
WarLikeLaux

Второе задание
enter image description here

ivashkevich
ivashkevich

Конкатенация строк происходит с помощью точки:

echo $x . ' ' . $y . ' ' . $z;
WarLikeLaux
WarLikeLaux

Да, точно, забыл, не привык еще) Спасибо!)

WarLikeLaux
WarLikeLaux

Третье задание
enter image description here

ivashkevich
ivashkevich

Тут всё хорошо.

WarLikeLaux
WarLikeLaux

Четвертое задание
enter image description here

ivashkevich
ivashkevich

Тут тоже всё верно)

serb2017
serb2017

Вариант для последнего задания. Выводит числа от m до n.

function Nature($m, $n)
{
    echo $m++, ',';
    if ($m == $n + 1) return;
    return Nature($m, $n);
}

$n = 10;
$m = 0;
Nature($m, $n);
ivashkevich
ivashkevich

Конкатенация строк происходит с помощью точки:

echo $x . ' ' . $y . ' ' . $z;

Имена функций начинаются с маленькой буквы.

serb2017
serb2017
function getMin3(float $x1, float $x2, float $x3)
{
    if ($x1 < $x2 && $x1 < $x3) {
        return $x1;
    }
    if ($x2 < $x3) {
        return $x2;
    }
    return $x3;
}

$x1 = 3.25;
$x2 = 3.2;
$x3 = 3.3;
echo "минимально число из   $x1, $x2, $x3 ". '<br>'. getMin3($x1, $x2, $x3);
Lungren
Lungren
function getMinn($x, $y, $z)
{
    if ($x < $y) {
        return $x;
    } elseif ($y < $z) {
        return $y;
    } else {
        return $z;
    }
}

$a = 6;
$b = 3;
$c = 1;
echo 'Наименьшее число ' . getMinn($a, $b, $c);
ivashkevich
ivashkevich

Ошибка. Если я передам числа 2, 3, 1, то вернется число 2.

1nSide
1nSide

1 Задача

<?php

function getMin ($x, $y, $z) {
    if ($x < $y && $x < $z) {
        return $x;
    } elseif ($y < $x && $y < $z) {
        return $y;
    } else return  $z;
}

$a = 6;
$b = 10;
$c = 8;

echo 'Наименьшее число = ' . getMin($a, $b, $c);
ivashkevich
ivashkevich

Всегда оформляйте код после if и else в блоки с помощью фигурных скобок.

else {
    ...
}
1nSide
1nSide

2 Задача

<?php

function multiply2(&$x, &$y){
    $x = $x * 2;
    $y = $y * 2;
}

$a = 4;
$b = 10;

multiply2($a, $b);
echo 'Первое число умноженое на 2 = ' . $a;
echo '<br>';
echo 'Второе число умноженое на 2 = ' . $b;
ivashkevich
ivashkevich

Тут всё гуд)

1nSide
1nSide

3 Задача

<?php
function factorialOfNumber ($number){
    var_dump($number);
    echo '<br>'.'<br>';
    if($number == 0){ // если равно 0 то программа завершает рекурсию
        return 1;
    }
    return $number * factorialOfNumber($number-1); // число умножаем на число, после прохождения условия вычитается один 
}

$a = 5;

echo 'Факториал числа ' . $a .' = '. factorialOfNumber($a);
ivashkevich
ivashkevich

У функции открывающая фигурная скобка находится на следующей строке. В остальном - норм.

1nSide
1nSide

2 раза пересматривал видео урок чтобы понять=)
В комментарии не смотрел, крутые курсы все достаточно понятно, было бы круто если бы задач было побольше.

4 Задача

<?php
function getSumOfNumbersFromZero($nmin,$nmax)
{
    echo 'Число: ' . $nmin . '<br>';

    //если минимально значение не равно максимальному продолжается проверка условия   
    if($nmin==$nmax){
        return;
    }

    // прибавляем в рекурсии +1 к минимальному значению
    // пока минимальное значение не станет равным максимальному и условие if выполнится
    return getSumOfNumbersFromZero($nmin+1,$nmax);
}

echo getSumOfNumbersFromZero(0,10);
ivashkevich
ivashkevich

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

function getSumOfNumbersFromZero(int $nmin, int $nmax)

Будет плюсом при трудоустройстве, если вы будете знать возможности PHP7.

1nSide
1nSide

Думал что язык сам подбирает тип переменных поэтому не считал нужным писать их в аргумент функции)

ivashkevich
ivashkevich

Он их не подбирает. Если их не указать, то они придут как есть. Это плохо, когда в аргументах может прийти что угодно. Это приводит к большему числу ошибок.

hkam11
hkam11

Добрый день. Подскажите, пожалуйста, при рекурсии получается, что функция преобразует запись 2^3 в 2x2^2, а потом в 2x2x2^1?

ivashkevich
ivashkevich

Добрый. Да, вроде того. Посмотрите видео в следующем уроке, после него точно поймёте.

hkam11
hkam11

Задание №4.

<?php
function getNumbers (int $n) {
    if ($n==0) {
        return $n;

    } else {
        echo $n, ' ';
        return getNumbers($n-1);
    }
}
echo getNumbers(6);

Не могу понять, как сделать, чтобы отсчет начинался с 0, а не с заданного числа

ivashkevich
ivashkevich

Подсмотрите в других комментариях, не страшно :)

FantaZ
FantaZ

По поводу последней задачи - не уверен, но мне кажется самый лаконичный вариант:

<?php
declare(strict_types=1);

function numbers(int $num) {
    if ($num > 0) {
        numbers($num - 1);
    }

    echo $num;
    return;
}

numbers(5);
ivashkevich
ivashkevich

Отлично! Но return в конце не имеет смысла. Уберите, пока никто не увидел =)

vityan97@gmail.com
vityan97@gmail.com
<?php
//Напишите функцию, которая будет принимать на вход 3 аргумента с типом float и возвращать минимальное значение.
//Напишите функцию, которая принимает на вход два аргумента по ссылкам и умножает каждый из них на 2.
//Напишите функцию, считающую факториал числа (произведение целых чисел от единицы до переданного). Ну разумеется, тут никуда без рекурсии =)
//Напишите функцию, которая будет выводить на экран целые числа от 0 до переданного значения. И да, тут тоже не обойтись без рекурсии, это задание
// повышенной сложности. Кто справится и первым напишет верное решение в комментах – тот красавчик и получит от проекта небольшой бонус.
//__________________________________________________________________
echo '<b>1-е задание</b></br>';
function minimumNumber(float $x, float $y, float $z)
{
    if ($x > $y) {
        $minimum = $y;
    } else
    {
        $minimum = $x;
    }
    if ($minimum > $z)
    {
        return $z;
    }   else
    {
        return $minimum;
    }
}
$a = 1.27;
$b = 1.26;
$c = 1.25;
echo 'Минимальное число будет равно '.minimumNumber($a, $b, $c);
echo "</br>";
//_______________________________________________________________
echo '<b>2-е задание</b></br>';
function multiplication(&$a)
{
    $a = $a*2;
}
$x = 100;
$y = 200;

multiplication($x);
echo "x = $x <br/>";
multiplication($y);
echo "y = $y </br>";
//___________________________________________________________________
echo '<b>3-е задание</b> </br>';
function faktorialOfNumbers(int $x)
{
    echo "$x *";
    if ($x <= 1)
    {
        return 1;
    }
    return $x * faktorialOfNumbers($x-1);
}
$a = 5;
echo 'Факториал числа '.$a.' = '.faktorialOfNumbers($a).'</br>';

//__________________________________________________________________
echo '<b>4-е задание</b></br>';
function getMaxNumberFromZero(int $min, int $max)
{
    echo "Число $min</br>";
    if ($min == $max)
    {
        return ;
    }
    return getMaxNumberFromZero($min + 1, $max);
}
$min = -10;
$max = 10;
echo 'Вывод чисел от '.$min.' до '.$max.'</br>';
echo getMaxNumberFromZero($min, $max);
ivashkevich
ivashkevich

Отлично! Из замечаний:

  1. не нужно в функции делать вывод чего-либо, она должна только вернуть число.
  2. всё хорошо, но return на последней строке функции необязателен, достаточно просто вызывать её, ничего не возвращая.
nemo.dont@gmail.com
nemo.dont@gmail.com

C последней функцией повышенной сложности не справилась (( Рассмотрела, как решили другие, все вроде бы понятно, но вот сама не дошла до этого, увы.
Фун №1

<?php
function minNumFrom (float $a, float $b, float $c)
{ if ($a<$b && $a<$c)
   {return $a;}

   elseif ($b<$a && $b<$c)
   {return $b;}

    return $c;
}

$a=25.7;
$b=808.1;
$c=10.8;

    echo 'Минимальное число ' . minNumFrom ($a,$b,$c);
?>

Фун №2

<?php
function multi2(int &$x, int &$y)
{
    $x = $x * 2;
    $y = $y * 2;
}

$a = 9;
$b=467;

multi2($a, $b);

echo 'Первое число, умноженное на 2 равно ' . $a . '<br> ' . ' Второе число, умноженное на 2 равно ' . $b;

?>

Фун №3

<?php

function fac($a)
{
    if ($a>2)
    {return  $a * fac($a-1);}

    return $a;

}

$a=3;

echo 'Факториал числа ' . $a . ' равен ' . fac($a);

?>
Fox-24
Fox-24

Добрый день.

Начиная с PHP 5.3.0, вы можете получить предупреждение о том, что передача переменной по ссылке устарела, если используете & в foo(&$a);. Начиная с PHP 5.4.0 передача переменной по ссылке стала невозможна, поэтому использование этого приема приведет к фатальной ошибке.

ivashkevich
ivashkevich

Добрый день, это про то, что нельзя при вызове функции передавать ссылку:

$x = func(&$y);

Но при определении функции это можно делать:

function func (&$x)
{
    ...
}
Fox-24
Fox-24

Благодарю за урок!

<?php

// Найти минимальное число из трех
function minNum($a, $b, $c)
{
    if ($a < $b) { // Сравниваем первые два числа
        $num = $a; // Если а меньше b, записываем число в переменную num
    } else {
        $num = $b; // Если b меньше a, записываем число в переменную num
    }

    if ($num < $c) // Наименьшее число из первого сравнения сравниваем с третьим числом
        return $num;
    else {
        return $c;
    }
}

$a = 2;
$b = 6556;
$c = 55;

echo minNum($a, $b, $c); // ывод

// Произведение целых чисел от единицы до переданного
function fuctNum($a)
{

    if ($a == 1) {   // Если переданное число больше 1, вернуть значение
        return $a;
    } else {
        return $a * fuctNum($a - 1); // Умножение
    }

}

$a = 5;

echo fuctNum($a);

// Вывод на экран целых чисел от 0 до переданного значения
function funInter($a)
{

    if ($a >= 0) {
        funInter($a - 1); // Уменьшаем заданное число на единицу
        echo $a . '</br>';   // И выводим каждое новое число из предыдущей операции с новой строки

    } else {
        return;
    }

}

funInter(15);
ivashkevich
ivashkevich
function funInter($a)
{

    if ($a >= 0) {
        funInter($a - 1); // Уменьшаем заданное число на единицу
        echo $a . '</br>';   // И выводим каждое новое число из предыдущей операции с новой строки

    } else {
        return;
    }
}

Изменится ли что-то, если убрать вот этот кусок:

    else {
        return;
    }
Fox-24
Fox-24

ничего не изменится)

ivashkevich
ivashkevich

Правильно, значит этот кусок кода убираем, и код становится проще :)

ivashkevich
ivashkevich

Не забывайте указывать типы у аргументов функций!

Fox-24
Fox-24

Да, спасибо, я их специально не указываю т.к.:

Scalar type hints are available in PHP 7

А у меня в проекте 5.4.

Но я это учитываю.

ivashkevich
ivashkevich

Советую Вам всё же перейти на версию 7, 5.4 - старенькая. На работе будут требовать 7, и будет круто, если Вы уже её использовали.

Fox-24
Fox-24

Да, я конечно же перейду, у меня просто есть проект в котором сейчас 5.4 и пока удобнее оставаться на ней. Но преимущества 7-ки я оценил.

honor
honor
function lowSum(float $a, float $b, float $c){
                        if ($a > $b){
                            return $a;
                        }elseif($a > $c){
                            return $a;
                        }elseif($b > $a){
                            return $b;
                        }else{
                            return $c;
                        }
                    }
                    echo 'наибольшее число'.lowSum(7.2, 6.1, 2.3);
ivashkevich
ivashkevich

Это к какому заданию домашка?

AxLT
AxLT

Первое:

function getMin(float $x, float $y, float $z){
    if ($x < $y){
        if ($x < $z){
            return $x;
        }
    }
    elseif($y < $z){
        return $y;
    }
    return $z;
}
echo 'Наименьшее число float из трех: ' . getMin(1.3, 2.1, 3.2)

Второе:

function doubleSomeNumber(int &$x, int &$y){
    $x *= 2;
    $y *= 2;
    return;
}
$x = 5;
$y = 3;
echo doubleSomeNumber($x,$y);

Третье

//Факториал числа
function factorialOfNumber(int $n){    
    if ($n == 1){
        return $n;
    }
    return $n * factorialOfNumber($n-1);
}
echo factorialOfNumber(3)

Все ли верно или что то лучше написать иначе?
4 глянул в комментах, не очень понятно почему выводит на экран с нуля а не наоборот =)

ivashkevich
ivashkevich

Всё норм, но непонятно зачем во втором вы возвращаете строку из двух склеенных чисел. По поводу четвертого - переходите к следующему уроку, будет понятнее.

AxLT
AxLT

Подправил чуток второе. Да с отладкой, четвертое стало понятнее, но еще надо с рекурсией разбираться

<?php

function doubleSomeNumber(int &$inputNumFirst, int &$inputNumSec)
{
    $inputNumFirst *= 2;
    $inputNumSec *= 2;
}

$someNumFirst = 5;
$someNumSec = 3;
doubleSomeNumber($someNumFirst,$someNumSec);
echo 'Первое произведение равно: ' . $someNumFirst . '<br>Второе произведение равно: ' . $someNumSec;
ivashkevich
ivashkevich

Окей, ничего страшного, рекурсия многим непонятна на первых порах.

ArtemijeKA
ArtemijeKA

1:

function smallOfThreeArg(float $a, float $b, float $c)
{
    if ($a < $b) {
        if ($a < $c) {
            return $a;
        }
        return $c;
    }
    return $b;
}
echo smallOfThreeArg(5.2, 8.6, 3.6);

2:

$a = 4;
$b = 3;
function twoArgMultiplyBy2(&$a, &$b)
{
    $a = $a * 2;
    $b = $b * 2;
}
twoArgMultiplyBy2($a, $b);
var_dump($a, $b);

3:

function factorialBy1ToArg($arg) // 4 3 2 1 0
{
    if ($arg >= 1) {
        return $arg + factorialBy1ToArg($arg - 1); // 5 6 10
    }
}
echo factorialBy1ToArg(4); // 10

4.0:

Здесь обошелся без рекурсии и более понятно.

function echoNumberBy0ToArg_v1($arg)
{
    for ($i = 0; $arg >= $i; $i++) {
        echo $i . '<br />';
    }
}
echoNumberBy0ToArg_v1(2);

4.1:

Здесь не поянтно почему cперва 0, а не 1 ведь arg-(arg-1)=1?

function echoNumberBy0ToArg_v2($arg) // 2
{
    if ($arg >= 0) { // 2
        echo $arg - echoNumberBy0ToArg_v2($arg - 1) . '<br />'; // 0 1 2 
    }
}
echoNumberBy0ToArg_v2(2);
ivashkevich
ivashkevich

Нужно указывать return-type для функции, через двоеточие, как в уроке.

3 - а где обработка случая, когда не больше единицы? Вам повезло, что null преобразовался в 0. Факториал - это произведение а не сумма.

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

ArtemijeKA
ArtemijeKA

Благодарю за замечания!
3. Так будет корректно? Или не очень?

function factorialBy1ToArg($arg) // 4 3 2 6 24 120
{
    if ($arg >= 1) {
        if ($arg > 2) { // 4 3 2
            $arg *= factorialBy1ToArg($arg - 1); // 12 6
        }
        return $arg; // 2 6 24 120
    } else {
        echo 'Нельзя вычислить факториал от числа меньше 1-ого';
    }
}
echo factorialBy1ToArg(5); // 120
ivashkevich
ivashkevich

Привет, не очень, потому что:

  1. факториал нуля равен единице
  2. где работа над замечаниями, что я писал выше? Где типы аргументов, где тип возвращаемого значения?
  3. что за название? Почему не просто factorial? =)
Benya
Benya

3 задание

function fact(int $x)
{
    if ($x == 1) {
        return $x;
    }
    return $x * fact($x-1);
}

echo "rezult---" . fact(5);
ivashkevich
ivashkevich

Отлично =)

ilyaOrlov
ilyaOrlov

Верно ли выполнение третьего задания?

function Factorial (int $a)
{
    if ($a == 0) {
        return $a + 1;
    } elseif ($a == 1) {
        return $a;
    }
    return $a * getFactorial ($a - 1);
}

echo getFactorial (6);
ivashkevich
ivashkevich

ну не работает же, ёлки-палки - функция называется Factorial (что некорректно - все имена функций должны начинаться с маленькой буквы), а вызывается и в теле, и снаружи getFactorial.

после блока с return необязательно ставить elseif - если верхнее условие выполнится, то функция не пойдет дальше, поэтому лучше просто if c новой строки:

function factorial (int $a): int
{
    if ($a === 0) {
        return $a + 1;
    }

    if ($a === 1) {
        return $a;
    }

    return $a * factorial($a - 1);
}
dsokol-ok
dsokol-ok

Спасибо за урок!

function getIntFromZero ($a)
{
   if ($a >= 0) {
       if ($a == 0) {
           echo $a . '<br>';
           return;
       }
       echo $a . '<br>' . getIntFromZero($a - 1);
       return;
   }
   echo 'Введите неотрицательное число!<br>';
}
$a = 47;
getIntFromZero($a);