Framework Foton
Инструмент для профессиональной разработки web приложений
Создание своего типа запроса


В файле /core/etting/dev.php вы можете найти основные настройки типов запросов

<?php
$arr['typeFormat'] = [
    "function"=>[
        "mvc"=>[
            "tpl"=>"/app/view/[dir]/[name].tpl",
            "php"=>"/app/view/[dir]/[name].php",
            "api"=>"/system/api/tpl/[dir]/[name].php"
        ],
        "modul"=>[
            "view"=>"/dev/modul/[name]/index.php",
            "modul"=>"/dev/modul/[name]/[method]/index.php"
        ],
        "widget"=>[
            "view"=>"/dev/widget/".$arr['sitedir']."/[name]/index/template.php",
            "style"=>"/dev/widget/".$arr['sitedir']."/[name]/index/style.php",
            "script"=>"/dev/widget/".$arr['sitedir']."/[name]/index/script.php"
        ],
        "micro"=>[
            "tpl"=>"/dev/service/micro/[name]/return/index.tpl",
            "setting"=>"/dev/service/micro/[name]/setting.json"
        ],
        "face"=>[
            "view"=>"/app/face/".$arr['admindir']."/tpl/[name].tpl",
            "method"=>"/app/face/".$arr['admindir']."/tpl/[name]/[method].tpl"
        ],          
        "tpl"=>[
            "view"=>"/app/type/".$arr['sitedir']."/tpl/[name].php"
        ],
        "tplfront"=>[
            "style"=>"/app/type/".$arr['sitedir']."/css/[name].css",
            "script"=>"/app/type/".$arr['sitedir']."/js/[name].js"
        ],
        "ajax"=>[
            "ajax"=>"/dev/modul/[name]/ajax.php",
            "view"=>"/dev/modul/[name]/ajax/[method].php"
        ],
        "ajaxadmin"=>[
            "ajax"=>"/app/ajax/".$arr['admindir']."/[name].php",
            "view"=>"/app/ajax/".$arr['admindir']."/".$arr['admindir']."/[name]/[method]/index.php"
        ],
        "ajaxsite"=>[
            "ajax"=>"/app/ajax/".$arr['sitedir']."/[name].php",
            "view"=>"/app/ajax/".$arr['sitedir']."/".$arr['sitedir']."/[name]/[method]/index.php"
        ]        
    ],
    "admin"=>[
        "modul",
        "face", 
        "ajax",
        "ajaxadmin",
    ],
    "boot"=>[
        "mvc"=>[
            "Controller",
            "Model"
        ],  
        "modul"=>"ModulController",
        "widget"=>"Widget",
        "micro"=>"Micro",
        "face"=>"Faces",          
        "tpl"=>"Tpl",
        "tplfront"=>"Tpl",
        "ajax"=>"Ajax",
        "ajaxadmin"=>"Ajaxadmin",
        "ajaxsite"=>"Ajaxsite"
    ],
    "front"=>[
        "mvc"=>[
            "css"=>["/app/view/[dir]/css/style.css","/app/view/[dir]/css/[page].css","/app/view/[dir]/css/[head].css","/app/view/[dir]/css/[foot].css"],
            "js"=>["/app/view/[dir]/js/jquery.js","/app/view/[dir]/js/script.js","/app/view/[dir]/js/[page].js","/app/view/[dir]/js/[foot].js"]  
        ],
        "modul"=>[
            "css"=>["/dev/modul/[page]/css/style.css","/dev/modul/[page]/css/face.css"],
            "js"=>["/app/view/".$arr['admindir']."/js/jquery.js","/dev/modul/[page]/js/face.js","/dev/modul/[page]/js/script.js"] 
        ],
        "face"=>[
            "css"=>["/app/view/".$arr['admindir']."/css/style.css","/app/view/".$arr['admindir']."/css/[head].css","/app/view/".$arr['admindir']."/css/[foot].css","/app/face/".$arr['admindir']."/css/[page].css"],
            "js"=>["/app/view/".$arr['admindir']."/js/jquery.js","/app/view/".$arr['admindir']."/js/script.js","/app/view/".$arr['admindir']."/js/[head].js","/app/view/".$arr['admindir']."/js/[foot].js","/app/face/".$arr['admindir']."/js/[page].js"]
        ]
    ],
    "recurse"=>[
        "ajaxadmin",
        "ajaxsite"
    ],
    "autoload"=>[
        "mvc"=>[
            "Controller"=>"app/controller/[name].php",
            "Model"=>"app/model/[name].php"
        ],
        "modul"=>[
            "ModulController"=>"dev/modul/[name]/controller.php",
            "ModulModel"=>"dev/modul/[name]/model.php"
        ],
        "widget"=>[
            "Widget"=>"dev/widget/".$arr['sitedir']."/[name]/index.php"
        ],
        "micro"=>[
            "Micro"=>"dev/service/micro/[name]/return/class.php"
        ],
        "face"=>[
            "Faces"=>"app/face/".$arr['admindir']."/php/[name].php"
        ],          
        "tpl"=>[
            "Tpl"=>"app/type/".$arr['sitedir']."/php/[name].php"
        ],
        "ajax"=>[
            "Ajax"=>"dev/modul/[name]/ajax.php"
        ],
        "ajaxadmin"=>[
            "Ajaxadmin"=>"app/ajax/".$arr['admindir']."/[name].php"
        ],
        "ajaxsite"=>[
            "Ajaxsite"=>"app/ajax/".$arr['sitedir']."/[name].php"
        ]  
    ]
];


Ключ function содержит пути к файлам методов по ключам типов запроса, пути к css,js,php файлам

Ключ admin содержит список значений типов запросов, если тип запроса включен в список, доступ к данному типу будет открыт только для авторизованных в админ панели пользователей

Ключ boot содержит namespace типов запросов

Ключ front содержит списки массивов данных содержащих пути подключения front-end файлов

Ключ recurse содержит типы запросов, в которых может работать вложенность методов и последовательный вызов в текучем интерфейсе как 


<?php
$this->core->view()->ajaxsite->test->test2->test3->end();

Ключ autoload содержит список с ключами являющимися типами запросов и значениями как список с ключами namespace типов запросов и значениями путями к файлам с соответствующими классами

После добавления своего типа в настройки необходимо добавить файл с определением класса типа запроса по пути /core/foton/view/type/ваштип.php

Вот пример файла для ajax запросов сайта


<?
namespace Foton\View\Type;

final class Ajaxsite{
    public function appclass($class,$name){
        $arr = explode('\\',$name);
        $method = array_pop($arr);
        $class = ucfirst($class);
        foreach($arr as $item){
            $class.= '\\'.ucfirst($item);
        }
        $class = str_replace('Ajaxsite','Ajaxsite\Site',$class); 
        return $class;
    }

    public function datareturn(\Foton\View $view,$obj,$nameSpace){
        $arr = explode('\\',$view->page);
        $name = array_pop($arr);
        if(method_exists($obj,$name)){
            if(empty($view->attr)){
                $view->data = $obj->$name(); 
            }
            else{       
                $view->data = $obj->$name(...array_values($view->attr)); 
            }
            return $view; 
        }
        echo 'Метода не существует';        
    }

    public function render(\Foton\View\Render $render){
        
        $page = $render->view->page;
        if($render->init->setting('ajaxsite')){
            //переопределяем формат вывода объекта new Format
            $render->init->format = 'ajaxsite';
            $render->init->wrapper = 'page';
            $render->init->page($page);
            //подключаем языковые файлы
            $render->init->lang();
        }
        return $render;
    }
}

Класс обязательно должен быть финализирован, чтобы не было возможности создания дубликата объетка

Также класс должен содержать основные методы:

appclass($class,$name)
datareturn(\Foton\View $view,$obj,$nameSpace)
render(\Foton\View\Render $render)
Первый метод формирует namespace из url типа запроса
Второй метод datareturn формирует массив data для использования в представлении
Третий метод render после получения и проверки всех данных из свойства setting формирует  страницу с определением формата, оболочки, инициализации страницы и подключения языковых файлов

cli() - не обязательный метод, если его добавить он будет вызываться для данного типа запроса через командную строку с помощью команды
php foton type название_вашего_типа_запроса


Создадим пример типа запроса


<?php
$arr['typeFormat'] = [
    "function" => [
        "mvc" => [
            // ...
        ],
        "report" => [                  // <-- новый тип
              "tpl"  => "/dev/report/view/[name].tpl",
              "view" => "/dev/report/view/[name].php",
              "api"=>"/system/api/tpl/report/[name].php"
        ],
        // остальные типы...
    ],
    "admin" => [
        // ...
        "report",                      // <-- разрешаем доступ только в админке (если нужно)
    ],
    "boot" => [
        // ...
        "report" => "Report",          // <-- имя класса (без namespace), будет сопоставлено с Foton\View\Type\Report
    ],
    "front" => [
        // можно добавить css/js, если отчётам нужны свои стили/скрипты
        "report" => [
            "css" => ["/dev/report/css/[page].css"],
            "js"  => ["/dev/report/js/[page].js"]
        ]
    ],
    "recurse" => [
        // если нужна вложенность методов, добавляем сюда
        // "report",
    ],
    "autoload" => [
        "report" => [
            "Report" => "dev/report/[name].php"  // путь к файлу класса типа
        ]
    ]
];

Создаем файл типа запроса report

<?php
namespace Foton\View\Type;
use Foton\Lib\Cli;
final class Report
{
    /**
     * Формирует namespace из URL типа запроса.
     * В простом случае можно возвращать тот же класс или модифицировать его.
     */
   public function appclass($class, $name)
    {
        $arr = explode('\\',$name);
        if(count($arr)>1){
            $method = array_pop($arr);
            $class = ucfirst($class);
            foreach($arr as $item){
                $class.= '\\'.ucfirst($item);
            }
        }
        else{
            $class = $class.'\\'.ucfirst($name);
        }
        return $class;
    }

    /**
     * Метод для работы с CLI
     */
    public function cli(){
        $cli = new Cli;
        return $cli->green('Инициализация метода cli');
    }

    /**
     * Получает данные из метода контроллера и кладёт в $view->data.
     */
    public function datareturn(\Foton\View $view, $obj, $nameSpace)
    {
        
        $pageParts = explode('\\', $view->page);
        //если в ЧПУ есть метод ищем его и только его и подключаем
        if(count($pageParts)>1){
            $name = array_pop($pageParts);
            if (method_exists($obj, $name)) {
                if (empty($view->attr)) {
                    $view->data[$name] = $obj->$name();
                } else {
                    $view->data[$name] = $obj->$name(...array_values($view->attr));
                }
                
                return $view;
            }
        }
        // иначе подключаем все доступные методы
        else{
            foreach(get_class_methods($obj) as $method){
                if (empty($view->attr)) {
                    $view->data[$method] = $obj->$method();
                } else {
                    $view->data[$method] = $obj->$method(...array_values($view->attr));
                }
            }
            return $view;
        }
        echo 'Метода не существует';
        return $view;
    }

    /**
     * Настраивает формат вывода, обёртку, страницу, языки и т.п.
     */
    public function render(\Foton\View\Render $render)
    {
        $page = $render->view->page;

        if ($render->init->setting('report')) {
            // Устанавливаем формат вывода специально для отчётов
            $render->init->format = 'report';
            $render->init->wrapper = 'page';

            // Инициализируем страницу
            $render->init->page($page);

            // Подключаем языковые файлы
            $render->init->lang();
        }

        return $render;
    }
}


Так как мы добавили свой формат report в метод render нам нужно также добавить метод для работы в библиотеку форматов в трейт Format /core/foton/view/lib/format.php

<?php
    // 3 аргумента берутся по ключам из настройки function в typeFormat (/core/setting/dev.php)
 public function report($tpl,$view,$api){
        //Подключаем глобальный класс инициализации
        $init = new \Foton\View\Init($this->view);
        // записываем в массив данных, для того, чтобы инициализировать подключение css,js на странице представления, так как могут быть страницы в формате json  и т.д.
        $this->view->data['css'] = $init->css();
        $this->view->data['js'] = $init->js();
        $this->tpl($tpl,$view,$api);
 }

Форматы вынесены в отдельный файл для того, чтобы разные типы запросов могли выбирать любой из существующих форматов для вывода.


Теперь создаем файл класса Report /dev/report/sales.php

И файл представления /dev/report/view/sales.tpl

Добавим содеримое класса

<?php
namespace Report;

class Sales
{
    // Метод, который будет вызван при обращении к report-типу
    public function summary($month=null)
    {
        global $FG;
        if($month!=null){
              return $month;
       }
        return  $FG->get()->month;
    }
}

И представление для типа запроса

<h1>Отчёт по продажам за @{data['summary'] }</h1>
<p>Можно добавить как пример Итого: @{data['total'] }</p>
<ul> Можно добавить как пример
    for:{$data['items'] as $item}
        <li>@{item['name'])}: @{item['amount'] }</li>
    @:@
</ul>

Теперь мы можем вызвать наш тип запроса в коде

<?php
$this->core->view()->report->sales->summary->end(['month'=>'2024-09']);

Или через запрос в url /sales/summary.report?month=2024-09

 
<?php
namespace Foton\View\Type;
use Foton\Lib\Cli;
final class Report
{
    /**
     * Формирует namespace из URL типа запроса.
     * В простом случае можно возвращать тот же класс или модифицировать его.
     */
   public function appclass($class, $name)
    {
        $arr = explode('\\',$name);
        if(count($arr)>1){
            $method = array_pop($arr);
            $class = ucfirst($class);
            foreach($arr as $item){
                $class.= '\\'.ucfirst($item);
            }
        }
        else{
            $class = $class.'\\'.ucfirst($name);
        }
        return $class;
    }

    /**
     * Метод для работы с CLI
     */
    public function cli(){
        $cli = new Cli;
        return $cli->green('Инициализация метода cli');
    }

    /**
     * Получает данные из метода контроллера и кладёт в $view->data.
     */
    public function datareturn(\Foton\View $view, $obj, $nameSpace)
    {
        
        $pageParts = explode('\\', $view->page);
        //если в ЧПУ есть метод ищем его и только его и подключаем
        if(count($pageParts)>1){
            $name = array_pop($pageParts);
            if (method_exists($obj, $name)) {
                if (empty($view->attr)) {
                    $view->data[$name] = $obj->$name();
                } else {
                    $view->data[$name] = $obj->$name(...array_values($view->attr));
                }
                
                return $view;
            }
        }
        // иначе подключаем все доступные методы
        else{
            foreach(get_class_methods($obj) as $method){
                if (empty($view->attr)) {
                    $view->data[$method] = $obj->$method();
                } else {
                    $view->data[$method] = $obj->$method(...array_values($view->attr));
                }
            }
            return $view;
        }
        echo 'Метода не существует';
        return $view;
    }

    /**
     * Настраивает формат вывода, обёртку, страницу, языки и т.п.
     */
    public function render(\Foton\View\Render $render)
    {
        $page = $render->view->page;

        if ($render->init->setting('report')) {
            // Устанавливаем формат вывода специально для отчётов
            $render->init->format = 'report';
            $render->init->wrapper = 'page';

            // Инициализируем страницу
            $render->init->page($page);

            // Подключаем языковые файлы
            $render->init->lang();
        }

        return $render;
    }
}
 
© Copyright 2026 Разработано на Framework Foton
Продукт зарегистрирован в Роспатенте