YII2 выполнение кода в каждом контроллере

В продолжении темы примитивного логгирования. Понадобилось записывать, какой пользователь открывает какие страницы. И если с клиентским отображением в принципе ничего сложного, просто вставил в /view/layouts/main.php код вида:

if (isset(Yii::$app->user->identity)){
  if (isset(Yii::$app->user->identity->username)){
    Logger::Log(Yii::$app->user->identity->username." >> ".$_SERVER["REQUEST_URI"]);
  }
};

Но, к сожалению оный не перехватывает вызов страниц, которые завершаются в контроллере. Ну например всякие ajax запросы на странице. Поступил чуть хитрее: создал свой компонент в папке components (требуется создать папку если нет):

<?php
namespace app\components;
use yii\base\Component;
use app\models\Logger;

class Logging_at_start extends Component{
    public function init() {
           Logger::Log(" >> ".$_SERVER["REQUEST_URI"]);
        parent::init();
    }
}   

И добавил/отредактировал в /config/web строчки:

...
'bootstrap' => ['log','Logging_at_start'],
...
    'components' => [
        'Logging_at_start'=>[
            'class'=>'app\components\Logging_at_start'
        ],        

Плюс добавил сохранение сессии в константу sess в web/index.php

Итого, в логах теперь красуется всё то нужно:

Примитивное логгирование в YII2

Иногда необходимо в проект добавить логгирование событий работы, однако не всегда удобно тащить для этого кучу сторонних библиотек. Тем более что особых требований и не нужно. Если достаточно что бы:

  • логи велись «стандартно» для системы на базе Linux, с автоматической ротацией и т.п.
  • особых тонкостей и настроек для вывода не нужно, достаточно просто текста

То вполне можно написать свою простенькую модель вида:

<?php
namespace app\models;
use Yii;

class Logger {
    
    const Error=1;
    const Info=2;
    const Warning=3;
    const Success=4;
    const Fail=5;
    
 public static function Log($message,$type=self::Info){
     $prefix="Info:";
     if ($type==self::Error)    $prefix="Error";
     if ($type==self::Info)     $prefix="Info";
     if ($type==self::Warning)  $prefix="Warning";
     if ($type==self::Success)  $prefix="Success";
     if ($type==self::Fail)  $prefix="Fail";
     /usr/bin/logger "(GEO) $prefix: $message";
 }   
}

И использовать её далее в любом месте в коде, например так:

        Logger::Log("-попытка авторизации в AD $username");        
        // авторизуемся в AD
        $ldapbind = @ldap_bind($ldap_con, $username."@".$value["ldap_server"], $password);                        
        if ($ldapbind==false) {
            Logger::Log("--ошибка",Logger::Fail);
            return null;            
        };
        Logger::Log("--ok",Logger::Success);

Логи можно будет наблюдать в стандартном /var/log/messages:P.S. Раньше тоже велосипедил с добавлением лога в отдельный файл, а потом подумал «А зачем?». В большинстве случаев достаточно так.

YII: Шаблон модели при использовании CRUD генератора

Не понятно почему, но CRUD не создает самостоятельно модель для работы с таблицой БД. По крайне мере у меня. Потому из нескольких разрозненных кусков собрал «рыбу»:

<?php

namespace app\models;

class YandexKeys extends \yii\db\ActiveRecord{

public static function tableName(){
    return 'api_map_keys'; // Имя таблицы в БД в которой хранятся записи
}
 
public function rules(){    
        return [
            [['name', 'key'], 'required'],  // какие поля есть в таблице обязательные для добавления
        ];
    }
 
public function attributeLabels(){  // Зададим имена колонок
        return [
            'id' => 'ID',
            'name' => 'Имя',
            'key' => 'Ключ API'
        ];
 }
 
 public static function getAll(){   // выборка всех значений из БД
    $data = self::find()->all();
    return $data;
 }

}

Краткая шпаргалка по YII2

Последнее время в очередной раз вплотную занимаюсь работой с фреймворком yii2. В связи с чет сделал для себя небольшую шпаргалку.

Получение POST/GET параметров:

$request = Yii::$app->request;
$period= $request->post("period");
$period= $request->get("period");

Выполнение SQL запроса типа SELECT:

// Вариант 1
$lsa = Yii::$app->db->createCommand($sql)->queryAll();       
foreach ($lsa as $row99) {   
}
// Вариант 2
$rows = (new \yii\db\Query())->select(['id'])->from('users')->where(['login' => $login])->limit(1)->all();
foreach ($rows as $row99) {   
}

Выполнение SQL запроса типа Insert:

// Вариант 1
$res=(new \yii\db\Query())->createCommand()->insert('users', ['login' =>$username])->execute();
        if ($res==false){
            die("Не удалось вставить запись с новым пользователем..Увы и ах..");
        };   
// Вариант 2
        $sql="insert into posting_zones (area,name,coors) values ($area,concat('Зона ',(select (max(id)+1) as name from posting_zones)),'$coors')";
        $res= Yii::$app->db->createCommand($sql)->execute();       

Корневой путь YII:

$dir=Yii::$app->basePath;

Корневой URL приложение YII:

$WUO_ROOT=Yii::getAlias('@app')."/web/";

Получение параметров из файла конфигурации YII:

$params = require(__DIR__ . '/../../config/web.php');
$geo_config = \yii\helpers\ArrayHelper::getValue($params, 'params'); //всякие настройки

Данные авторизованного пользователя (шаблон basic):

Yii::$app->user->identity

YII2: Bad Request (#400) Unable to verify your data submissionYII2:

Такая ошибка:

Bad Request (#400) Unable to verify your data submissionYII2

может возникнуть при принудительном вызове формы с POST или GET параметрами со страницы сайта. Например:

    <form id="TheFormRoute" method="post" action="?r=site%2Fls_route_report" target="Маршруты доставки">
        <input type="hidden" id="f_count_ls" name="f_count_ls" value="" />
        <input type="hidden" id="f_route_id" name="f_route_id" value="" />
        <input type="hidden" id="f_route_name" name="f_route_name" value="" />
        <input type="hidden" id="f_period" name="f_period" value="" />
        <input type="hidden" id="f_area" name="f_area" value="" />
        <input type="hidden" id="f_area_name" name="f_area_name" value="" />
        <input type="hidden" id="f_ls_list" name="f_ls_list" value="" />
    </form>

В контроллере сайта код вида :

    public function actionLs_route_report()    {
      Yii::$app->controller->enableCsrfValidation = false;
      return $this->render('route_report');  
    }

Как раз и приведет к подобной ошибке:

Это своеобразная защита фреймворка от потенциального флуда. Вариантов решения несколько:

Отключить проверку CSRF глобально:

    'components' => [
        'request' => [
            'enableCsrfValidation' => false,
        ],

Отключить проверку для конкретного контроллера:

class SiteController extends Controller
{
    
    public function beforeAction($action){ 
        $this->enableCsrfValidation = false; 
        return parent::beforeAction($action); 
    }    
    
    public function actionLs_route_report()    {
      return $this->render('route_report');  
    }

Или воспользоваться ПРАВИЛЬНЫМ по мнению фреймворка методом:

    <form id="TheFormRoute" method="post" action="?r=site%2Fls_route_report" target="Маршруты доставки">
        <input id="form-token" type="hidden" name="<?=Yii::$app->request->csrfParam?>" value="<?=Yii::$app->request->csrfToken?>"/>
        <input type="hidden" id="f_count_ls" name="f_count_ls" value="" />
        <input type="hidden" id="f_route_id" name="f_route_id" value="" />
        <input type="hidden" id="f_route_name" name="f_route_name" value="" />
        <input type="hidden" id="f_period" name="f_period" value="" />
        <input type="hidden" id="f_area" name="f_area" value="" />
        <input type="hidden" id="f_area_name" name="f_area_name" value="" />
        <input type="hidden" id="f_ls_list" name="f_ls_list" value="" />
    </form>
1 2