Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > сделать свой MVC и привязать к нему Smarty


Автор: numerovan 22.9.2015, 16:25
Здравствуйте. Необходимо привязать Смарти в будущим проектам, так сказать хочу сделать основу для проектов. Почему Смарти? Популярен, хорошее кеширование, разделение труда с верстальщиками.

Хочится сделать упор на архитектуру MVC (модель-вид-контроллер).

Можете подсказать как написать нормальный MVC и соединить его со Смарти? 

Смущают еще вопросы:
1. Нужно ли создавать (проверять) наличие одноименного названия модели исходя от контроллера?
2. Если в ЧПУ будет много данных, н-р: /catalog/shop1/product1/kind1/model1/sony , то как всю эту байду разгребать? Первое (/catalog)-название контроллера, второе (shop1) - название метода ... как организовать потом (product1/kind1/model1/sony) - это типо необязательные параметры данного метода? помоему вроде так.

Если знаете на подобные уже сделанные решения, скиньте ссылки пожалуйста, буду благодарен. Но все таких хотелось бы тоже разобратся как и что почем.

Автор: _zorn_ 24.9.2015, 15:53
Почему смарти, а не twig ? Почему свой MVC, а не symfony с doctrine например ?
Может не стоит в очередной раз делать свой велосипед ?

Присмотрись http://symfony.com/

Автор: numerovan 24.9.2015, 17:46
Цитата(_zorn_ @  24.9.2015,  15:53 Найти цитируемый пост)
Почему смарти, а не twig?

Больше о Смарти наслышен.

Цитата(_zorn_ @  24.9.2015,  15:53 Найти цитируемый пост)
Почему свой MVC, а не symfony с doctrine например ?

О Симфони тоже наслышан. Да конечно почему бы их не использовать ... любопытно что ли самому сделать и разобратся в деталях )

Цитата(_zorn_ @  24.9.2015,  15:53 Найти цитируемый пост)
Может не стоит в очередной раз делать свой велосипед ?

Да, похоже на велосипед ) ... разобратся наверно хочится ).

Автор: _zorn_ 26.9.2015, 02:27
Цитата(numerovan @  25.9.2015,  00:46 Найти цитируемый пост)
разобратся наверно хочится

Ну так прочитай документацию smile 
Хотя бы http://symfony.com/doc/current/book/from_flat_php_to_symfony2.html
Зачем для этого свой фреймворк писать ?  smile 

Автор: _zorn_ 26.9.2015, 03:23
В использовании готовых (известных) фреймворков есть существенный плюс.
Когда (заметь не ЕСЛИ) тебе надоест - всем проектам на твоем фреймворке хана. Ну или по ночам будешь ворочатся когда поддерживающие твой код будут тебя материть за кривой код ))
Короче не думай только о себе.

Автор: numerovan 9.10.2015, 17:28
набросал наброски, оцените пожалуйста и если где увидили недочеты, напишите, чтоб быть в курсе дела.
Код

session_start();

// объявим константы и создадим установки
    define("WORK_MODE",        0);
    
    ini_set('error_reporting',    WORK_MODE? 0: E_ALL); // вывод всех ошибок, в 5.4 E_NOTICE входит в состав E_ALL
    ini_set("display_errors",    WORK_MODE? 0: 1);
    ini_set("log_errors",        1);
    ini_set("error_log",        __DIR__."/_errors.log");
    ini_set("default_charset",    "utf-8");
    
    define("ROOT",                $_SERVER['DOCUMENT_ROOT']);

    define("DIR_APPS",            __DIR__."/apps");
    define("DIR_CONTROLLERS",    DIR_APPS."/controllers");
    define("DIR_MODELS",        DIR_APPS."/models");
    define("DIR_VIEWS",        DIR_APPS."/views");
    define("DIR_SMARTY",        __DIR__."/smarty");

    define("DB_HOST",            "localhost");
    define("DB_NAME",            "volodya-nrg");
    define("DB_USER",            "root"); // необходим юзер, который имеет меньше прав. под рутом не рекомундуется заходить
    define("DB_PASS",            "somepass");
    define("DB_CHARSET",        "UTF8");

    define("NMSPC_CNTRLR",        "vnrgController");

// проверим необходимые папки
    $aTmp = array(DIR_CONTROLLERS, DIR_MODELS, DIR_VIEWS, DIR_SMARTY);

    foreach($aTmp as $val){
        if(!is_dir($val)){
            die("Err: not found dir '".basename($val)."'.");
        }
    }
    $aTmp = NULL;
    
// проверим версию php
    if(version_compare(PHP_VERSION, '5.3.0', '<')) {
        die("Err: change php version (".PHP_VERSION.").");
    }

// подключимся к базе данных
    try{
        $pdo = new PDO(        "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHARSET,
                            DB_USER,
                            DB_PASS,
                            array(  PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC)
                       );
    }catch(PDOException $e){
        die("Err: not connect to database.");
    }

// укажем как нужно грузить контроллеры когда их вызываем внутри ф-ии через __autoload
    spl_autoload_register(function($class_name){
        $class_name = substr_count($class_name, NMSPC_CNTRLR."\\")? str_replace(NMSPC_CNTRLR."\\", "", $class_name): $class_name;
        $file        = DIR_CONTROLLERS.'/'.$class_name.'.php';

        if(file_exists($file)){
            require_once($file);
        }
    });
    
// подсоединим Smarty, обязательно до вызовов метода текущего контроллера
    $file = DIR_SMARTY."/libs/Smarty.class.php";

    if(!file_exists($file)){
        die("Err: not found Smarty.");
    }
    else{
        require_once($file);
        
        // смарти лучше создать здесь и задать параметры. Это из-за аякса.
        $smarty = new Smarty();
        $smarty->setTemplateDir(DIR_VIEWS);
        $smarty->setCompileDir(DIR_SMARTY.'/templates_c');
        $smarty->setCacheDir(DIR_SMARTY.'/cache');
        $smarty->setConfigDir(DIR_SMARTY.'/configs');
        //$smarty->debugging = true;
    }

// подсоединим абстрактный класс для контроллеров
    $file = DIR_APPS."/Controller.php";

    if(!file_exists($file)){
        die("Err: not found abstract Controller.");
    }
    else{
        require_once($file);
    }

// подсоединим пользовательские ф-ии если есть
    $file = DIR_APPS."/functions.php";

    if(file_exists($file)){
        require_once($file);
    }
    
    $file = NULL;

// обработаем url и возьмем названия контроллера, метода, параметров и шаблона
    $req_uri            = strtolower($_SERVER['REQUEST_URI']);
    $sUrl                = substr_count($req_uri, "?")? substr($req_uri, 0, strpos($req_uri, "?")): $req_uri;
    $aUrl                = explode("/", $sUrl);
    
    $preg_pattern        = "/^[a-z][a-z0-9_]*$/"; // патерн для названия класса и контроллера
    //$preg_pattern        = "/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/"; // патерн для названия класса и метода
    $preg_ptrn_args        = "/^[a-zа-я0-9][-a-zа-я0-9_.]*$/iu"; // паттерн для аргументов метода
    $aDisallowedCtrlrs    = array("controller");
    
    array_shift($aUrl); // уберем первый пустой элемент
    
    $sTplName            = (!empty($aUrl[0]) && preg_match($preg_pattern, $aUrl[0]) && !in_array($aUrl[0], $aDisallowedCtrlrs))? $aUrl[0]: "main";
    $sControllerMethod    = (!empty($aUrl[1]) && preg_match($preg_pattern, $aUrl[1]))? $aUrl[1]: "index";
    $sControllerName    = NMSPC_CNTRLR."\\".$sTplName;
    $aArgs                = array($sControllerMethod); // по умолчанию первым аргументом идет название ф-ии, сделанно спец-но, т.к. подобный подход используется и в других языках программирования
    
    if(sizeof($aUrl) > 2){
        for($i=2, $size = sizeof($aUrl); $i<$size; $i++){
            if(isset($aUrl[$i]) && preg_match($preg_ptrn_args, $aUrl[$i])){
                $aArgs[] = $aUrl[$i];
            }
        }
    }
    
// проверим наличие контроллера (объект и метод)
    if(!class_exists($sControllerName)){
        die("Err: not found class controller.");
        /*header("Location: /error");
        exit;*/
    }
    if(!method_exists($sControllerName, $sControllerMethod)){
        die("Err: not found class method.");
        /*header("Location: /error");
        exit;*/
    }

// проверим наличие view, лучше перед вызовом метода у класса ... из-за редиректа на страницу error
    if(!file_exists(DIR_VIEWS."/".$sTplName.".tpl")){
        die("Err: not found tamplate (".$sTplName.".tpl)");
    }
    
// вызовем метод у контроллера, если есть аргументы, то подставим их
    //eval("\$aOutput = call_user_func(array(\$sControllerName, \$sControllerMethod)".(sizeof($aArgs)? ", ".implode(",", $aArgs): "").");");
    $aOutput = call_user_func(array(new $sControllerName(), $sControllerMethod), $aArgs);
    
    if($aOutput === false){
        die("Err: controller method return false");
    }

// если это ajax-метод, то шаблон (внизу) не подставляем. выводим данные.
    if(substr($sControllerMethod, 0, strlen("ajax_")) == "ajax_"){
        echo $aOutput;
        exit;
    }
    
// назначим необходимые переменные для шаблона (если есть) и отобразим шаблон
    if(!empty($aOutput) && is_array($aOutput)){
        foreach($aOutput as $key=>$val){
            $smarty->assign($key, $val);
        }
    }

    $smarty->display($sTplName.".tpl");


Добавлено через 6 минут и 38 секунд
http://rghost.ru/7TrHN77Md

Автор: numerovan 9.10.2015, 17:43
пока решил основу поставить в один файл (index.php), не стал разделять.

.htaccess такой
Код

# кодировка по умолчанию
AddDefaultCharset UTF-8

DirectoryIndex index.php
# переходить по ссылочным файлам
Options +FollowSymlinks
# не показывать листинг в пустой папке
Options -Indexes

#отдаем правильно файлы
#XSendFile On

#защищаем типы файлов
<Files ~ "\.(htaccess|htpasswd|ini|fla|psd|log|sh)$">
    order allow,deny
    deny from all
</Files>

<ifModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    
    #редирект с www на без него
    RewriteCond %{HTTP_HOST} ^www.(.*) [NC]
    RewriteRule ^/?(.*) http://%1/$1 [L,R=permanent]

    # убираем последний слеш
    RewriteCond %{HTTP_HOST} (.*)
    RewriteCond %{REQUEST_URI} /$ [NC]
    RewriteRule ^(.*)(/)$ $1 [L,R=301]

    # весь url перенаправляем на route
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ /index.php [L,QSA]
</ifModule>

<ifModule mod_headers.c>
    #<FilesMatch "\.(jpg|jpeg|png|gif|js|css)$">
    #Header set Cache-Control "max-age=3153600, public"
    #</FilesMatch>
</ifModule>

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)