lordphnx/ez-cake

一组用于增强频繁使用行为的CakePHP质量提升器

9.0.0 2023-10-04 14:51 UTC

This package is auto-updated.

Last update: 2024-09-28 18:58:33 UTC


README

EasyCake是一组库,用于使常见的CakePHP任务更简洁。它包括多个子项目

  1. EasyTest,用于辅助模拟ORM实体以进行测试用例
  2. EasyAuth,用于辅助编写isAuthorized(User $user) : bool方法
  3. ErrorPrevention,用于防止烦人的wordpress扫描器扰乱你的(Sentry)错误日志

为什么选择EasyCake

对于我的公司,我运行了大量的不同CakePHP项目,并且不断地重复编写相同的逻辑。所以我决定将它们放入一个库中。随着时间的推移,其他开发人员朋友开始借用这些库,所以我感觉是时候将这些开源了。

EasyTest

让我感到非常烦恼的是,当模拟具有大量字段实体的测试用例时,你通常只关心一两个字段。所以EasyTestTrait的核心是createGeneric方法。

以下代码将生成两个Project实体,它们具有(主要)随机值,除了

  1. project1.name将name属性设置为"ExampleProject"
  2. project2.name将name属性设置为"ExampleProject2"
  • 注意,这些实体实际上将被保存在它们相应的模型上。
  • EasyTestTrait将检查表架构,并根据每列的类型生成随机值
$project1 = $this->genericCreate("Project",[
    "name" => "ExampleProject"
]);
$project2 = $this->genericCreate("Project",[
    "name" => "ExampleProject2"
]);
//Project1
Project {
    "project_id" => 1,
    "name" => "ExampleProject",
    "is_premium" => true,
    "size" => 5 
}

Project {
    "project_id" => 2,
    "name" => "ExampleProject2",
    "is_premium" => false,
    "size" => 17
}

关系

有时你会有强制性的依赖关系,所以我会这样做

创建一个特定项目的测试特性(例如ProjectTestTrait.php

function createUser(array $overrides = []) : User{
    return $this->genericCreate("Users", [
        "password" => hash("sha256","stupidPassword")
    ], $overrides);
}

function createProject(User $owner, array $overrides = []) : Project {
    return $this->genericCreate("Users", [
        "owner_id" => $owner->user_id
    ], $overrides);
}

//create a User entity, and ensure it's is_admin property is set to true
$user = $this->createUser(['is_admin' => true]);
//create a project, using the created user as its owner
$project = $this->createProject($user);

EasyAuth

对我来说,最常见的授权方式如下

  • 有人发起了一个请求,例如,/projects/view/1
  • 你需要确认当前登录的User是否与具有project_id =1Project有特定的关系

使用EasyAuth,你只需要这样做

  • 第一个参数是Project的标识符

GET请求

function isAuthorized(?User $user = null) : bool {
    switch ($this->getRequest()->getAction()) {
        case "view":
            //Here we tell EasyAuth that param 0 should be used to ->get() on the Projects model.
            return  $this->easyAuth([0 => "Projects"], function (Project $project) {
                return $project->isMember($user);            
            }) ;
        default:
            return parent::isAuthorized($user); 
    }
}

这可以更简洁地表示

    $action = $this->getRequest()->getAction();
    if ($action === "view") {
        $this->loadModel("Projects");
        try {
            $project = $this->Projects->get($this->getRequest()->getParam(0));
            return $project->isMember($user);
        } catch (Exception e) {
            return false;
        }
    }

这也具有优势,即可以将具有相同授权逻辑的多个操作分组在一起

function isAuthorized(?User $user = null) : bool {
    switch ($this->getRequest()->getAction()) {
        case "view":
        case "delete":
        case "edit":
            //Here we tell EasyAuth that param 0 should be used to ->get() on the Projects model.
            return  $this->easyAuth([0 => "Projects"], function (Project $project) {
                return $project->isMember($user);            
            }) ;
        default:
            return parent::isAuthorized($user); 
    }
}

POST请求

可以为POST请求执行与GET请求类似的操作,但参数的命名与POST名称相同

function isAuthorized(?User $user = null) : bool {
    switch ($this->getRequest()->getAction()) {
        case "view":
        case "delete":
        case "edit":
            //Here we tell EasyAuth that post-param "project_id" should be used to ->get() on the Projects model.
            return  $this->eastPostAuth(["project_id" => "Projects"], function (Project $project) {
                return $project->isMember($user);            
            }) ;
        default:
            return parent::isAuthorized($user); 
    }
}

ErrorPrevention

由于WordPress漏洞扫描器扰乱我的Sentry日志(或任何错误日志),我感到非常痛苦。所以我决定编写一些基本的规则,以防止每次从GET /wp-adminGET /rpc.php获得ControllerNotFoundException时,CakeSentry记录错误。这变成了一种可扩展的系统,可以轻松地忽略你明显不关心的错误。

//in Application.php
function buildMiddlewareQueue(MiddlewareQueue $middleWare) : MiddlewareQueue{
    parent::buildMiddlewareQueue($middleWare);
    $errorPrevention = new ErrorPreventionMiddleware();
    
    $errorPrevention->add(WordpressRequests::class);
    $errorPrevention->add(ASPRequests::class);
    $errorPrevention->add(ExternalInvalidUrls::class);
    
    $middleWare->add($errorPrevention);
    return $middleWare;  
}
  • WordPressRequests将忽略所有与某人请求WordPress URL相关的异常
  • ExternalInvalidUrl检查由于无效请求URL(例如MissingControllerExceptionArgumentCountError)而产生的异常。然后它会尝试确认此请求是由于我们的应用程序内的链接错误,还是某人手动输入了错误的URL(例如referer = /)。在后一种情况下,这几乎不是我们应用程序的问题。因此,错误不是我们应用程序的错。
  • ASPRequests 会忽略由用户请求 .asp 文件引起的所有异常