За последние 24 часа нас посетили 18065 программистов и 1599 роботов. Сейчас ищут 880 программистов ...

Функции и переменные в них

Тема в разделе "PHP для новичков", создана пользователем Netopyr, 31 дек 2016.

  1. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    Запутался с областью видимости переменной. Функция в функции, плюс записывается новая переменная. Написал простой код, нужно чтобы выводилось string1, string1, string2, string2. Пробовал с глобальными переменными, но это не получается. Понимаю, что скорее всего глупейшее непонимание, но курение мануала или гугла совсем не помогает.
    PHP:
    1. function test1 () {
    2.     $a = "string1";
    3.     echo $a;
    4.     echo "<br />";
    5. }
    6. function test2 () {
    7.     $a = "string2";
    8.     test1 ();
    9. }
    10. test1 ();
    11. test1 ();
    12. test2 ();
    13. test2 ();
     
  2. SamyRed

    SamyRed Старожил

    С нами с:
    23 июл 2015
    Сообщения:
    1.196
    Симпатии:
    111
    Адрес:
    Украина
    Смотрим: test1 выводит string1:
    string1
    string1
    Далее: test2 выводит string1, поскольку она вызывает test1(), а она перезаписывает переменную $a, получается что выведется 4 раза string1
    --- Добавлено ---
    Если надо чтоб так вывелось - можно передавать параметр в функцию:
    function ($a) {
    echo $a;
    }
    test1("string1");
    test1("string1");
    test1("string2");
    test1("string2");
     
  3. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Тут нет функции в функции. Есть вызов первой функции внутри второй. Вызов, а не объявление. Новая переменная не записывается. Переменная $a из первой функции никак не связана с переменной $a во второй функции.

    1. test1 ();
    2. test1 ();
    3. test2 ();
    4. test2 ();
    Вы дважды вызываете первую функцию, а потом дважды вызываете ее из второй. При этом во второй создается своя переменная, которая не передается в первую. Попробуйте вот так:

    PHP:
    1. function test1 ($a = "string1") {  
    2.     echo $a;
    3.     echo "<br />";
    4. }
    5. function test2 () {
    6.     test1 ("string2");
    7. }
    8. test1 ();
    9. test1 ();
    10. test2 ();
    11. test2 ();
    Здесь у нас первая функция имеет необязательный входной параметр, который, по-умолчанию, равен string1. Когда мы вызываем первую функцию без параметров, именно это значение она выдаст на страницу. Внутри второй функции мы, как и ранее, вызываем первую, но передаем в нее, в качестве параметра, строку "string2". При явном указании параметра, используется именно он, а не значение по-умолчанию. По этому, в данном случае мы увидим string2 на странице.
    --- Добавлено ---
    P.S. Сейчас эра HTML5, а не XHTML, так что br можно писать просто как <br>.
     
    Netopyr нравится это.
  4. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Простое правило: Если переменная появилась в функции, не является параметром, и не указана внутри функции как global, то она локальная, т.е. имеющая отношение только к функции, в которой появилась
     
    Netopyr нравится это.
  5. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    С допотопных уроков ютюба привычка :)

    Спасибо большое! Очень подробно написали, разобрался ;)
     
  6. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Однако... ты хотя бы проверяй то, что говоришь, прежде чем это утверждать.

    Держи, по твоей логике, на экран должно выдаваться "overrided"
    PHP:
    1. function test1 () {
    2.     $c = "overrided";
    3. }
    4. function test2 () {
    5.     $c = "not_overrided";
    6.     test1 ();
    7.     echo $c;
    8. }
    9. test2 ();
    Еще раз - переменная, объявленная внутри функции существует только внутри функции. Даже если переменная с таким же именем была объявлена ВНЕ функции, внутри все равно будет свой собственный экземпляр:

    PHP:
    1. $c = "global_value";
    2.  
    3. function test1 () {
    4.     $c = "local_value";
    5.     echo $c,'<br>';
    6. }
    7.  
    8. echo $c,'<br>'; //Выводим переменную из внешней области видимости.
    9. test1(); //Объявляем такую же внутри функции и выводим ее.
    10. echo $c,'<br>'; //Проверяем, изменилась ли внешняя переменная? Нет.
    Более того, если попробовать использовать внутри функции глобальную переменную, мы получим notice:
    PHP:
    1. $c = "global_value";
    2.  
    3. function test1 () {
    4.     echo $c;
    5. }
    6.  
    7. test1(); //NOTICE: Undefined variable
    Для такого случая в php даже запилен особый костыль в виде служебного слова global, которое намекает, что переменную надо искать в области видимости вне локальной:
    PHP:
    1. $c = "global_value";
    2.  
    3. function test1 () {
    4.     global $c;  
    5.     echo $c;
    6. }
    7.  
    8. test1(); //global_value
    Фух. Выговорился.
    Не надо так, бро.
     
  7. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    Вроде все предельно понятно, а у меня все равно не получается уже в моем скрипте. Смоделировал его!
    PHP:
    1. // устанавливем переменную, появляется из $_POST
    2. $var = 1;
    3. // эти переменные находятся в подключаемом файле php, подключаем include
    4. $x = "one".$var;
    5. $y = "two".$var;
    6. $z = "three".$var;
    7. // пишем функцию
    8. function test1 () {
    9.     global $arr;
    10.     $randarr = array_rand($arr, 1);
    11.     echo $arr[$randarr];
    12.     echo "<br>";
    13. }
    14. // пишем вторую функцию, как раз в ней задача изменить переменную $var,  а также во всех последующих шагах цикла чтобы она осталась ей (изменить на 2)
    15. function test2 () {
    16.     $var = 2;
    17.     test1 ();
    18. }
    19. $arr = array($x, $y, $z);
    20. // основной цикл
    21. while ($i <= 10) {
    22.     test1 ();
    23.     $i++;
    24.     if ($i == 5) {
    25.         test2 ();
    26.         $i++;
    27.     }
    28. }
     
    #7 Netopyr, 31 дек 2016
    Последнее редактирование: 31 дек 2016
  8. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Передавайте в функцию значение, обрабатывайте в ней, и возвращайте из нее новое, присваивая его начальной переменной. Либо передавайте переменную по ссылке.
     
  9. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ну чувак... Ты глобальную переменную $arr указал в функции как глобальную, а вот глобальную переменную $var в test2() не указал... А вообще, global не увлекайся. Отсилы одну-две можно оставить глобальных на большую систему (читал рекомендацию не более 10), лучше передавать через параметры
     
  10. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    Все равно не получается, ни объвления глобальной переменной var, ни передача по ссылке. Кривые руки не рулят совсем o_O
     
  11. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Ты сначала разберись, а потом уже делай, а не наоборот. И все будет получаться.
    --- Добавлено ---
    Ну и снова перечитай внимательно всю мою предыдущую простынь примеров. Там же код дан. И все объяснено. В том числе и то, что ты делать пытаешься.
     
  12. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    На самом деле я и не хочу, чтобы кто-то за меня это сделал, хочу разобраться сам. Вы правы, все предельно ясно написано, однако уразуметь я этого совсем не могу. Предложенный во втором сообщении код ваш работает, только я не могу присваивать входной параметр, так как это переменная, и сделать function test ($var = $var1) не валидно.
    Более того совсем запутался в этом:
    PHP:
    1. function test ($var) {
    2.     $var = 1;
    3.     echo $var;  
    4. }
    5. test (2);
    При изменении в теле функции порядка строк, изменение параметра происходит только если переменная объявлена после функции echo. Как так то. Просто выполнение функции происходит без разницы расположения.
    С областью видимости тут все вроде ясно, но применить на практике не получается.
    Буду дальше ломать голову.
    Спасибо большое.
     
  13. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    непонятно, что ты тут ломаешь.
    все инструкции выполняются в порядке прочтения скрипта, т.е. сверху вниз справа налево, не считая умножения и деления.
    global вообще никогда не делай и всё.
     
  14. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ты что, хочешь чтоб у тебя значения этих переменных менялись, когда функция меняет глобальную переменную $var? Так не получится.
     
    Netopyr нравится это.
  15. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    Все получилось при условии, что я отказался от global.

    PHP:
    1. function test1 ($var) {
    2.     $x = "one".$var;
    3.     $y = "two".$var;
    4.     $z = "three".$var;
    5.     $arr = array($x, $y, $z);  
    6.     $randarr = array_rand($arr, 1);
    7.     echo $arr[$randarr];
    8.     echo "<br>";
    9. }
    10.  
    11. function test2 () {
    12.     global $var2;
    13.     $var2 = 2;
    14.     test1 ($var2);  
    15. }
    16.  
    17. $a = 1;
    18.  
    19. while ($i <= 10) {
    20.     test1 ($a);
    21.     $i++;
    22.     if ($i == 5) {
    23.         test2 ();
    24.         $a = $var2;
    25.         $i++;
    26.     }
    27. }
    Понял, что к global лучше не прибегать. Буду учиться это обходить. НО. В данной случае мне пришлось прибегнуть, так как никак не вывести было $var2 за пределы функции. Return возвращал NULL.
    Всем спасибо еще раз, удивительно, что столько терпения к идиотским вопросам :)
     
  16. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Назначение $var2 непонятно :)
    --- Добавлено ---
    Код (Text):
    1.  
    2. function test1 ($var) {
    3.    $x = "one".$var;
    4.    $y = "two".$var;
    5.    $z = "three".$var;
    6.    $arr = array($x, $y, $z);
    7.    $randarr = array_rand($arr, 1);
    8.    echo $arr[$randarr];
    9.    echo "<br>";
    10. }
    11.  
    12. function test2 () {
    13.        test1 (2);
    14.        return 2;
    15. }
    16.  
    17. $a = 1;
    18.  
    19. while ($i <= 10) {
    20.     test1 ($a);
    21.    $i++;
    22.    if ($i == 5) {
    23.        
    24.        $a = test2 ();
    25.        $i++;
    26.    }
    27. }
     
  17. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    в конечном варианте эта переменная будет брать значения из массива, и перезаписывать $var
    $var2 = array_shift($some_arr);
     
  18. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Ну так и верни его из функции, как я сейчас показал
     
    Netopyr нравится это.
  19. Netopyr

    Netopyr Новичок

    С нами с:
    24 дек 2016
    Сообщения:
    15
    Симпатии:
    0
    Понял! спасибо :)