Функция внутри цикла php

Заметка: активирована адаптивная версия сайта, которая автоматически подстраивается под небольшой размер Вашего браузера и скрывает некоторые детали сайта для удобства чтения. Приятного просмотра!
Здравствуйте уважаемые читатели блога Site on! В предыдущей статье мы узнали что есть функция в PHP, научились создавать собственные функции, передавать в них аргументы и вызывать их для выполнения. Продолжая тему функций в PHP необходимо подчеркнуть следующие вещи:
- Внутри функции можно использовать любой PHP код (циклы, условия, любые операции), включая другие функции (как встроенные, так и собственные);
- Имя функции должно начинаться с латинской буквы, либо знака подчёркивания, далее может идти любое количество латинских букв, цифр или знаков подчёркивания;
- Все функции имеют глобальную область видимости, это значит, что любая функция может быть вызвана в любом месте, даже если эта функция определена внутри другой;
- PHP не поддерживает перегрузку функций, также отсутствует возможность переопределить (изменить, дополнить) или удалить созданную функцию;
- Функции не обязаны быть определены до их использования. То есть если вы сначала вызовите функцию, а только потом – ниже по коду её опишите, то это не повлияет на работоспособность и не вызовет ошибок.
Функции, зависящие от условий
Мы можем создавать (определять, описывать) функцию, в зависимости от условия. Например:
<?php $apply = true; sayHi(); //вызвали функцию sayHi, её можно вызывать в любом месте /*здесь нельзя вызвать функцию sayGoodbye, так как мы ещё не проверили условие и не зашли внутрь конструкции if*/ if($apply){ sayGoodbye(){ echo ‘Всем пока! <br>’; } } /*вот теперь можем вызвать sayGoodbye*/ sayGoodbye(); sayHi(){ echo ‘Всем привет! <br>’; }
Результат:
И взгляните на этот пример:
<?php $apply = true; sayHi(); /*вызвали функцию sayHi, её можно вызывать в любом месте*/ /*а вот что будет, если вызвать sayGoodbye здесь*/ sayGoodbye(); if($apply){ sayGoodbye(){ echo ‘Всем пока! <br>’; } } sayHi(){ echo ‘Всем привет! <br>’; }
Результат:
Всё понятно из названия ошибки, разве что стоит пояснить следующую вещь: интерпретатор PHP при первом (быстром) обходе не видит что функция sayGoodbye вообще хоть где-то описана, он увидит это только когда код начнёт выполняться и только если условие будет true (читайте про типы переменных).
На самом деле, сколько я работаю, ни разу нигде такого не встречал, но иметь в виду нужно все возможности языка.
Вложенные функции
Вложенная функция – это функция, объявленная внутри другой функции. Пример:
<?php /*Здесь нельзя вызвать sayGoodbye, так как она появится только после вызова функции sayHi*/ sayHi(); /*вызвали функцию sayHi, её можно вызывать в любом месте*/ /*Теперь можем вызывать sayGoodbye*/ sayGoodbye(); sayHi(){ echo ‘Всем привет! <br>’; sayGoodbye(){ echo ‘Всем пока! <br>’; } }
Опять-таки, при первом обходе интерпретатор PHP помечает себе, что он нашёл описание функции sayHi, но не заходит внутрь её тела, он видит только название, а раз интерпретатор не заходит внутрь тела sayHi, то он понятия не имеет, что внутри мы определяем ещё одну функцию – sayGoodbye.
Далее код начинает исполняться, мы вызываем sayHi, интерпретатору PHP приходиться зайти в тело функции sayHi, чтобы выполнить её и там он случайно находит описание ещё одной функции – sayGoodbye, после чего и sayGoodbye можно вызывать в любом месте, сколько угодно раз.
Но стоит обратить внимание на очень тонкий момент в ситуации выше: функция sayHi становится одноразовой, потому что если мы ещё раз её вызовем, то PHP опять наткнётся на определение функции sayGoodbye, а в PHP так делать нельзя – нельзя переопределять функции. Об этом и о том, как с этим бороться я писал в предыдущей статье.
В PHP описанные выше приёмы применяются очень редко, чаще их можно увидеть, например, в JavaScript.
Область видимости переменных
В PHP ровно две области видимости: глобальная и локальная. В каждом языке программирования области видимости устроены по-разному. Например, в C++ даже в циклах своя (локальная) область видимости. В PHP, кстати, циклы – это глобальная область видимости. Но сегодня мы говорим о функциях.
У функций в PHP своя, внутренняя область видимости (локальная), то есть все переменные внутри функции видны только внутри этой самой функции.
Итак, ещё раз: все, что вне функций – это глобальная область видимости, все, что внутри функций – локальная область видимости. Пример:
<?php sayHi($name){ echo ‘Привет, ‘.$name.’! <br>’; $name = ‘Рудь Сергей’; } $name = ‘Андрей’; sayHi($name); echo $name; // ?
Уважаемые знатоки, внимание, вопрос! Что выведет последняя инструкция echo $name; ?
Ответ:
Как вы сами видели, у нас было 2 переменных $name, одна внутри функции (локальная область видимости), другая просто в коде (глобальная область видимости), последнее присвоение в переменную $name было $name = ‘Рудь Сергей’; Но так как это было внутри функции, то там оно и осталось. В глобальной же области видимости последним присвоением было $name = ‘Андрей’; что мы собственно и видим в результате.
То есть две одинаковые переменные, но в разных областях видимости никак не пересекаются и не влияют друг на друга.
Давайте я проиллюстрирую области видимости на рисунке:
При первом обходе интерпретатор бегло просматривает глобальную область видимости, запоминает какие есть переменные и функции, но не выполняет код.
Обращение к глобальным переменным из локальной области видимости
Но что если нам всё-таки нужно из функции обратиться к той самой переменной $name из глобальной области видимости, да не просто обратиться, а изменить её? Для этого есть 3 основных варианта. Первый из них использование ключевого слова global:
<?php sayHi($name){ echo ‘Привет, ‘.$name.’! <br>’; global $name; /*начиная с этого момента мы имеем ввиду глобальную переменную $name*/ $name = ‘Рудь Сергей’; } $name = ‘Андрей’; sayHi($name); echo $name; // ?
Результат:
Но у этого способа есть минус, с тех пор как мы обратились к глобальной переменной $name мы потеряли (переписали) локальную переменную $name.
Второй способ заключается в том, чтобы использовать суперглобальный массив PHP. В этот массив PHP сам, автоматически помещает каждую переменную, которую мы создали в глобальной области видимости. Пример:
$name = ‘Андрей’; //Тоже самое что и $GLOBALS[‘name’] = ‘Андрей’;
Следовательно:
<?php sayHi($name){ echo ‘Привет, ‘.$name.’! <br>’; $GLOBALS[‘name’] = ‘Рудь Сергей’; } $name = ‘Андрей’; sayHi($name); echo $name; // ?
Результат тот же, что и при использовании ключевого слова global:
Только в этот раз мы не переписали локальную переменную, то есть переменная $name внутри функции осталась прежней и равна “Андрей”, а не “Рудь Сергей”.
Передача аргументов по ссылке
Третий способ – это передача адреса (ссылки) переменной, а не её значения. Ссылки в PHP не очень удались, в отличие от других языков программирования. Тем не менее, я расскажу вам единственный правильный вариант передачи аргумента по ссылке в функцию, который нормально поддерживается в PHP 5.3 и выше. Есть и другие способы работы со ссылками, но они работали в PHP 5.2 и ниже, в итоге сами разработчики PHP решили от них отказаться, поэтому не будем о них.
Так вот, ПРАВИЛЬНАЯ передача аргумента по ссылке в PHP 5.3 и выше осуществляется следующим образом:
sayHi(&$name){
Мы в самом описании функции добавили значок амперсанд (&) – этот значок означает, что мы принимаем не значение переменной, а ссылку (адрес) на это значение в памяти. Ссылки в PHP позволяют создать две переменные, указывающие на одно и то же значение. Это означает, что при изменении одной из этих переменных, меняются обе, так как в памяти они обращаются к одному и тому же значению.
И в итоге имеем:
<?php sayHi(&$name){ //принимаем не значение, а ссылку на значение echo ‘Привет, ‘.$name.’! <br>’; $name = ‘Рудь Сергей’; } $name = ‘Андрей’; sayHi($name); echo $name; // ?
Результат:
Статические переменные
Представьте себе следующую ситуацию: нам нужно посчитать сколько раз мы всего поздоровались. Вот что мы пытаемся сделать:
<?php sayHi($name){ $c = 0; // счётчик echo ‘Привет, ‘.$name.’! <br>’; $c++; // увеличиваем счётчик на 1 echo ‘Всего поздоровались ‘ . $c . ‘ раз.<hr>’; } sayHi(‘Рудь Сергей’); sayHi(‘Андрей’); sayHi(‘Дмитрий’);
Результат:
Переменная $c не запоминает своего значения, она каждый раз создаётся заново. Нам нужно сделать так, чтобы наша локальная переменная $c запоминала своё значение после выполнения функции, для этого используют ключевое слово ic:
<?php sayHi($name){ ic $c = 0; // счётчик, сделали статическим echo ‘Привет, ‘.$name.’! <br>’; $c++; // увеличиваем счётчик на 1 echo ‘Всего поздоровались ‘ . $c . ‘ раз.<hr>’; } sayHi(‘Рудь Сергей’); sayHi(‘Андрей’); sayHi(‘Дмитрий’);
Результат:
Возврат значений
В функциях есть такая удобная вещь, как возврат значений. Это когда функция вместо того, чтобы вывести что-нибудь на экран, помещает всё в переменную и отдаёт эту переменную нам. А мы уже дальше решаем, что с ней делать. Для примера возьмём эту функцию, она возводит число в квадрат:
<?php getSquare($number){ $result = $number*$number; echo $result; } getSquare(5);
Результат:
Сделаем так, чтобы вместо вывода на экран она возвращала результат выполнения. Для этого используется ключевое слово return:
<?php getSquare($number){ $result = $number*$number; return $result; } getSquare(5);
Результат:
Теперь мы можем использовать это различными способами:
<?php getSquare($number){ $result = $number*$number; return $result; } echo getSquare(5); //выводит результат echo ‘<br>’; $num = getSquare(5); // присвоили результат в переменную echo $num; // вывели переменную на экран
Результат:
Обращаю ваше внимание, что ключевое слово return не просто возвращает значение, а полностью прерывает работу функции, то есть весь код, который находится ниже ключевого слова return никогда не исполниться. Другими словами, return для функций вдобавок работает как break для циклов:
<?php getSquare($number){ $result = $number*$number; return $result; echo ‘До меня PHP никогда не дойдёт :(‘; } echo getSquare(5); //выводит результат echo ‘<br>’; $num = getSquare(5); // присвоили результат в переменную echo $num; // вывели переменную на экран
Результат:
То есть return – это ещё и выход из функции. Его можно использовать и без возвращаемого значения, только ради выхода.
Рекурсивная функция
Рекурсивная функция – это функция, которая вызывает сама себя. Рекурсия используется не часто и считается ресурсоёмкой (медленной) операцией. Но бывает, что использование рекурсии самый очевидный и простой вариант. Пример:
<?php countPlease($number){ echo $number . ‘<br>’; if($number < 20){ // чтобы рекурсия не стала бесконечной countPlease(++$number); // функция countPlease вызвала сама себя } } countPlease(1);
Результат:
Если вы знаете, как обойтись без рекурсии, то лучше так и сделать.
Строгая типизация в PHP (уточнение типа)
В PHP сделаны мелкие шаги к строгой типизации, благодаря этому мы можем заранее указать, какой тип должна принимать функция (это называется type-hint):
<?php countPlease(array $numbers){ // какой-то код } countPlease(1);
Результат:
Catchable fatal error: Argument 1 passed to countPlease() must be an array, integer given, called in /home/index.php on line 7 and defined in /home/index.php on line 3
Ошибка нам говорит, что функция ожидает принять массив, а вместо этого мы ей передаём число. К сожалению, пока что мы можем уточнять тип только для массивов (array), а с PHP 5.4 ещё добавился такой вариант как callable:
<?php countPlease(callable $v){ $v(); } countPlease(“getEcho”); getEcho(){ echo ‘Вызвали функцию getEcho; }
Callable проверяет, может ли переданное значение быть вызвано в качестве функции. Callable может быть как именем функции, заданным строковой переменной, так и объектом и именем вызываемого метода. Но про объекты и методы мы поговорим позже (это раздел объектно-ориентированного программирования), а с функциями вы уже знакомы. Результат работы я вам показать не могу, так как у меня сейчас стоит PHP 5.3, но он был бы:
Вызвали функцию getEcho
Использование аргументов переменной длины
И напоследок ещё один очень редко используемый нюанс. Представьте ситуацию, мы передаём в функцию аргументы, хотя в функции мы их не описали, например:
<?php getEcho(){ echo ‘Вызвали функцию getText’; } $age = 22; getEcho(‘Рудь Сергей’, $age);
Результат:
Как видите, ошибок нет, но и наши переданные аргументы нигде не используются. Но это не значит, что они пропали – они всё равно передались в функцию и мы можем их использовать, для этого существуют встроенные функции PHP:
func_num_args() – Возвращает количество аргументов, переданных функции
func_get_arg(порядковый номер) – Возвращает элемент из списка аргументов
func_get_args() – Возвращает массив, содержащий аргументы функции
Пример:
<?php getEcho(){ echo ‘Вызвали функцию getText <br>’; echo func_get_arg(0); } $age = 22; getEcho(‘Рудь Сергей’, $age);
Результат:
Заключение
Сегодняшняя статья является заключительной по теме функций в PHP. Теперь вы можете быть уверены в полноте своих знаний касательно этой темы и можете смело использовать функции для своих нужд.
Если у кого-то есть желание набить руку, но нет идей как это сделать – лучшим способом будет написание уже готовых (встроенных) функций PHP, например, можно написать собственную функцию count() или любую другую.
Благодарю всех за внимание и до новых встреч! Если что-то не понятно, смело задавайте ваши вопросы в комментариях!
Пожалуйста, оцените эту статью
Средняя оценка: 4.74 из 5 (проголосовало: 34)
Статья оказалась вам полезной? Подпишитесь, чтобы не пропустить новые!
Вы можете помочь развитию проекта, сделав всего 1 клик:
Спасибо!
Источник
Что-то вроде этого:
echo ‘<div class=”medium-auto small-12 cell” style=”padding:2px;”>’; echo ‘<select style=”margin: 0; height: auto; border: 0;” name=”program” id=”program-‘.$row[‘id’].'” >’; echo ‘<option value=”” disabled selected>’.$row[“program”].'</option>’; echo ‘<option value=”Hockey”>Hockey</option>’; echo ‘<option value=”Fundamentals”>Fundamentals</option>’; echo ‘</select>’; echo ‘</div>’; echo ‘<div class=”medium-auto small-12 cell” style=”padding:2px;”>’; echo ‘<select style=”margin: 0; height: auto; border: 0;” name=”plan” id=”plan-‘.$row[‘id’].'”>’; echo ‘<option value=”” disabled selected>’.$row[“plan”].'</option>’; echo ‘</select>’; echo ‘</div>’; ?> <script> var programsByplan = { Hockey: [“Off Season”, “Pre Season”, “In Season”], Fundamentals: [“Phase 1″], } $(‘select[name=”program”]’).change((){ var program = $(this).val(); var plan_id = $(this).prop(‘id’).replace(‘program’, ‘plan’); if(programsByplan[program]){ var options = []; $.each(programsByplan[program], (i,v){ options.push(‘<option value=”‘+v+'”>’+v+'</option>’); }); $(‘#’+plan_id).html(options.join(“n”)); }else{ //or, do somkind of error recovery here. $(‘#’+plan_id).html(‘<option value=””>No Plans</option>’); } }); </script>
Я бы избавился от onChangeЯ также активно использую jQuery, но вопрос помечен этим.
Таким образом, на изменение любого выбора с именем program (что мы не изменили, поэтому они все имеют одно и то же имя), мы запускаем обратный вызов события. Конечно, вы также можете выполнить эту часть с классом.
В обратном вызове мы получаем значение, выбранное в текущем выборе, затем мы проверяем, что оно существует в programsByplan (что всегда должно быть), но проверять не мешает.
Затем мы конвертируем идентификатор программы program-‘.$row[‘id’].’ в plan-‘.$row[‘id’].’, Теперь мы знаем, какой план выбрать для изменения. Я предпочитаю использовать массив для добавления параметров, но вы можете сделать += вещь. И тогда их просто заменить, теперь, когда мы знаем идентификатор элементов плана, .html(),
Я не проверял это, но это должно быть довольно близко. Самое главное – настроить себя на успех, легко идентифицируя идентификатор, или, другими словами, легко найти правильный plan элемент для измененных program элемент.
Я также предполагаю, что у вас есть $row[‘id’] это по крайней мере уникально для цикла, который генерирует их.
Обновить
Но как я могу получить параметры для отображения на странице загрузки, когда программа / план правильно из базы данных
Я бы еще изменил это так:
//outside of the loop define your data $programsByplan = [ ‘Hockey’ => [“Off Season”, “Pre Season”, “In Season”], ‘Fundamentals’ => [“Phase 1″], ]; //inside the loop echo ‘<div class=”medium-auto small-12 cell” style=”padding:2px;”>’; echo ‘<select style=”margin: 0; height: auto; border: 0;” name=”program” id=”program-‘.$row[‘id’].'” >’; foreach($programsByplan as $program => $plans){ //$selected = $row[“program”] == $program ? ‘disabled selected’ : ”; $selected = $row[“program”] == $program ? ‘selected=”selected”‘ : ”; echo ‘<option value=”‘.$program.'” ‘.$selected.’>’.$program.'</option>’; } echo ‘</select>’; echo ‘</div>’; echo ‘<div class=”medium-auto small-12 cell” style=”padding:2px;”>’; echo ‘<select style=”margin: 0; height: auto; border: 0;” name=”plan” id=”plan-‘.$row[‘id’].'”>’; foreach($programsByplan[$row[“program”]] as $plan){ //$selected = $row[“plan”] == $plan ? ‘disabled selected’ : ”; $selected = $row[“plan”] == $plan ? ‘selected=”selected”‘ : ”; echo ‘<option value=”‘.$plan.'” ‘.$selected.’>’.$plan.'</option>’; } echo ‘</select>’; echo ‘</div>’; ?> <script> var programsByplan = <?php echo json_encode($programsByplan); ?>; //… other code
Здесь мы добавляем $programsByplan в PHP, затем с помощью json_encode мы можем добавить тот же массив в Javascript, что является удивительным. Надеюсь, это работает
var programsByplan = <?php echo json_encode($programsByplan); ?>;
Иногда это может потребовать некоторых усилий, но оно имеет огромные преимущества в поддержке кода. Потому что вы используете только один авторитетный источник данных для этого. В отличие от того, чтобы распространяться повсюду. Дополнительным преимуществом этого является то, что если вы идете и делаете программы и планы в виде двух таблиц с отношением «многие к одному», вы можете поместить их в БД и легко обновить код, создав этот массив. Посмотрите, распределяются ли данные только в жестком коде, тогда будет сложно внести подобные изменения позже.
Это также позволяет нам исправить некоторые другие проблемы, которые у вас возникли с созданием селекторов изначально, и просто упрощает код. Одной из больших проблем было удаление значения на выбранных элементах и наличие дублирующих элементов.
echo ‘<option value=”” disabled selected>’.$row[“program”].'</option>’;
Вы на самом деле удаляете значение здесь, что, вероятно, не то, что вы хотите. Я также не уверен в disabled немного, так что я просто оставил это в. Может быть, это было просто там, чтобы исправить проблемы выбора при его инициализации? Во всяком случае, я поставил эту часть в комментарии. Я всегда выбирал так:
$selected = $row[“program”] == $program ? ‘selected=”selected”‘ : ”;
Это, вероятно, «старый школьный» способ сделать это, но он всегда работал для меня.
В любом случае, и, очевидно, если мы попытаемся получить значение выбранного параметра и его значение будет удалено, это, вероятно, не сработает. Не говоря уже о том, что нет способа «узнать», что это такое, чтобы удалить опцию с тем же значением, когда она просто жестко запрограммирована, как это было, и поэтому вы получите дублирующую опцию для нее.
Это должно исправить большинство из этого, но все это сделано в моей голове, так что, надеюсь, все это работает так, как я думаю, что должно. Теория в любом случае обоснована.
Вы можете проверить это в этой песочнице:
https://sandbox.onlinephps.com/code/077c8a988697122549713ede9c305bf4f7620ed9
используя (как консервированные данные для строки.)
$row = [ ‘id’ => 1, ‘program’ => ‘Hockey’, ‘plan’ => ‘Off Season’ ];
Какие выводы:
<div class=”medium-auto small-12 cell” style=”padding:2px;”> <select style=”margin: 0; height: auto; border: 0;” name=”program” id=”program-1″ > <option value=”Hockey” selected=”selected”>Hockey</option> <option value=”Fundamentals” >Fundamentals</option> </select> </div> <div class=”medium-auto small-12 cell” style=”padding:2px;”> <select style=”margin: 0; height: auto; border: 0;” name=”plan” id=”plan-1″> <option value=”Off Season” selected=”selected”>Off Season</option> <option value=”Pre Season” >Pre Season</option> <option value=”In Season” >In Season</option> </select> </div>
Как вы можете видеть, у нас есть program-1 а также plan-1 наши идентификаторы, то оба выбора имеют соответствующий элемент с selected=”selected”
Up2
Для обработки случаев, когда данные ранее не были выбраны для программы.
Для первого цикла выше я бы добавил это
//echo <select … echo ‘<option value=”” > – Please select a program – </option>’; //foreach( …
Сделайте это до цикла и после открытия для <select, Затем для второго цикла я бы отключил второй выбор, пока они не сделают выбор в первом.
$disabled = empty($row[“program”]) ? ‘disabled=”disabled”‘: ”; echo ‘<select style=”margin: 0; height: auto; border: 0;” name=”plan” id=”plan-‘.$row[‘id’].'” ‘.$disabled.’>’;
А потом в Javascript
$(‘select[name=”program”]’).change((){ var program = $(this).val(); if(program == ” ) return; //exit on empty selection var plan_id = $(this).prop(‘id’).replace(‘program’, ‘plan’); //enable the select if disabled. $(‘#’+plan_id).attr(‘disabled’,false);
Тогда вы можете просто проверить перед сохранением, что они выбрали программу и т. Д. И т. Д.
Up3
Для любых проблем Javascript всегда используйте окно отладки в браузере (f12), затем нажмите на console, Тогда в вашем коде вы можете просто сделать как
console.log(var);
И это напечатает это значение в консоли. Это похоже на PHP var_export, _r или var_dump и т.д …
Поэтому я бы начал с этого
<script> var programsByplan = <?php echo json_encode($programsByplan); ?>; console.log(programsByplan); $(‘select[name=”program”]’).change((){ var program = $(this).val(); console.log(program); var plan_id = $(this).prop(‘id’).replace(‘program’, ‘plan’); console.log(programsByplan[program]); if(programsByplan[program]){ var options = []; $.each(programsByplan[program], (i,v){ options.push(‘<option value=”‘+v+'”>’+v+'</option>’); }); $(‘#’+plan_id).html(options.join(“n”)); }else{ //or, do somkind of error recovery here. $(‘#’+plan_id).html(‘<option value=””>No Plans</option>’); } }); </script>
И так далее, и посмотрите, что это за значения. Это, наверное, лучший способ.
Приветствия.
-1
Источник