фреймворки мне не нравились наверно полтора 2 года назад, пока я не написал свой микроговнофреймворк.
в и тоге оказалось что наличие такого инструмента значительно ускоряет процесс развёртывания любого проекта от визитки до не стандартного сайта, какой нить системы аналитики или т.д.
в моём фреймворке всё просто
есть индексный файл в котором происходит автоинклуд классов в том числе подключение базовых контроллера и модели
он основан на MVC
для создания новой группы модели контроллера и шаблона есть отдельный раздел в котором через форму указывается имя нового раздела (название файлов) и к какой части этот раздел относиться - к пользовательской или административной
т.е. структура папок под эти моменты выглядит так
app/
--controllers
----admin
--models
---admin
--tpls
---admin
при создания нового раздела сразу создаются 3 файла -
контроллер name_controller.php
модель name_model.php
шаблон name.tpl
контроллер и модель сразу содержат коды классов по имени файлов, получается:
class Name extends BaseControllel{
.....
}
class Name extends BaseModel{
.....
}
код нового шаблона - это начальная HTML разметка
в итоге от нужного параметра в урл происходит вызов тех или иных групп файлов (mvc)
в случае необходимости обработки до. параметров из url - я пишу до. логику
пример контроллера
<?php
class ServicesController extends BaseController{
public function __construct(){
parent::__construct();
}
public function getListServices(){
$result = $this->model->getListServices();
if($result['success'] === false){
return (array('errors'=>array($result['error'])));
}
else{
return (array('totalCount'=>$result['total'], 'listServices'=>$result['listServices']));
}
}
public function getServicesOrders(){
$result = $this->model->getServicesOrders();
return $result;
}
public function getListGroupsServices(){
$result = $this->model->getListGroupsServices();
if($result['success'] === false){
Bufer::add(array('errors'=>array($result['error'])));
}
else{
$emptyGroupsServices = array(array('gsrvid'=>0, 'gsrvname'=>''));
$result['listGroupsServices'] = array_merge($emptyGroupsServices, $result['listGroupsServices']);
Bufer::add(array('listGroupsServices'=>$result['listGroupsServices']));
}
}
public function addServices($data){
$result = $this->model->addServices($data);
return $result;
}
public function editServices($data){
$result = $this->model->editServices($data);
return $result;
}
public function deleteServices($data){
$result = $this->model->deleteServices($data);
return $result;
}
}
$controller = new ServicesController;
$controller->setModel('Services');
if(isset($_GET['m']) && $_GET['m'] == 'getListServices'){
$result = $controller->getListServices();
echo json_encode($result);
exit;
}
if(isset($_GET['m']) && $_GET['m'] == 'getServicesOrders'){
$result = $controller->getServicesOrders();
echo json_encode($result);
exit;
}
if(isset($_GET['m']) && $_GET['m'] == 'editServices'){
$data = array(
'srvid'=>$_POST['srvid'],
'srvname'=>$_POST['srvname'],
'srvshortname'=>$_POST['srvshortname'],
'srvprice'=>$_POST['srvprice'],
'gsrvid'=>$_POST['gsrvid'],
);
$result = $controller->editServices($data);
echo json_encode($result);
exit;
}
if(isset($_GET['m']) && $_GET['m'] == 'addServices'){
$data = array(
'srvname'=>$_POST['srvname'],
'srvshortname'=>$_POST['srvshortname'],
'srvprice'=>$_POST['srvprice'],
'gsrvid'=>$_POST['gsrvid'],
);
$result = $controller->addServices($data);
echo json_encode($result);
exit;
}
if(isset($_GET['m']) && $_GET['m'] == 'deleteServices'){
$data = array(
'srvid'=>(int)$_POST['srvid'],
);
$result = $controller->deleteServices($data);
echo json_encode($result);
exit;
}
?>
пример модели
<?php
class ServicesModel extends BaseModel{
public function __construct(){
parent::__construct();
}
public function getListServices(){
if(isset($_GET['gsrvid']) && $_GET['gsrvid'] != ''){
$gsrvid = (int)$_GET['gsrvid'];
$filter = " where gs.gsrvid = {$gsrvid}";
}
else{
$filter = '';
}
$sql = "
select s.*,
gs.gsrvname,
p.prprice,
p.prcount_in_one,
sc.sccounts,
IFNULL(sum(cast((p.prprice/p.prcount_in_one) * sc.sccounts as decimal(5,2))), 0) as scprice
from services s
left join service_cons sc on sc.srvid = s.srvid
left join products_belle p on p.prid = sc.prid
LEFT JOIN groups_services gs ON gs.gsrvid = s.gsrvid
{$filter}
group by s.srvid
order by gs.gsrvid ASC
";
$result = $this->returnData($sql);
$total = $this->returnData("select count(*) as total from services");
return array('success'=>true, 'total'=>$total[0]['total'], 'listServices'=>$result);
}
public function getServicesOrders(){
$sql= "SELECT
srvid,
srvshortname,
srvprice,
srvname as name,
CONCAT(s.srvname, ' ( ', s.srvshortname, ', ', gsrvname, ' )', ' - ', s.srvprice, ' руб.') as srvname
FROM services s
LEFT JOIN groups_services gs on gs.gsrvid = s.gsrvid order by srvname
";
$result = $this->returnData($sql);
return array('success'=>true, 'listServicesOrders'=>$result);
}
public function getListGroupsServices(){
$sql = "select * from groups_services";
$result = $this->returnData($sql);
if($result === false){
return array('success'=>false, 'error'=>'Группы услуг не обнаружены');
}
else{
return array('success'=>true, 'listGroupsServices'=>$result);
}
}
public function addServices($data){
$name = $this->escape($data['srvname']);
$shrtname = $this->escape($data['srvshortname']);
$price = $this->escape($data['srvprice']);
$gsrvid= (int)$data['gsrvid'];
$sql = "insert into services (srvname,srvshortname,srvprice,gsrvid) values ('".$name."','".$shrtname."', '".$price."',".$gsrvid.")";
$result = $this->sqlQuery($sql);
if($result === false){
return array('success'=>false, 'error'=>'Ошибка при добавлении новой услуги');
}
else{
return array('success'=>true);
}
}
public function editServices($data){
$srvid = (int)$data['srvid'];
$srvname = $this->escape($data['srvname']);
$srvshortname = $this->escape($data['srvshortname']);
$srvprice = $this->escape($data['srvprice']);
$gsrvid = (int)$data['gsrvid'];
$sql = "update services set
srvname= '".$srvname."',
srvshortname= '".$srvshortname."',
srvprice= '".$srvprice."',
gsrvid= '".$gsrvid."'
where srvid = ".$srvid;
$result = $this->updateData($sql);
if($result === false){
return array('success'=>false, 'error'=>'Произошла ошибка при обновлении данных услуги');
}
else{
return array('success'=>true);
}
}
public function deleteServices($data){
$sql = "select * from cons_service_belle where srvid = ".(int)$data['srvid'];
$result = $this->returnData($sql);
if($result != false){
return array('success'=>false, 'error'=>'Невозможно удалить услугу т.к. она была использована клиентом');
}
else{
$sql = "delete from services where srvid = ".(int)$data['srvid'];
$result = $this->deleteData($sql);
if($result === false){
return array('success'=>false, 'error'=>'Произошла ошибка при удалении услуги');
}
else{
return array('success'=>true);
}
}
}
}
в шаблонах я отказался от шаблонизации вообще
<center>
<div class="acontent">
<h3><i class="fa fa-camera-retro"></i> Услуги</h3>
<hr class="ahr"/>
<?php if(isset($errors) && !empty($errors)) :?>
<div class="alert alert-danger fade in">
<ul class="text-danger">
<?php foreach($errors as $error):?>
<li><?=$error?></li>
<?php endforeach;?>
</ul>
</div>
<?php endif;?>
<?php if(isset($_GET['action']) && $_GET['action'] == 'edit') :?>
<frameset>
<legend><h4>Редактирование услуги</h4></legend>
<?=$editServicesForm['begin'];?>
<?=$editServicesForm['srvid'];?>
<table class="addmoduleformtable" width="500px">
<tr>
<td><label for="srvname">Наименование</label> </td>
<td><?=$editServicesForm['srvname'];?></td>
</tr>
<tr>
<td><label for="srvshortname">Короткое наименование</label> </td>
<td><?=$editServicesForm['srvshortname'];?></td>
</tr>
<tr>
<td><label for="srvprice">Стоимость</label> </td>
<td><?=$editServicesForm['srvprice'];?></td>
</tr>
<tr>
<td colspan="2"><?=$editServicesForm['editservices'];?></td>
</tr>
</table>
</frameset>
<?=$editServicesForm['end'];?>
<?php endif;?>
<?php if(isset($_GET['action']) && $_GET['action'] == 'add') :?>
<frameset>
<legend><h4>Добавление новой услуги</h4></legend>
<?=$formAddServices['begin'];?>
<table class="addmoduleformtable" width="500px">
<tr>
<td><label for="srvname">Наименование</label> </td>
<td><?=$formAddServices['srvname'];?></td>
</tr>
<tr>
<td><label for="srvshortname">Короткое наименование</label> </td>
<td><?=$formAddServices['srvshortname'];?></td>
</tr>
<tr>
<td><label for="srvshortname">Стоимость</label> </td>
<td><?=$formAddServices['srvprice'];?></td>
</tr>
<tr>
<td><?=$formAddServices['scprice'];?></td>
<td></td>
</tr>
<tr>
<td colspan="2"><?=$formAddServices['addservices'];?></td>
</tr>
</table>
</frameset>
<?php else:?>
<?=$formAddServices['end'];?>
<?php endif;?>
<?php if(!isset($_GET['action'])) :?>
<a href="<?=Route::getUrl('?mode=admin&route=services&action=add');?>">
<button type="button" class="btn btn-primary">Добавить услугу</button>
</a>
<?php endif;?>
<?php if(isset($listServices)) :?>
<p> </p>
<p> </p>
<table class="table table-hover table-striped">
<tr>
<th>Наименование</th>
<th>Сокращение</th>
<th>Группа</th>
<th>Себестоимость, руб</th>
<th>Расходники, руб</th>
<th>Итого, руб</th>
<th></th>
</tr>
<?php foreach($listServices as $k=>$s) :?>
<tr>
<td><?=$s['srvname'];?></td>
<td><?=$s['srvshortname'];?></td>
<td>
<select onchange="location.href='<?=Route::getUrl('?mode=admin&route=services')?>&changegroup=< ?=$s['srvid'];?>,'+this.value" name="gsrvname">
<?php foreach($listGroupsServices as $k=>$srv):?>
<option <?=($s['gsrvid'] == $srv['gsrvid'] ? 'selected="selected"' : '');?> value="<?=$srv['gsrvid'];?>"><?=$srv['gsrvname'];?></option>
<?php endforeach;?>
</select>
</td>
<td align="center"><?=$s['srvprice'];?></td>
<td align="center"><a href="<?=Route::getUrl('?mode=admin&route=consum&srvid='.(int)$s['srvid']);?>"><?=$s['scprice']?></a></td>
<td align="center"><?=$s['fullprice'];?></td>
<td>
<a href="<?=Route::getUrl('?mode=admin&route=services&action=edit&edit='.(int)$s['srvid']);?>">
<button type="button" class="btn btn-warning btn-xs"><span class="glyphicon glyphicon-pencil"></span> Редактировать</button></a>
<a onclick="return confirm('Удалить услугу?');" href="<?=Route::getUrl('?mode=admin&route=services&action=delete&delete='.(int)$s['srvid']);?>">
<button type="button" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-trash"></span> Удалить</button>
</a>
</td>
</tr>
<?php endforeach;?>
</table>
<?php endif;?>
</div>
</center>
базовые модели и контроллер - содержат обёртки для популярных операций (возврат табличных занчений, апдейт, удаление и т.д)
<?php
@author @email igor.vasinsky@gmail.com
@copyright
class BaseModel{
const DEBUG = DEBUG;
protected $mysqli;
protected $start;
protected $count;
protected $pageSize;
protected $thisPage;
private $paginate = array();
public function __construct(){
return $this->mysqli = Fw_mysqli::connect();
}
@param
public function sqlQuery($sql){
$result = $this->mysqli->query($sql);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
return $result;
}
}
@param
public function sqlMultyQuery($sql){
$result = $this->mysqli->multi_query($sql);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
while($this->mysqli->next_result()) $this->mysqli->store_result($linkId);
return $result;
}
}
@param
public function returnData($sql){
$result = $this->mysqli->query($sql);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
if($result->num_rows>0){
while($row = $result->fetch_assoc()){
$data[] = $row;
}
return $data;
}
else{
return false;
}
}
}
@param
public function updateData($sql){
$result = $this->mysqli->query($sql);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
return $this->mysqli->affected_rows;
}
}
@param @return
public function deleteData($sql){
$result = $this->mysqli->query($sql);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
return $this->mysqli->affected_rows;
}
}
@param @param @param @return
public function getPaginateData($sql, $pageSize, $curPage){
$result = $this->mysqli->query($sql);
$this->thisPage = $curPage;
$data = false;
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'>>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
$totalData = $result->num_rows;
if($totalData <= $pageSize){
while($row = $result->fetch_assoc()){
$data[] = $row;
}
return $data;
}
else{
$result = null;
if($this->thisPage == 1)
$this->start = 0;
$this->start = ($this->thisPage*$pageSize)-$pageSize;
$pages = ceil($totalData/$pageSize);
$result = $this->mysqli->query($sql.' limit '.$this->start.','.$pageSize);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
if($result->num_rows>0){
while($row = $result->fetch_assoc()){
$data[] = $row;
}
$padinate = array();
for($i=0;$i<=$pages;$i++){
if($i == $curPage)
$paginate['active'] = $i;
else{
$paginate[] = $i;
}
}
unset($paginate[0]);
$this->paginate = $paginate;
}
return $data;
}
}
}
}
public function paginate(){
return $this->paginate;
}
public function escape($data){
return $this->mysqli->real_escape_string($data);
}
public function multiQuery($sqls){
$result = $this->mysqli->multi_query($sqls);
if($result === false){
return false;
}
else{
while($this->mysqli->more_results() && $this->mysqli->next_result())
$this->mysqli->store_result();
return true;
}
}
public function last_id(){
return $this->mysqli->insert_id;
}
@param
public function returnPageData($name){
$sql = "select * from pages where name = '".$this->escape($name)."' LIMIT 1";
$result = $this->mysqli->query($sql);
if(!$result){
Files::addtolog(LOG_MYSQLI, $sql.'--->>>'.$this->mysqli->error);
throw new Exception($this->mysqli->error);
}
else{
if($result->num_rows>0){
while($row = $result->fetch_assoc()){
$data[] = $row;
}
return $data;
}
else{
return false;
}
}
}
}
?>
<?php
@author @email igor.vasinsky@gmail.com
@copyright
class BaseController{
const DEBUG = DEBUG;
public $model;
public $data = array();
public $paginateNumberPages = 10;
public $paginateButtonNext = true;
public $paginateButtonPrev = true;
public $paginateButtonNextText = 'дальше';
public $paginateButtonPrevText = 'назад';
public $paginateCurPage = 1;
public function __construct(){
}
public function setModel($route){
$class = $route.'Model';
$this->model = new $class;
return $this->model;
}
public function returnData($sql){
return $this->model->returnData($sql);
}
public function updateData($sql){
return $this->model->updateData($sql);
}
public function deleteData($sql){
return $this->model->deleteData($sql);
}
public function query($sql){
return $this->model->query($sql);
}
public function getPaginateData($sql, $pageSize, $curPage){
return $this->model->getPaginateData($sql, $pageSize, $curPage);
}
public function view($pathtotpl){
ob_start();
Files::load($pathtotpl);
$html = ob_get_contents();
ob_clean();
echo Snippet::parseSnippet($html, MODE);
}
public function paginate(){
return $this->model->paginate();
}
}
?>
на этом фреймворке у меня развернута CMF с уже созданными разделами страницы, галерея и тд. вообщем всё что нужно чтобы развернуть любой сайт.
_____________
HTML, CSS (Bootstrap), JS(JQuery, ExtJS), PHP, MySQL, MSSql, Posgres, (TSql, BI OLAP, MDX), Mongo, Git, SVN, CodeIgnater, Symfony, Yii 2, JiRA, Redmine, Bitbucket, Composer, Rabbit MQ, Amazon (SQS, S3, Transcribe), Docker