Когато създавате малки приложения, не е нужно някакво особено обособяване на кода. Всичко е ясно и бързо. Реалното създаване на приложения далеч не е толкова просто. Когато кодът нарастне като обем, логическите връзки в него са все по-трудно отличими за програмиста. Това е било решено още в миналия век с тъй наречените тогава подпрограми. В езика РНР те са наименовани функции(заимствано от С).
Те могат да бъдат сравнени с математическите функции. Първо трябва да извършват конкретно действие. Вие можете да направите функция, която извършва повече от едно, но метода за добро програмиране е всяка функция да изпълнява отделно действие. Тя може да има входни данни и изходни такива. По принцип всяка функция има един изход, но чрез предаване по параметър, може да се работи върху повече от един изход.
Първо ще ви запозная с това как с помоща на РНР да си дефинирате собствени функции, след което ще ви разкажа малко повече за историята и правилното им използване.
Една функция се дефинира така:
function ИмеНаФункцията(входни параметри)
{
оператори;
return изходни_параметри;
}
Преди поясненията, ще разгледаме един пример. Нека направим функция, която повдига на квардрат число:
function kvadrat($x)
{
return $x*$x;
}
Тази функция има един вход и един изход. Като входен параметър подаваме променливата $x, а функцията ще ни върне квадрата на тази променлива. Ето как ще използваме функцията в главната програма:
$result = kvadrat( 5 );
echo $result; /*извежда 25*/
Има няколко правила при наименоването на функциите. Освен чисто програмните ограничения - името да не е по-кратко от 3 символа, да не започва с число, а със знак, да не е име на декларирана вече функция, да няма тирета и други специални символи в нея(само главни, макли букви, числа и долна черта са позволени), има и правила от чисто естетическа гледна точка. Първо името на функцията трябва да дава ясна идея за какво служи тя. Ако то не може да бъде изразено с една дума, използвайте или NameFunction или nameFunction или name_function. Така, човек четейки кода и виждайки непозната функция, може дори да не чете самата нея, защото името й ще говори точно какво прави тя. По същия начин се отнасяйте и към променливите. Променливи с имена $a, $b, $r, $f не говорят нищо за предназначението си и затрудняват разбирането на кода.
Понякога се налага да правим функции, в които не всички параметри се предават задължително. Тогава използваме стойност по подразбиране:
function kvadrat($x = 0)
{
return $x*$x;
}
Ако параметрите са повече от един, се записват, разделени със запетая и се извикват в същия ред. Предаването чрез указател или чрез параметър е възможност, чрез която може да връщате повече от един резултат. Ето как става това:
function increment(&$value , $amount = 1)
{
$value += $amount;
}
Тази функция не връща резултат, но променя входните данни. По този начин може да промените повече от една стойност. С ключовата дума return указвате край на функцията. Той може също да е преждевременен или във "ако то" конструкция.
Ако искате да използвате стойността на променлива, декларирана в главната програма, т.е. някъде в кода, а не във функция, ползвайте в тялото на функцията:
global $p;
Преди да завърша с възможностите на функциите, трябва да спомена и рекурсията. Това е метод, при който функция извиква себе си. Това е малко по-сложен тип алгоритми, но затова пък много ефективни. Нека направим функция с рекурсия, която изчислава n!
function nFact($n)
{
if ($n == 0 || $n == 1)
return 1;
else
return $n*nFact($n - 1);
}
Нека детайлно разгледаме тази функция. Първо, тя приема един параметър $n. Това ще е положително число или нула. Първо проверяваме дали това число не е едно или нула и в този случай връщаме 1. Ако това не е изпълнено, извикваме същата функция и връщаме резултата от нея, умножен по това число $n. Нека видим как ще работи алгоритъмът при $n = 3. При първото извикване, условието е лъжа. Т.е. извикваме функцията с параметър 2. Първото извикване не продължава работа, докато не получи своя резултат. При второто извикване условният оператор пак няма да изпълни условието и ще извика за трети път функцията с параметър 1. Това трето извикване ще върне резултат без да извиква повече функции - 1. Така второто извикване вече е получило стойност и може да върне резултат, т.е. то ще умножи 1*2 и ще върне 2. Първото извикване на функцията също вече получава резултат и умножава 2*3, т.е. крайния резултат е 6, което и трябва да бъде получено. Сигурно ви се струва малко объркано и трудно за съобразяване, но това е метод, който много помага при еднотипни изчисления, зависещи едно от друго. Помислете за упражнение върху редицата на Фибоначи - как може тя да бъде изчислена с рекурсия.
Това бяха възможностите на функциите, а сега нека видим как са се развили те в историята. Първоначално програмирането е било хаотично. Т.е. при зададена задача, се прави някакъв най-общ план как точно да се изпълни и се започва програмиране. Нямало е функции. След този период, се е установило, че така за програмирането на някой важни практически задачи, ще е нужно половината от населението на земята. Тогава се е родило структурното програмиране. То се състои в това, дадена задача да се раздроби на под задачи. Това раздробяване продължава до достигането на задачи, които са относително елементарни. Този тип програмиране все още се използва на много места при относително непроменящи се начални условия. В РНР този подход работи добре и е често използван, въпреки че масовото му използване при различни ситуации, може да доведе до проблемите, поради които това е все пак остарял метод. Всъщност, той е провалил редица важни за икономиката проблеми. Простата причина за провала е, че при разделянето на подзадачи, вие вземате точно условие и всяка подзадача зависи пряко от него. Във времето на изпълнението на проекта, може да се промени условието и често се оказвало, че заради минорни корекции, трябва да се пренапише целият проект. Така били загубвани 5 месеца и повече работа на стотици програмисти.
След структурното програмиране се е появил междинен етап - модулно програмиране. Т.е. част от задачите се отделят в модул, който не зависи от конкретните условия. Това е програма, която може да бъде изпълнена самостоятелно. От тази идея се е родило и за момента най-често използваното обектно ориентирано програмиране, за което ще говорим по-късно.
Нека се върнем сега в конкретния случай - езика РНР. За момента той е масово използван за създаване на уебсайтове, но вече започва и масовото му използване за вътрешни проекти. Далеч не е нужно РНР да бъде използван в интернет. Той работи много добре и във затворени мрежи. Порталните уебсайтове вече не са просто съвкупност от странички, а са цели завършени приложения със стотици редове код. Ето защо е важно да знаете от къде са тръгнали първите програмисти и накъде вървят нещата в програмирането. Целта ми в тези статии е не просто да ви изтрелям поредния наръчник, от който да вземете някаква основа, от която да имате минимална полза, а да дам полезна съвкупност от статии, за това как да постигнете най-добри резултати и най-бързо да извървите пътя от начинаещ уеб програмист, до познаващ из основи програмирането професионалист.
Силата ви на програмисти зависи от това до колко бързо и ефективно може да решавате поставена задача. Казано по друг начин, да използвате един и същ код на повече места. Защо функцията дадена за пример за намирането на квадрат на число е лошо обмислена функция? Защото намира квадрат, а ако някой утре ви каже че трябва да изчислите обем на куб, ще се наложи да напишете нова функция. Ето защо правим следната модификация на горната функция:
function stepen($value, $step)
{
$result = 1;
for ($i = 1; $i <= $step; $i++)
$result *= $value;
return $result;
}
Какво прави тази функция? Умножава толкова пъти параметъра $value със себе си, колкото е числото $step. Т.е. тази функция намира n-та степен на дадено число. stepen($x,2); ще е всъщност примерната ни функция за намиране на квардат. А ако някой ви поиска обем на куб ще ползвате stepen($strana, 3); Не пренаписвате нищо. Ако при всяка задача вие създавате функция, която има и по-общо използване, с времето ще имате множество файлове с функции и ще използвате само тези, които са необходими. Така времето за изпълнение на даден проект ще се сведе до минимум.
В първия урок загатнах една функция - include(); Това е може би най-мощният ви инструмент. Тази функция добавя съдържанието на друг файл на мястото, на което е извикана. Т.е. създавате един файл functions.php и в него поставяте всички функции, които сте написали и сте сигурни че работят. Когато ви потрябват просто пишете:
include('functions.php');
и вече може да ги ползвате. Това е и начина, по който може да реализирате модули в РНР. Файлове, изпълними самостоятелно, които могат да бъдат добавяни в други приложения.