Решил я намедни задачку и, похоже, красиво. Может, кто заинтересуется. Организации, как известно, плодят всякие бланки для распечатки и/или высылки по почте. Как те, которые требует родное государство, так и сочинённые самостоятельно для пользы дела. И очень хотят, чтобы их рабочая программа также их выплёвывала. Если нужен один-два бланка -- можно написать код, который их будет генерить. Но если их МНОГО - тогда нужно решение, подобное тому, что придумал я. В основе, разумеется, до блеска обсосанная на этом форуме шаблонизация. Но, как мне кажется, всё же с изюминкой. Изюминка - это абстрактный класс printable - в котором есть вся функциональность для генерации бланка. Если объект хочет генерить бланки - ему всего лишь надо унаследоваться от printable. А шаблон представляет собой HTML-файл с разметкой - особенность которой в том, что в качестве маркеров выступают имена свойств и методов класса-наследника printable. на место которых ставится текст, который они возвращают. И есть два режима формирования бланка -- редактирование и печать. Это делается затем, чтобы бланк можно было отредактировать перед сохранением, не меняя ничего в базе данных. * * * Ну вот я изложил главное содержание идеи. Но я её год откатывал - занимаясь мелочами. И теперь мне даже самому нравится, как всё это работает. Так что могу ответить на вопросы и по этим мелочам.
Ну сам класс 711 строк, и в основном банальности (типа чтения файлов в папке и выведение их в SELECT). Я покажу методы, которые заменяют маркеры в шаблоне на значения. Вот примеры таких маркеров: ##status## -- заменяется на свойство status, изменить при редактировании бланка нельзя %%status%% -- заменяется на свойство status, изменить при редактирвоании бланка можно ##output(2)## -- заменяется на результат метода output(), изменить при редактировании бланка нельзя %%output(2)%% -- заменяется на результат метода output(), изменить при редактировании бланка можно Думаю, логика ясна. А теперь методы класса printable PHP: //------ Формирование html-коду бланка--------------------------------- public function blank($mode=self::printer) { $this->blank_folder(); // получение папки с шаблонами $file=$this->template_folder().'/index.html'; $html=file_get_contents($file); //получение html-кода шаблона if($html===false) { return 'Error of reading '.$file; } /* После редактирования данные для подстановки вместо маркера хранятся в сессиях. Классам-детям даётся возможность изменить отцовскую логику обработки этих значений: */ $this->modify_session($mode); //Заменяем маркеры методов $html=$this->blank_methods($html,$mode); //Заменяем маркеры свойств $html=$this->blank_properties($html,$mode); //Скореректируем путь к имиджам, которые ставит редактор tiny_mce $html=preg_replace('/src="tiny_mce/','src="../../../../tiny_mce',$html); //При формировании HTML-кода для редактирования иногда приходится "фиксировать" места для кнопок //При печати мы убираем такие "гнёзда" для кнопок из HTML-кода шаблона if($mode==self::printer) { $html=preg_replace('/@@submit@@/','',$html); $html=preg_replace('/@@anchor@@/','',$html); } return $html; } PHP: //---------------- Заменяем маркеры методов ---------------------------- protected function blank_methods($html,$mode) { $html=$this->blank_methods_noedit($html); $html=$this->blank_methods_edit($html,$mode); return $html; } PHP: //---------- Заменяем маркеры методов без поддержки редактирования --------------------------------- protected function blank_methods_noedit($html) { $re="/##(([a-z_]\w*)\(([^()]*)\))##/i"; preg_match_all($re,$html,$m,PREG_SET_ORDER); /* -==СОСТАВ МАССИВА $m==- перший індекс -- номер знайденої відповідності $m[i][0] -- полный текст маркера $m[i][1] -- название метода с аргументами в скобках $m[i][2] -- ім'я метода (без скобок) $m[i][3] -- аргументы метода (без скобок) */ for ($i=0;$i<count($m);$i++) { $eval="\$replacement=\$this->".$m[$i][1].";"; eval($eval); $html=str_replace($m[$i][0],$replacement,$html); } return $html; } PHP: //----------- Замена маркеров методов с поддержкой редактирования ----------------------------- protected function blank_methods_edit($html,$mode) { $re="/%%(([a-z_]\w*)\(([^()]*)\))%%/i"; preg_match_all($re,$html,$m,PREG_SET_ORDER); /* -==СОСТАВ МАССИВА $m==- перший індекс -- номер знайденої відповідності $m[i][0] -- полный текст маркера $m[i][1] -- название метода с аргументами в скобках $m[i][2] -- ім'я метода (без скобок) $m[i][3] -- аргументы метода (без скобок) */ for ($i=0;$i<count($m);$i++) { $replacement=$this->blank_methods_edit_one($html,$mode,$m[$i][1]); $html=str_replace($m[$i][0],$replacement,$html); } return $html; } PHP: //-------- HTML-код для замены одного маркера с поддержкой редакт-ия ---------------------------------- protected function blank_methods_edit_one($html,$mode,$method) { $one=''; $default=''; $session=$this->method_session_index($method); if(isset($_SESSION[$session])) { $default=$_SESSION[$session]; } else { $eval="\$default=\$this->".$method.";"; eval($eval); $default=$this->special_m_default($default,$method); // Чтоб дети могли подсуетиться с содержанием по умолчанию $_SESSION[$session]=$default; } switch ($mode) { case self::form: $button="<input type="button" id="m_".preg_replace('/\(\)/','',$method)."" style="color:blue;background:yellow" value="Edit" onclick=" var url='http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['REQUEST_URI'])."/blank_edit.php?session=$session'; w_blank=self.open(url,'w_blank','top=50,left=50'); if(w_blank != null) { w_blank.focus(); } " />"; //Поищем "якорь" для кнопки $re='/@@anchor@@/'; if(preg_match($re,$default)) { $one=preg_replace($re,$button,$default); } else { $one=$default.$button; } break; case self::printer: $one=$default; break; } return $one; }
Да я бы поделился - но у меня нет "автономного" кода этого проекта. Его нужно "с мясом" вырывать из своей поделки, писать комментарии (кстати, к представленному коду только что написал...), писать доку, примеры применения -- и всё равно останется много вопросов. Я проиллюстрировал только идею - которая, как я надеюсь, полезна тому, кто её оценит и реализует для себя. По-своему. А я бы помог ответами на много "мелочных" вопросов.