Правилно структуриране на PHP
07-03-2012
Здравейте туристи.

Забелязал съм, че доста от вас ползвате ob_start(); и маскиране на грешките в кодовете. В този урок ще се опитам да ви обясна какво представляват тези 2 метода който ползвате и как да ги избягваме, също така и как да структурираме правилно един код, за да бъде той по четлив и оптимизиран.

-----------------------------------------


Първо да започнем с какво представлява ob_start();

- ob_start(); (output buffering) е функция която, чете целият ви написан код и го пренарежда по стандартите. Обаче това си има и своят минус.

Разгледайте го така: За да ви зареди страница която вие сте избрали и на нея се съдържа тази функция, то първо страницата се зарежда от функцията (1 път), после кода се нарежда (1 пъти) и най-накрая се изпълнява през функцията, тоест един вид страницата ви се презарежда 3 пъти, това означава ли, че функцията ви забавя страниците x3 ? Да, забавя е и то значително при по-големи файлове с повечко код.


- Пример за ob_start();:


<?php
echo 'some text';
session_start();
echo 'some more text';


Този код по стандарт, би ни изкарало грешка от типа: "headers already been sent".


Но ако го напишем:


<?php
ob_start();
echo 'some text';
session_start();
echo 'some more text';


Грешка няма да получим, заради това, че функцията ни пренарежда кода, по ето този вариянт (давам като пример да разберете как работи самата функция) :

<?php
session_start();
echo 'some text';
echo 'some more text';


Но, за да се получи тази структура, трябва да се изпълни:
1. Преглед на целият код.
2. Нареждане на кода.
3. Показване на готовият за вас вид на кода през функцията.

Малко по-надолу в урока ще ви обясна защо дава тази грешка с headers и как да е избегнем без ob_start();




-----------------------------------------


"Скриване на грешки"

- Скриването на грешки не ви решава проблемите!

Скриване на грешки от типа:

error_reporting(0)
@
И премахване от php.ini

Говорят само за един доста на бързо написан и не добре структуриран код, може и в някой моменти да се говори дори и за не добре защитен код.



- Защо да не премахваме грешките?
Грешките са тези който в даден момент ти помагат да разрешиш даден проблем, който всъщност не можеш да откриеш в случай, че си стартирал функциите за "маскиране" на грешки.

- Забавя ли зареждането на страницата ви?
И това както и ob_start(); Забавя зареждането на страницата.

- Как да не пропускаме грешки?
-----
Като за начало не слагайте функции като error_reporting(0) за маскиране на грешките, защото вие не подобрявате кода, а го забавяте още и грешките са в сила все още.

"@" - Маймунското "А". Предполагам всички знаете, че ви скрива грешки възникнали на даден ред от кода. Как да го избягваме?
Това става с проверки if .. else

Пример за взимане на информация от форма:


if($_POST['submit']) {
//код
}


При този вариянт ако всичко на хоста ви е по "defalut" (както се нарича), ще получите грешка при първоначално стартиране на кода: Unidentified variable.
Защото променливата $_POST не се е индентифицира никъде. Обаче при натискане на бутона "submit" тази грешка, ще ви изчезне, защото вече ще е индентифицирана.

Сега тази грешка може да бъде маскиране с "@" ето така:


if(@$_POST['submit']) {
//код
}


Но, това не ви решава проблема, грешката продължава да е в действие, макар че не се показва.

Обаче за пълното решение на този проблем, може да ползваме функцията "isset()", тази функция проверява дали тази променлва е индентифицира и ако не е връща "false" и проверката минава за невалидна, а не да върне грешка.

Ето така:


if(isset($_POST['submit'])) {
//код
}


Разбира се тази функция, може да се ползва и за други променливи (глобални и не глобални).

----

Пример за още един вид маскиране с "@" или с "error_reporting(0)".
Е когато изкарвате информация от даден файл. И ако този файл не съществува ви връща грешка.

Винаги може и на него да се направи проверка от този тип:
if (file_exists($filename)) {echo 'file exist'}


----

Като правило е да описвате всичко което правите. Да проверявате дали дадено нещо съществува дали е индентифицирано, ако дадена функция да кажем не връща стойност, трябва да и зададем нещо като алтернатива в този случай, като пример "null" стойност.

Мисля, че до тук разгледахме в общи линии за грешките, и тяхните маскирания като ob_start(); и маскиране на грешките.



Правилно структуриране на кода, за избягване на грешки и ob_start();

- Сега разглеждайте един файл да кажем index.php като 2 части.
1. - ва: PHP кодът (който седи най-отгоре на страницата).
2. - ра: HTML кодът (който седи надолу в страницата).

- Когато пишете вашият код смесено като пример:


<html>
<head></head>
<body>
<h2>Hello</h2>
<?php
session_start();
$_SESSION['smth']='text';
?>
</body>
</html>


Това ще ви върне грешка, че "headers already been sent" - в превод, че имаш вече изпратена сървърна информация към клиента (не съм със сигурност дали това е точното определение).

Тази грешка се дължи на това, че преди session_start(); Имаш написани тагове или текст. И следователно щом имаш написани тагове или текст, всичко след първият ТАГ или ТЕКСТ не се счита вече за тази "първоначална информация която се праща към клиента" и когато дойде реда на session_start(); сървъра се опитва да изпрати информация за стартиране на сесии, обаче няма как да се стартират сесиите, тъй като те се водят от този вид "първата информация (сървърната)" и се връща грешка.

Сега как да избягваме този вид грешки:

1. -во: Запомнете, че всички функции свръзани към headers (главните части), се пращат преди всеки таг или текст (тоест те се пишат първи в файла).

Примера от горе, без никъкви грешки, ще изглежда така:


<?php session_start(); ?>
<html>
<head></head>
<body>
<?php
echo '<h2>Hello</h2>';
$_SESSION['smth']='text';
?>
</body>
</html>


Сега написах "<h2>Hello</h2>" в PHP и ECHO, какво искам да ви кажа:
Някой ползват ето този стил на писане:

<?php //kod ?><img src='<?php echo 'some text' ?>' height='<?php echo $width ?>' width='100px' /><?php //kod ?>


Не казвам, че е лошо. Но просто е нечетливо, и може би това отваряне затваряне на PHP, забавя до някъква степен кода (не съм сигурен за това със забавянето, ! мое предположение !).
Искам да ви каже, че иматели динамични места като примерно този код за снимки е хубаво целият ред да бъде вкаран в echo.

------

2. -ро: Сега едно от важните неща за структуриране на кода е имено това как да разделите PHP от HTML.

- Като за начало искам да почна с това, че над <html> тага се извършват всички действия който желаете да бъдат извършени с PHP - там няма echo "" да пускате и други видове показване на текст. Само действията. Самото показване става в <body> ТУК </body>. Като информацията ще е прехвърляте с променливи. Това помага на действия като header(); за препращане и помага за по нагледен код. Също така това, ще бъдат действия който браузера ще зареди първи и от там надолу страницата няма да ви забавя своето отваряне.

Ето пример за една POST форма за коментари да кажем:



<?php
session_start();

if(isset($_POST['submit'])){

$greshka=array();
if(empty($_POST['name']) || empty($_POST['komentar']))
{$greshka['1']=true;}

else {
$inrow=mysql_query("INSERT INTO");
if($inrow)
{
header("Location: index.php");
exit;
}
}

}
?>
<html>
<head></head>
<body>
<form method='post' action='index.php'>
<br>
<input type='text' name='name' />
<br>
<textarea name='komentar' rows='20' cols='10' ></textarea>
<br><br>
<input type='submit' name='submit' value=' SEND ' />
<br>
</form>
<?php if(isset($greshka['1'])) {echo 'Не може да оставяте празни полета';} ?>
</body>
</html>



Ето как изпълних този код:
В началото на файла проверявам дали формата е изпратена ако е изпратена, проверявам дали полетата са празни ако не са - записвам в базата данни и препращам към index.php (тоест към същият файл). Сега ако са празни полетата, не слагам echo веднага ами го вкарвам в променлива или в масив ако са повече грешки и го зареждам долу под формата.
Написал съм и също в началото един session_start(); - в този момент не ми трябва, но искам да ви покажа къде трябва да му е мястото.

Разбира се ако дори напишете всичко след <html> (заедо с него) в едно "echo", няма да се счита за грешка. Избягвайте само постоянното отваряне и затваряне на "<?php" "?>".

---------------------------

Мисля, че е това е достатъчно. Оставяйте коментари, сигнализирайте ако имам грешки и се надявам да съм помогнал на поне някого.










/ Трябва да сте регистриран за да напишете коментар /
От: dakata__92
12:01 13-03-2012
Полезен урок, особено за ob_start(); ! Браво :]
От: tedo96
17:45 16-03-2012
Ако ползвате MVC няма да имате никакви проблеми! Иначе урока е добър. :)
От: MaLa_NocHe
22:28 23-05-2012
Не съм съгласен че кода се забавя или е грешно вкарването на в хтмл кода, даже си е доста по-удобно и бързо действащо.
От: dakata__92
20:14 09-07-2012
MaLa_NocHe - нечетливо е, а и нищо не ти пречи да генерираш целия html с echo и да имаш само веднъш отворени ! Така спокойно си сваляш променливите без да отваряш нан ново работите :)
1