Вопрос, наверное, глупый. Нужен скрипт галереи. Вот как лучше поступить: писать свой, или переработать готовый под свои нужды. Полностью готовый не хочу. Пытался разобраться с singapore-0.10.1 но пока для меня сложновато. Может вы посоветуете с чего начать. Скрипты писал раньше, но как-то кострубато выходит все, некрасиво Но впринципе, работет.
В быдлокоде (95% бесплатных галлерей) бывает разбираться себе дороже, если нужна глубокая интеграция в сайт, проще, конечно, написать.
Тем более, если буду писать сам с вкипте будет только то что мне нужно и ничего другого. Сам php сейчас изучаю, кое-что уже знаю. Как бы сказать, не совсем хорошо представляю саму "логику" написания скрипта. Где можно почитать? Как я понял изученим готовых скриптов -- не стоит.
По мне так на проектирование системы открыла дорогу книга PHP5 для профессионалов Эд-Леки Томпсон, ..... Есть баги но всё же ....
Думаю, что в процессе написания - возникнет масса вопросов. Остается надеяться только на вашу помощь. Сразу вопрос: лучше создать класс, или на отдельных функциях? Скажем, кроме галереии будут и другие рубрики. Думаю разумно написать один раз форму и скрипт для комментариев и использовать во всех рубриках. Разница будет только в базе данных, в которую производиться запись данного комментария.
для начала лучше функции. ООП требует несколько другого подхода и мышления, желательно перед этим иметь просто опыт программирования.
Все-таки решил на классах. Смастерил пока 2. Первый PHP: <?php /************************************************* * ek-image 1.0 * by: Юхименко Игорь * e-mail: [email=igor@ekklesiast.org.ua]igor@ekklesiast.org.ua[/email] *************************************************/ if ((!defined ('ROOT_DIR'))||(ADMIN!==-1)) { die ('Internal error'); } require_once ROOT_DIR."set/config.php"; class ekio { var $id; //индетификатор ресурса var $res; //индетифокатор запроса function open() { global $database; echo $database; if (!$this->id) $this->id = sqlite_open($database); } function getName() { return "SQLite"; } function query($query) { $this->res= sqlite_query($this->id, $query); return $this->res; } function exes($query) { sqlite_exec($this->id, $query); } function escape_string($query) { return sqlite_escape_string($query); } function fetch_single() { return sqlite_fetch_single($this->res); } function fetch_array() { return sqlite_fetch_array($this->res); } function fetch_array_asinc($res) { return sqlite_fetch_array($res); } function fetch_all () { return sqlite_fetch_all($this->res); } function num_rows() { return sqlite_num_rows($this->res); } function error() { return sqlite_error_string(sqlite_last_error($this->id)); } function close() { return sqlite_close($this->id); } } ?> Использую так PHP: <?php /************************************************* * ek-image 1.0 * by: Юхименко Игорь * e-mail: [email=igor@ekklesiast.org.ua]igor@ekklesiast.org.ua[/email] *************************************************/ //Установлен ли базовый путь? if ((!defined('ROOT_DIR'))|| (ADMIN!==-1)) { die ("Internal error!"); } require (ROOT_DIR."includes/io.php"); //---------------------------------------------------------------------// // // //========== Главный класс адиминистратирования =======================// //====== Содержит все функции для работы с галереей ===================// // // //---------------------------------------------------------------------// class ekimage extends ekio { function readfoto () { $this->open(); $addquery.=!empty($_GET['type'])? " AND types.type_name='$type' ":""; $addquery.=!empty($_GET['user'])? " AND fotos.user='$user' ":""; //Узнать количество записей $count_query="SELECT COUNT(*) from fotos LEFT JOIN types ON (fotos.type=types.id) WHERE types.id>0".$addquery; $this->query($count_query); //запрос на количество данных $datacount=$this->fetch_single(); //получаем количество данных в базе $pages=ceil($datacount/$perpage); //Количество страниц $p=(isset ($_GET["p"]))? $_GET["p"] : 1; //Установлено ли? $p=($p>0)?$p : 1; //Коректировка, страница меньше 1 $p=($p>$pagecount)? $p=$pagecount : $p; //Больше количества страниц $lp=$p; $lp--; $offset=$lp*$perpage; //Строка запроса $query="SELECT * FROM fotos LEFT JOIN types ON (fotos.type=types.id) WHERE types.id>0".$addquery." LIMIT $perpage OFFSET $offset "; $this->query($querty); $fotoarray=$this->fetch_all (); } function deletetype($id) { if ($id<1) {return "Ошибка удадения"; $this->open(); $this->query("select * from types WHERE id='$id'"); $is_ext=$this->fetch_single(); if (empty($is_ext)) { $this->exes("delete * from types WHERE id='$id'"); } else return "Категоря не пуста"; } function deletefoto ($arr) { $this->open(); $count=count($arr); for ($r=0; $r<$count; $r++) { //удаляем все комментарии $this->exes("delete * from coments WHERE link='$r'") //Получим имена всех файлов $this->query("SELECT fotos.id, fotos.filename, types.path FROM fotos LEFT JOIN types ON (fotos.type=types.id) WHERE fotos.id='$r'"); $arr=$this->fetch_array(); $this->deleteparticle[$arr['fotos.filename'], $arr['types.path']); $this->exec("delete * from fotos WHERE id='$r'"); } $this->close(); } function readtypes() { $this->open(); $query="SELECT * FROM types"; $this->query($$type_query); $types=$this->fetch_all(); $this->close(); return $types; } function create_db() { $this->open(); echo $this->database; //Создаем таблицу с описанием видов альбомов $this->exes ("Create table IF NOT EXISTS types (id integer primary key, path TEXT, type_name TEXT, type_deskr TEXT, user_add TEXT, user_visible TEXT, type_date TEXT, reserv1 TEXT)"); //Таблица с путями $this->exes ("CREATE TABLE fotos (id integer primary key, type TEXT, filename TEXT, name TEXT, user TEXT, data TEXT, ip TEXT, size TEXT, resolution TEXT, description TEXT, loaded TEXT, reserv1 TEXT, reserv2 TEXT)"); //Таблица комментариев $this->exes ("CREATE table coments (id integer primary key, link INTEGER, comment TEXT, user TEXT, data TEXT, ip TEXT, admin_coment TEXT, admin_data TEXT)"); $this->close(); } } ?> Стоит ли двигаться в таком направлении, или код никуда не годиться. Дальше: как лучше подключить файл параметров (имя базы данных, пути для хранения фоток, для уменьшенных копий и т.д.)
Мне кажется лучше было бы не расширять класс а получить в конструкторе ссылку на обьект класса БД, а потом присвоить закрытой переменной и манипулировать методами класса БД. Ещё лучше, наверное сделать класс БД статическим и все методы его статические, так как он не требует инстанцирования экземпляра. Если будут другие рубрики то следует продумать общие методы с другими рубриками админки.
PHP: <?php class DB_Mysql { protected $conn=null; protected $Host; protected $User; protected $Pass; protected $Database; public function __construct($DB_Host, $DB_User, $DB_Pass, $DB_Database) { $this->Host = $DB_Host; $this->User = $DB_User; $this->Pass = $DB_Pass; $this->Database = $DB_Database; } protected function connect() { if (is_null($this->conn)) { if (!$this->conn = @mysql_pconnect($this->Host, $this->User, $this->Pass)) { throw new Mysql_Exception(); } if (!@mysql_select_db($this->Database, $this->conn)) { throw new Mysql_Exception(); } } return true; } public function query($sql) { if (is_null($this->conn)) $this->connect(); // $ret = mysql_query($sql); if ($ret===false) { throw new Mysql_Exception($sql); } return new DB_Mysql_Statement($ret, $sql); } } class DB_Mysql_Statement { protected $Resourse; protected $query; public function __construct($resourse, &$sql=null) { $this->Resourse = $resourse; $this->query = $sql; } public function fetchRow() { return mysql_fetch_assoc($this->Resourse); } public function getQuery() { return $this->query; } public function fetchObject() { return mysql_fetch_object($this->Resourse); } public function numRows() { return mysql_num_rows($this->Resourse); } } class SQLException extends Exception { protected $query; function getQuery() {return $this->query;} } /** * Enter description here... * */ class Mysql_Exception extends SQLException { function __construct($query = null) { parent::__construct(mysql_error(), mysql_errno()); $this->query = $query; } } try { $db = new DB_Mysql(DB_HOST, DB_USER, DB_PASS, DB_DB); $rs = $db->query($sql)->fetchRow(); catch (SQLException $sqlException) { ?> <table width="50%"> <tr> <th colspan="2">SQL Exception</th> </tr> <tr> <td>Сообщение</td> <td><?php echo $sqlException->getMessage();?></td> </tr> <tr> <td>Запрос</td> <td><?php echo $sqlException->getQuery();?></td> </tr> <tr> <td>Код</td> <td><?php echo $sqlException->getCode();?></td> </tr> <tr> <td>Файл</td> <td><?php echo $sqlException->getFile();?></td> </tr> <tr> <td>Строка</td> <td><?php echo $sqlException->getLine();?></td> </tr> <tr> <td>trace</td> <td><?php echo $sqlException->getTraceAsString();?></td> </tr> </table> <?php }
Вот что я сделал: В io.php функцию open переименовал в __construct PHP: <?php function __construct() { global $database; if (!$this->id) $this->id = sqlite_open($database); } ?> Вот мне не нравиться global $database; как лучше "подключить" имя базы данных? (sqlite) А в самом admin_class такие функции как добавления нового альбома и т.д. Как лучше его имя передать в функцию аргументом, или сама функция должна прочитать его из _POST? Как более красиво и правильней?
можешь покапаться в phpc - http://phpc.ru он совместим с PHP4 так что чудес ООП не жди, зато там есть много других неплохих идей..
Подскажите, как сделать красивей. А ток получается очень запутанный. Вкратце: галлереи храняться в отдельной таблице Код (Text): id - Ид pId - Ид родителя name - Имя галлереи (можно русскими, любые символы (это то, что пишеться как ссылка)) path - Только латиница и цифры (Уникальное в даной подгалереи) для передачи GETом, чтобы не кодировать PHP: <?php //Функция получает информацию о текущей галлереи function getFolderInfo() { if ((isset($_REQUEST['gallery'])) && (!empty($_REQUEST['gallery']))) { $this->fullpath = $_REQUEST['gallery']; } else { $this->fullpath=""; $this->cId=0; $this->pId=0; return; } $prevId=0; $folderitems=split('/',$this->fullpath); $itemcount=count($folderitems); $this->folderpaths[-1]=""; for ($r=0; $r<$itemcount; $r++) { $this->pId=$prevId; $this->dbio->query("SELECT id, path from gallerys WHERE path='".$folderitems[$r]."' AND parent='$prevId' LIMIT 1"); $arr=$this->dbio->fetch_array(); if (empty($arr)) return false; $prevId=$arr['id']; //Это id текущего каталога, но за следующим проходом он станет родительським $this->folderpaths[$r]=$this->folderpaths[$r-1].'/'.$folderitems[$r]; $this->foldernames[$r]=$arr['path']; $this->cId=$prevId; } unset ($this->folderpaths[-1]); }?> Получаем инфу о текущей галлереи, ее ид, ид родителя PHP: <?php //Поличим информацию о всех потомках данной папки function getFolderChildrens() { $query="SELECT * FROM gallerys WHERE parent = '".$this->cId."' ORDER BY name"; $this->dbio->query($query); $this->childs=$this->dbio->fetch_all(); if ($this->hasParent()) { $count=count($this->childs); for ($r=0; $r<$count; $r++) $this->childs[$r]['path']=$this->fullpath.'/'.$this->childs[$r]['path']; } } //Получим всех сестёр для данной папки function getFolderSisters() { $query="SELECT path, name FROM gallerys WHERE parent = '".$this->pId."' ORDER BY name"; $this->dbio->query($query); $this->sisters=$this->dbio->fetch_all(); if ($this->hasParent()) { $count=count($this->sisters); for ($r=0; $r<$count; $r++) $this->sisters[$r]['path']=$this->parentpath.'/'.$this->sisters[$r]['path']; } } ?> Очень некрасиво получается Код (Text): if ($this->hasParent()) { $count=count($this->childs); for ($r=0; $r<$count; $r++) $this->childs[$r]['path']=$this->fullpath.'/'.$this->childs[$r]['path']; } Хоть подскажите, как лучше[/url]