Аргументы функции. Реализация механизма разграничения прав доступа к админ-части Передача аргументов функции по значению и по ссылке

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

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

Передача аргументов

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

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

$color цвет"; // Значение переменной не изменилось?>

Если необходимо разрешить функции изменять переданные аргументы за ее пределами, вы должны передавать их по ссылке. Для того, чтобы аргумент был передан по ссылке, необходимо указать знак & (амперсанд) перед именем параметра в определении функции:

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

\n"; } echo tea(); // выведет значение по умолчанию echo tea("черный"); ?>

Примечание: все параметры, для которых установлены значения аргументов по умолчанию, должны находиться правее аргументов, для которых значения по умолчанию не заданы, так как в противном случае ваш код может работать не так, как вы того ожидали:

Значение, возвращаемое функцией

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

Return выражение;

Оператор return может быть расположен в любом месте функции. Когда до него доходит управление, функция возвращает значение (если указано) и завершает свое выполнение. Если оператор return не указан или не указано возвращаемое значение, то функция вернет значение NULL . Для использования возвращаемого значения, результат выполнения функции можно присвоить к примеру переменной:

"; // => 16. function foo($num) { if($num === 10) return "$num равно 10"; else return "$num не равно 10"; echo "hello"; // эта строка кода никогда не выполнится } echo foo(6); ?>

Подписчикам

Аргументы функции

Что такое аргументы функции?

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

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

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

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

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

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

Значения аргументов функции по умолчанию

Также в PHP имеется возможность использовать для аргументов функции значения по умолчанию , которые представляют собой значения, используемые в случае, если данному аргументу при вызове функции не будет передано вообще никакого значения. Для того, чтобы задать значение аргумента по умолчанию, необходимо в определении функции присвоить желаемое значение данному аргументу (см. пример №2). При этом значения по умолчанию могут иметь как аргументы, передаваемые по значению, так и аргументы, передаваемые по ссылке. Однако в любом случае все аргументы, которым присваиваются значения по умолчанию, должны идти в списке после аргументов, у которых значения по умолчанию отсутствуют. Кроме того, в качестве значений по умолчанию могут использоваться только константные выражения, а также массивы и значение NULL . Использовать, например, переменные или вызовы функций нельзя.

Пример №2. Использование значений аргументов по умолчанию

Список аргументов переменной длины

Если точное количество аргументов, передаваемых функции, заранее не известно, можно использовать список аргументов переменной длины . Такой список формируется при помощи специальной переменной, перед которой ставится многоточие "..." . В результате аргументы будут переданы в указанную переменную в виде массива (см. пример №3).

Пример №3. Использование списка аргументов переменной длины

Перед многоточием можно указывать обычные аргументы, при этом все остальные аргументы, переданные функции будут занесены в массив. Более того, перед многоточием можно указывать тип аргументов, которые могут быть занесены в массив, а также знак амперсанда "&" для передачи аргументов по ссылке (см. пример №4).

"; //Выведет 10, т.к. значение было передано функции //по ссылке и затем изменено функцией на 10 echo $a_1; ?>

Пример №4. Особенности использования списка аргументов переменной длины

Разрешается использовать многоточие "..." для разворачивания массива, передаваемого в качестве аргумента функции, в аргументы функции в виде его элементов (см. пример №5).

"; //Присваиваем массив переменной $a_3=; //Разворачиваем переданный функции массив //Выведет 3 echo m_sum_2(...$a_3); ?>

Пример №5. Разворачивание массива аргументов, переданного функции при вызове

Функции для доступа к аргументам

  • func_get_args() - возвращает массив, состоящий из аргументов функции;
  • func_get_arg(n) - возвращает указанный аргумент функции, где n=0,1,2,... - номер аргумента в списке, который начинается с нуля (напомним, что аргументы вычисляются слева направо);
  • func_num_args() - возвращает количество реально переданных функции аргументов.

"; //Выведет значение третьего аргумента, переданного функции echo func_get_arg(2); //Возвращаем сумму аргументов функции return $sum; } //Вызвали функцию. Выведет 38, т.е. количество переданных аргументов равно 3, //а значение 3-го аргумента равно 8 (нумерация элементов начинается с нуля) m_sum(1,2,8); ?>

Пример №6. Использование специальных функций для работы аргументами

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

Быстрый переход к другим страницам

Http://сайт Copyright © Петр Романовский, Минск, 2016-2019.

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

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

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

Давайте с самого начала обсудим архитектуру модульной системы на выбранной нами псевдо-системе.

Все модули представлены ввиде подключаемых к главному документу (индекс-файлу) вставок. Запрос модуля происходит из строки запроса QUERY_STRING, и название подключаемого модуля передаётся в качестве аргумента act. В некотором месте индекса файла происходит изъятие и обработка данного параметра. После, если у пользователя достаточно прав для доступа к модулю в контексте чтения, происходит проверка существования указанного в строке запроса модуля, и если таковой существует, то происходит его подключение к индекс файлу.

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

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

Значение do буду фиксированными, данная переменная будет принимать следующие значения:

  • main - главная часть модуля (доступно в контексте чтения)
  • config - раздел настройки модуля (доступно в контексте записи)
  • create - произвести некоторые действия, по добавлению информации в БД (доступно в контексте записи)
  • delete - доступ к разделу, предоставляющему возможности удалить некоторую информацию, в контексте данного модуля (доступно в контексте записи)
  • edit - доступ к редактированию информации в контексте модуля (доступно в контексте записи)

В целом, этот список можно увеличить, при этом всё зависит лишь только от масштабов проекта и его потребностей в функционале.

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

Так, запись о модуле системы будет содержать следующую информацию: английский идентификатор названия модуля, который будет идентичен значению переменной среды GET - act (относительно него будет производится непосредственно запрос модуля), русский идентификатор модуля, который будет использоватся в списке модулей.

Кроме модулей у нас будут ещё две таблицы, а именно таблица в которой будут хранится данные относительно профилей прав доступа и таблица с информацией о пользователях непосредственно.

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

Что ж, давайте рассмотрим эту особую структуру. Она будет следующей: [ module_indefier: + \: + \;] *

То есть идёт список из пар: имя модуля ":" права чтения "," права записи ";". При этом данная метка обновляется в момент внесения изменений о правах доступа пользователя к системе. Если в системе появляется информация о модуле, который не вошёл в данную метку, то стоит просто произвести процедуру редактирования, и данные сохранятся автоматически.

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

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

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

Таблица `modules`:

CREATE TABLE `modules` (`id` bigint(20) NOT NULL auto_increment, `indefier` text collate utf8_unicode_ci NOT NULL, `title` text collate utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Таблица `secure_groups`:

CREATE TABLE `secure_groups` (`id` bigint(20) NOT NULL auto_increment, `title` text collate utf8_unicode_ci NOT NULL, `perms` text collate utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;

Таблица `users`

CREATE TABLE `users` (`id` bigint(20) NOT NULL auto_increment, `login` text collate utf8_unicode_ci NOT NULL, `passwd` text collate utf8_unicode_ci NOT NULL, `groupId` int(1) NOT NULL default "0", PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;

temp=array(); $this->temp["_result"]=0; $this->temp["_uid"]=explode("::",$_COOKIE["site_hash"]); $this->temp["_uid"]=$this->temp["_uid"]; $this->temp["_gid"]=$this->getUserSecurityAccess($this->temp["_uid"]); $this->temp["_conn_id"]=mysql_connect("host","user","passwd"); mysql_select_db("database"); $this->temp["_q1"]=mysql_query("SELECT perms" ."FROM `secure_groups`" ."WHERE id=".$this->temp["_gid"]); $this->temp["_access_stamp"]=mysql_fetch_assoc($this->temp["_q1"]); $this->temp["_access_stamp"]=$this->temp["_access_stamp"]["perms"]; $this->temp["_access_stamp"]=explode(";",$this->temp["_access_stamp"]); $this->temp["_access_stamp"]=array_slice($this->temp["_access_stamp"],0,-1); foreach($this->temp["_access_stamp"] as $this->temp["v"]){ $this->temp["_mod_access"]=explode(":",$this->temp["v"]); $this->temp["_mod_indefier"]=$this->temp["_mod_access"]; if($this->temp["_mod_indefier"]==$module){ $this->temp["_perms"]=explode(",",$this->temp["_mod_access"]); switch($act){ case "r": $this->temp["_result"]=($this->temp["_perms"]==1)? 1:0; break; case "w": $this->temp["_result"]=($this->temp["_perms"]==1)? 1:0; break; } break; } } mysql_close($conn_id); return $this->temp["_result"]; } } ?>

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

Функция secure::getUserId()

Используя данную функцию, мы подразумеваем, что во время авторизации пользователя в системе в переменной среде $_COOKIE была установлена переменная `site_hash`, состоящая из идентификатора пользователя в системе и хеша для проверки аутентичности его в системе. Функция просто изымает значение идентификатора, возращая его значение на выходе.

Функция secure::getUserSecurityAccess($id)

На выходе данная функция возвращает идентификатор профиля безопасности текущего пользователя в системе.

Функция secure::checkUserPermission($module,$act))

Производится запрос к БД, относительно прав пользователя на произведение действий чтения/записи в контексте переданного в качестве параметра модуля.

Осталось лишь описать процедуру формирования переменной в среде $_COOKIE, и тему статьи можно будет считать расскрытой.

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

Для проверки аутентичности данных хранимых в переменной среде $_COOKIE, мы будем использовать функцию EatCookie(), которая будет производить валидацию данных, возвращая булевый результат проверки (истина - ложь).

Я не привожу форму для отправки, так как это не часть теории программирования, указав лишь идентификаторы полей.

  • `ulogin` - логин пользователя
  • `upasswd` - пароль пользователя
  • `stime` - время сессии, устанавливаемое пользователем (от 1 до 5 часов)
  • `auth` - имя кнопки отправки

Вот, в целом и всё. Осталось лишь пробовать, экспериментировать, ошибатся и находить решение, что я всецело и оставляю вам.

Надеюсь, что мы скоро встретимся, а для тех кто имеет ко мне вопрос в отношении статьи, да и не только - писать на [email protected], либо на [email protected].

С уважением Карпенко Кирилл, глава IT-отдела ИНПП.

В продолжение темы:
Безопасность компьютера

Современный Yandex браузер готов раскрывать удивительные возможности трансляции видео, но для этого требуется использование продвинутого Flash Player. Какая программа...

Новые статьи
/
Популярные