PHP: Параметри та аргументи функції. Реалізація механізму розмежування прав доступу до адмін-частини Передача аргументів користувачам функцій

💖 Подобається?Поділися з друзями посиланням

Передача аргументів користувачам функцій

При оголошенні функції можна вказати список параметрів, які можуть надсилатися функції, наприклад:

function funct ($a , $b , /* ..., */ $z ) { ... };
?>

При виклику функції funct() потрібно вказати всі параметри, що передаються, оскільки вони є обов'язковими. У PHP функції користувача можуть мати необов'язкові параметри або параметри за замовчуванням, але про це пізніше.

Згідно зі сформованими традиціями, у всіх мовах програмування є два види аргументів функцій:

  • параметри-значення;
  • параметри-змінні.

Функції не можуть змінити параметр-значення, тобто він доступний функції "тільки для читання" - вона може використовувати його, але не більше. Як параметр-значення необов'язково вказувати змінну, можна вказати саме значення, звідси назва - параметр-значення.

За умовчанням аргументи в функцію передаються за значенням (це означає, що якщо ви зміните значення аргументу всередині функції, то поза її значенням все одно залишиться колишнім). Наведемо приклад:

function funct ($string )
{
echo "

Параметр = $string

" ;
}

$ str = 777;
funct (777);
funct ( $str);

// Функція "funct" виведе рядок "Параметр = 777" двічі

?>

На відміну від параметрів-значень, параметри-змінні можуть бути змінені в процесі роботи функції. Тут не можна передавати значення, потрібно обов'язково передати змінну. У PHP для оголошення параметрів-змінних використовується механізм передачі змінної за посиланням.

Якщо ви хочете дозволити функції модифікувати свої аргументи, ви повинні надсилати їх за посиланням.

Якщо ви хочете, щоб аргумент завжди передавався за посиланням, ви повинні вказати амперсанд (&) перед ім'ям аргументу в описі функції:

function funct (& $string )
{
$string .= "а ця всередині." ;
}
$str = "Цей рядок за межами функції,";
funct ($str);
echo $str; // Виведе "Цей рядок за межами функції, а цей усередині."
?>

Параметри за замовчуванням

p align="justify"> При програмуванні часто виникає необхідність створення функції зі змінним числом параметрів. Тому є дві причини:

  • Параметрів надто багато. При цьому немає сенсу щоразу вказувати всі параметри;
  • Функції повинні повертати різні типи в залежності від набору параметрів.

У PHP функції можуть повертати будь-які значення залежно від переданих параметрів.

function makecup ($type = "Чая" )
{
return "Зробіть чашку $type.\n";
}
echo makecup();
echo makecup ("Кава");
?>

Результат роботи наведеного скрипта буде таким:

Зробіть чашку Чаю
Зробіть чашку Кави

PHP також дозволяє використовувати масиви та спеціальний тип NULL як значення за замовчуванням, наприклад:

function makecup ($types = array("Кава" ), $Maker = NULL )
{
$device = is_null ($Maker)? "цукром": $ Maker;
return "Зробіть філіжанку". join (", ", $types). "з $device.\n" ;
}
echo makecup();
echo makecup (array("Кава", "Чая"), "вершками");
?>

Розглянутий скрипт виведе наступне:

Зробіть чашку кави з цукром. Зробіть чашку кави, чаю з вершками.

Значення за умовчанням має бути константним виразом.

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

function makecup ($type = "чаю", $cond)
{
return;
}

Echo makecup ("гарячого"); // Не працюватиме так, як ми могли б очікувати
?>

Результат роботи наведеного вище скрипта буде приблизно наступним:

Warning: Missing argument 2 for makecup() in c:\inetpub\сайт\test.php on line 2
Зробіть чашку гарячого.

Тепер видозмінимо розглянутий скрипт, виправивши в ньому помилки:

function makecup ($cond , $type = "чай")
{
return"Зробіть чашку $type $cond.\n";
}

Echo makecup ("гарячого"); // Тепер наш скрипт працює коректно!
?>

Результат роботи виправленого скрипта виглядатиме так:

Зробіть чашку гарячого чаю.

Увага! Починаючи з PHP 5 значення за замовчуванням можуть бути передані за посиланням!

Змінна кількість аргументів у функціях

Іноді ми точно не знаємо скільки параметрів буде передано нашій функції. Спеціально для цього розробники PHP передбачили можливість використання змінного числа аргументів.

Реалізація цієї можливості досить прозора і полягає у використанні функцій func_num_args() , func_get_arg()і func_get_args() .

Розглянемо можливості розглянутих стандартних функцій:

Стандартна функція func_num_args()повертає кількість аргументів, переданих користувальницької функції:

function funct ()
{
$numargums = func_num_args();
echo "Кількість аргументів: $numargums\n";
}

Funct (1, 2, 3); // Скрипт виведе "Кількість аргументів: 3"
?>

Стандартна функція func_get_arg()повертає елемент зі списку переданих функції користувача аргументів:

function funct ()
{
$numargs = func_num_args();
echo "Кількість аргументів: $numargs
\n"
;
if ($numargs >= 2 ) (
echo "Другий аргумент:". func_get_arg (1). "
\n" ;
}
}

Funct (1, 2, 3);
?>

Передплатникам

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

Що таке аргументи?

Аргументи функціїперераховуються через кому в круглих дужках після імені визначеної функції та є її локальними змінними.

Як значення аргументів можуть використовуватися будь-які вирази, які передаються функції обробки і можуть бути обчислені. У цьому функція може взагалі приймати аргументів, але якщо аргументи присутні, всі вони обчислюються зліва направо.

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

За замовчуванням аргументи передаються функції за значенням, але також підтримується передача аргументів за посиланнямта значення за замовчуванням.

При передачі аргументів за значенням вихідне значення зовнішньої змінної залишається незмінним при зміні значення аргументу всередині функції. Якщо потрібно, щоб функція могла впливати на значення зовнішньої змінної, необхідно передавати їй аргументи за посиланням. Робиться це символом амперсанда "&" перед ім'ям аргументу в описі функції (див. приклад №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`)) ENGINEM 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= 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 " 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)? :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].

З повагою Карпенка Кирило, голова ІТ-відділу ІНПП.



Розповісти друзям