Спустя 1 минута, 25 секунд (22.03.2011 - 21:02) sharki написал(а):
Код выкладывай =)
желательно в спойлере [spoiler ] [ /spoiler]
желательно в спойлере [spoiler ] [ /spoiler]
Спустя 6 минут, 27 секунд (22.03.2011 - 21:08) Invis1ble написал(а):
Первый опыт - и стразу ООП ??
Сильно... Ждем код
Сильно... Ждем код
Спустя 4 минуты, 38 секунд (22.03.2011 - 21:13) inpost написал(а):
Или PHP для ООП? Что было первым, курица или яйцо? Не понимаю смысла этого топика, хоть убейте!
Спустя 4 минуты, 50 секунд (22.03.2011 - 21:18) Invis1ble написал(а):
Скорее, если расшифровать аббревиатуру, логичнее "ООП на PHP"... Но это так, лирическое отступление... Вобщем, ждем.
Спустя 4 минуты, 4 секунды (22.03.2011 - 21:22) Гость_Игорь написал(а):
Ок)
Скажу сразу: это первое что я написал после 1 часа чтения мануала по PHP, поэтому ясно дело куча уязвимостей, интересует мнение по поводу самого подхода (использование ООП). Всего 3 файла: index.php (страница гостевой книги), DBase.php (работа с БД), Comments.php (модуль комментариев)
Скажу сразу: это первое что я написал после 1 часа чтения мануала по PHP, поэтому ясно дело куча уязвимостей, интересует мнение по поводу самого подхода (использование ООП). Всего 3 файла: index.php (страница гостевой книги), DBase.php (работа с БД), Comments.php (модуль комментариев)
Скрытый текст |
|
Спустя 6 минут, 31 секунда (22.03.2011 - 21:28) Invis1ble написал(а):
Сильно не вникал, но вот несколько замечаний:
1. Логика перемешана с представлением (и в классах и в "остальном" коде) - так не делается
2. Обработку ошибок лучше реализовывать посредством выброса и обработки исключений
3. mysql_fetch_array() без флага лучше не юзать, т.к. лишняя нагрузка. Или с флагом или mysq_fetch_assoc()
1. Логика перемешана с представлением (и в классах и в "остальном" коде) - так не делается
2. Обработку ошибок лучше реализовывать посредством выброса и обработки исключений
3. mysql_fetch_array() без флага лучше не юзать, т.к. лишняя нагрузка. Или с флагом или mysq_fetch_assoc()
Спустя 4 минуты, 49 секунд (22.03.2011 - 21:33) sharki написал(а):
Гость_Игорь
Ну так, не плохо
1) Можно не прописывать пустые конструкторы, они и так пустые по дефоулту
2) В классе комментариев можно передавать как раз таки в конструктор соединение с БД т.е
3) реализация комментариев т.е их вывод из бд лучше бы отдал бы индексу.пхп чтобы отделить логику от представления
4)Ну и конечно же можно было обойтись без лишних манипуляций с БД извне т.е
Можно было бы наследовать БД класс и всё, а там уже
Ну так, не плохо
1) Можно не прописывать пустые конструкторы, они и так пустые по дефоулту
2) В классе комментариев можно передавать как раз таки в конструктор соединение с БД т.е
....................................................
public function __construct($sql)
{
$this->sqlConnect = $sql;
}
...................................................
$comments = new Comments($sql);
3) реализация комментариев т.е их вывод из бд лучше бы отдал бы индексу.пхп чтобы отделить логику от представления
4)Ну и конечно же можно было обойтись без лишних манипуляций с БД извне т.е
public function Open($sql)
{
$this->sqlConnect = $sql;
}
Можно было бы наследовать БД класс и всё, а там уже
$this->sqlConnect = $this->sql;
Спустя 9 минут, 25 секунд (22.03.2011 - 21:43) Гость_Игорь написал(а):
Спасибо за замечания) Ну если выбранный подход имеет право на существование, буду допиливать, покажу потом что получилось)
Вообще мне показалось, что обычно в php классы как-то не особо используют. А так было бы здорово сделать framework чисто на ООП-принципах, каждый модуль (гостевая, коменнтарии, статья) - класс, отдельно классы для разных задач.
Насчет разделения логики и представления - полностью согласен, насколько мог, перетащил из index.php в классы, но как сделать еще явнее... Хотя, кажется, понял: в классах не должно встречаться ни единого echo )) А про то, что в PHP есть исключения, я не знал)
Вообще мне показалось, что обычно в php классы как-то не особо используют. А так было бы здорово сделать framework чисто на ООП-принципах, каждый модуль (гостевая, коменнтарии, статья) - класс, отдельно классы для разных задач.
Насчет разделения логики и представления - полностью согласен, насколько мог, перетащил из index.php в классы, но как сделать еще явнее... Хотя, кажется, понял: в классах не должно встречаться ни единого echo )) А про то, что в PHP есть исключения, я не знал)
Спустя 2 минуты, 4 секунды (22.03.2011 - 21:45) sharki написал(а):
Гость_Игорь
А ты просто функцией $comments->Fetch(); возвращай тот самый массив $rec, и всё, а в индексе тупо делай fetch_assoc
А ты просто функцией $comments->Fetch(); возвращай тот самый массив $rec, и всё, а в индексе тупо делай fetch_assoc
Спустя 24 секунды (22.03.2011 - 21:45) inpost написал(а):
Гость_Игорь
Гугл, фейсбук, википедия написаны были на процедурке, а не ООП.
Гугл, фейсбук, википедия написаны были на процедурке, а не ООП.
Спустя 3 минуты, 29 секунд (22.03.2011 - 21:49) Гость_Игорь написал(а):
Цитата (inpost @ 22.03.2011 - 18:45) |
Гость_Игорь Гугл, фейсбук, википедия написаны были на процедурке, а не ООП. |
вот это и не понятно.. может тогда в PHP еще не появились классы?
Спустя 1 минута, 2 секунды (22.03.2011 - 21:50) Гость_Игорь написал(а):
Цитата (sharki @ 22.03.2011 - 18:45) |
Гость_Игорь А ты просто функцией $comments->Fetch(); возвращай тот самый массив $rec, и всё, а в индексе тупо делай fetch_assoc |
Понял, ок)
Спустя 28 минут, 15 секунд (22.03.2011 - 22:18) inpost написал(а):
Гость_Игорь
Именно, гиганты сети сделаны на ПХП без использования ООП по той причине, что в PHP4 они ещё не существовали.
Именно, гиганты сети сделаны на ПХП без использования ООП по той причине, что в PHP4 они ещё не существовали.
Спустя 23 минуты, 33 секунды (22.03.2011 - 22:41) alex12060 написал(а):
А еще, советую делать константы private. А еще, можно унаследовать один класс от другого, это упростит код в 10-ки раз. А функции с работой в БД так-же можно сделать приватными и открывать соединение в конструкторе.
А так, для новечка неплохо.
А так, для новечка неплохо.
Спустя 21 час, 29 минут, 21 секунда (23.03.2011 - 20:11) Гость_Игорь написал(а):
Всем привет,
возникли мысли и вопросы)
1. Правильно ли я понимаю, что при выполнении php-кода страницы нужно каждый раз заново открывать соединение с MySql, открывать базу? Т.е. ВСЕ значения переменных в php живут только в рамках момента обновления страницы? Пробовал модификаторы static, global, массив $GLOBALS - не помогает, при обновлении страницы все стирается, например:
- всегда выдает 1, т.е. значение x стирается, хоть это и static. В С++ static живет пока не завершится процесс.
2. Если так, можно действительно от класса "База данных" наследовать все классы типа "Комментарии", "Статьи", "Цитаты" и пр. Подумал, что было бы удобно в каждый такой класс добавить метод с запросом CREATE TABLE, т.е. чтобы каждый раз не создавать таблицы через PhpMyAdmin (когда новая БД), запустил скрипт, который для каждого такого класса вызывает метод создания таблицы.
3. Думал как хранить меню, т.е. засунуть древовидную структуру в реляционную таблицу, чтоб число уровней вложенности не было ограниченно.
Пока пришла такая идея: каждый пункт меню - это 1 запись в таблице, есть поле "предок" и поле "потомок", где хранятся либо null, либо id другой записи в этой же таблице.
4. Можно ли вместо mysql_fetch_assoc делать mysql_fetch_object? (в смысле, что не будет ли это тормознее, просто этот способ более похож на ООП-подход).
возникли мысли и вопросы)
1. Правильно ли я понимаю, что при выполнении php-кода страницы нужно каждый раз заново открывать соединение с MySql, открывать базу? Т.е. ВСЕ значения переменных в php живут только в рамках момента обновления страницы? Пробовал модификаторы static, global, массив $GLOBALS - не помогает, при обновлении страницы все стирается, например:
<html>
<header>
<title>Лаборатория</title>
</header>
<body>
<?php
class Foo
{
private static $x = 0;
public function __construct()
{
$x++;
echo $x;
}
}
$foo = new Foo();
?>
</body>
</html>
- всегда выдает 1, т.е. значение x стирается, хоть это и static. В С++ static живет пока не завершится процесс.
2. Если так, можно действительно от класса "База данных" наследовать все классы типа "Комментарии", "Статьи", "Цитаты" и пр. Подумал, что было бы удобно в каждый такой класс добавить метод с запросом CREATE TABLE, т.е. чтобы каждый раз не создавать таблицы через PhpMyAdmin (когда новая БД), запустил скрипт, который для каждого такого класса вызывает метод создания таблицы.
3. Думал как хранить меню, т.е. засунуть древовидную структуру в реляционную таблицу, чтоб число уровней вложенности не было ограниченно.
Пока пришла такая идея: каждый пункт меню - это 1 запись в таблице, есть поле "предок" и поле "потомок", где хранятся либо null, либо id другой записи в этой же таблице.
4. Можно ли вместо mysql_fetch_assoc делать mysql_fetch_object? (в смысле, что не будет ли это тормознее, просто этот способ более похож на ООП-подход).
Спустя 8 минут, 59 секунд (23.03.2011 - 20:20) inpost написал(а):
Гость_Игорь
1. В начале выполнения скрипта конектиться к БД нужно, в конце скрипта, если сам не закрыл соединение, оно автоматически закрывается, для экономии места, ведь в Мускуле есть лимит одновременных соединений, поэтому загрузил страницу, закрылось соединение, теперь через него кто-то другой обращается к БД.
2. Зачем создавать таблицу? Комментарии, статьи, цитаты хранятся в ранее созданных таблицах, каждый комментарий имеет его id, и родителя, кому он принадлежит, можно ещё добавить из какого раздела и т.д., но это как строка в Таблице, а не новая отдельная таблица.
3. Нормальная схема для неограниченного меню.
4. Нет, делай, как тебе нравится больше, ты копейку потеряешь, даже смотреть в эту сторону не надо =)
1. В начале выполнения скрипта конектиться к БД нужно, в конце скрипта, если сам не закрыл соединение, оно автоматически закрывается, для экономии места, ведь в Мускуле есть лимит одновременных соединений, поэтому загрузил страницу, закрылось соединение, теперь через него кто-то другой обращается к БД.
2. Зачем создавать таблицу? Комментарии, статьи, цитаты хранятся в ранее созданных таблицах, каждый комментарий имеет его id, и родителя, кому он принадлежит, можно ещё добавить из какого раздела и т.д., но это как строка в Таблице, а не новая отдельная таблица.
3. Нормальная схема для неограниченного меню.
4. Нет, делай, как тебе нравится больше, ты копейку потеряешь, даже смотреть в эту сторону не надо =)
Спустя 1 час, 48 минут, 22 секунды (23.03.2011 - 22:08) Гость_Игорь написал(а):
Постарался учесть замечания) Только почему-то не получается сочетать модификаторы const и private.
///////////////// Guard.php - набор функций для защиты //////////
<?php
class Guard
{
// Обработка пользовательского текста
static function TextProceed($text)
{
$text = stripslashes($text);
$text = htmlspecialchars($text);
return $text;
}
// Валидация e-mail'а
static function CheckEmail($email)
{
return (preg_match("/[0-9a-z_]+@[0-9a-z_^\.]+\.[a-z]{2,3}/i", $email));
}
// Проверка, что запрос произошел с нашего хоста
static function CheckHost()
{
$hostOwn = "http://";
$hostOwn.= $_SERVER["HTTP_HOST"];
$hostFrom=getenv("HTTP_REFERER");
if (!ereg($hostOwn, $hostFrom))
{
throw new Exception("Попытка взлома.");
}
}
}
?>
//////////// Table.php - базовый для всех классов-таблиц //////////
<?php
class Table
{
private $dbhost = "localhost";
private $dbuser = "root";
private $dbpswd = "";
private $dbname = "UP";
protected $sqlConnect;
/// Открывает sql и БД
public function __construct()
{
$this->sqlConnect = @mysql_connect($this->dbhost, $this->dbuser, $this->dbpswd);
if (!$this->sqlConnect)
{
throw new Exception("Ошибка подключения к серверу MySQL.");
}
if (!@mysql_select_db($this->dbname, $this->sqlConnect))
{
throw new Exception("Ошибка при открытии базы данных." );
}
}
/// Закрывает sql
public function __destruct()
{
if(!mysql_close($this->sqlConnect))
{
throw new Exception("Не удалось завершить соединение с сервером MySQL");
}
}
}
?>
//////////////// Comments.php - работа с комментариями /////////
<?php
require_once("Table.php");
require_once("Guard.php");
class Comments extends Table
{
private $querryFetch;
public function Add($Name, $Email, $Text)
{
// Данные от формы получены с этого хоста?
Guard::CheckHost();
if (!Guard::CheckEmail($Email))
{
return;
}
$querryStr = sprintf("INSERT INTO Comments (Text) VALUES (\"%s\");", Guard::TextProceed($Text));
$querry = mysql_query($querryStr, $this->sqlConnect);
if(!$querry)
{
throw new Exception("Ошибка добавления значения в БД запросом ".$querryStr.", описание:".mysql_error());
}
// Защита от флуда
sleep(1);
}
public function BeginFetch()
{
$this->querryFetch = mysql_query("SELECT * FROM Comments;", $this->sqlConnect);
if(!$this->querryFetch)
{
throw new Exception("Ошибка выборки комментариев: ".mysql_error());
}
}
public function Fetch()
{
if($this->querryFetch)
{
return mysql_fetch_object($this->querryFetch);
}
}
public function EndFetch()
{
$this->querryFetch = null;
}
}
?>
/////////////////////////// index.php //////////////////////////////
<html>
<header>
<title>Гостевая книга</title>
</header>
<body>
<table border="0" width="100%" height="100%">
<tr>
<td width="25%"></td>
<td width="50%" valign="top">
<?php
try
{
// Загрузка комментариев
require_once("Comments.php");
$comments = new Comments();
// Если есть новый - добавляем
$newComment = $_GET[AddText];
if($newComment)
{
$comments->Add("Igor", "igor@mail.ru", $newComment);
echo "<HTML><HEAD>\n";
echo "<META HTTP-EQUIV='Refresh' CONTENT='0; URL=index.php'>\n";
echo "</HEAD></HTML>\n";
}
$comments->BeginFetch();
while($rec = $comments->Fetch())
{
echo ($rec->Text);
echo "<br>";
}
$comments->EndFetch();
}
catch(Exception $e)
{
echo 'Исключение: ' . $e->getMessage();
}
?>
<form action = "index.php" method="get">
<TEXTAREA NAME="AddText" WRAP="virtual" COLS="40" ROWS="3"></TEXTAREA><br>
<input type="submit"/>
</form>
</td>
<td width="25%"></td>
</tr>
</table>
</body>
</html>
Спустя 4 дня, 9 часов, 52 минуты, 36 секунд (28.03.2011 - 07:01) Igorian написал(а):
Привет всем)
Прошу совета по вопросам архитектуры web-приложений.
Сделал так: архитектура сайта состоит из модулей (отображение статьи, отображение гостевой, отображение голосовалки и т.п.), каждый модуль лежит в своей папке и состоит из 3 файлов:
-view (почти чистый html)
-model (доменный объект, т.е. ООП-обертка над MySQL, например для Guestbook методы "Добавить запись", "Выбрать записи")
-controller (управляет предыдущими, т.е. обрабатывает get-запрос, дергает методы model, запускает view).
model и controller - статические классы.
Есть основное ядро сайта (как и все остальное - тоже класс). Например, юзер хочет зайти в гостевую. По get-запросу ядро понимает, что нужно активировать модуль Guestbook, оно вызывает у него метод Render, он возвращает результат работы. Используется ob_get_contens. Потом запускается файл шаблона сайта, который содержит именнованные области, например <?=main?>. Результат рендера модуля был записан в $main, а тут это все подставляется в шаблоне. Можно было бы конечно наоборот: в шаблоне дергать у логики работу модуля, но это не логично: код первичнее представления.
Как такой вариант? Особенно интересует вопрос использования ob_get_contens, нет ли там ограничений на размер результата, и насколько это нормально: рендерить скрипт не сразу на вывод, а в буфер, а потом этот буфер подставлять в шаблоне?
Прошу совета по вопросам архитектуры web-приложений.
Сделал так: архитектура сайта состоит из модулей (отображение статьи, отображение гостевой, отображение голосовалки и т.п.), каждый модуль лежит в своей папке и состоит из 3 файлов:
-view (почти чистый html)
-model (доменный объект, т.е. ООП-обертка над MySQL, например для Guestbook методы "Добавить запись", "Выбрать записи")
-controller (управляет предыдущими, т.е. обрабатывает get-запрос, дергает методы model, запускает view).
model и controller - статические классы.
Есть основное ядро сайта (как и все остальное - тоже класс). Например, юзер хочет зайти в гостевую. По get-запросу ядро понимает, что нужно активировать модуль Guestbook, оно вызывает у него метод Render, он возвращает результат работы. Используется ob_get_contens. Потом запускается файл шаблона сайта, который содержит именнованные области, например <?=main?>. Результат рендера модуля был записан в $main, а тут это все подставляется в шаблоне. Можно было бы конечно наоборот: в шаблоне дергать у логики работу модуля, но это не логично: код первичнее представления.
Как такой вариант? Особенно интересует вопрос использования ob_get_contens, нет ли там ограничений на размер результата, и насколько это нормально: рендерить скрипт не сразу на вывод, а в буфер, а потом этот буфер подставлять в шаблоне?