请求参数 – 永夜 https://www.shuijingwanwq.com 没有不值得去解决的问题,也没有不值得去学习的技术! Thu, 28 May 2026 12:21:50 +0000 zh-Hans hourly 1 https://wordpress.org/?v=7.0 在 yii2 的 backend 应用中,当前用户可以切换角色,希望在所有链接中一直具有一个 role=distributor 或者 role=management。视图中的链接实现 echo Url::toRoute(‘/user/profile’); 。如何实现? https://www.shuijingwanwq.com/2025/06/09/9104/ https://www.shuijingwanwq.com/2025/06/09/9104/#respond Mon, 09 Jun 2025 07:50:26 +0000 https://www.shuijingwanwq.com/?p=9104 浏览量: 96

1、现在切换角色为 distributor 的入口链接是后台首页:https://console.apply.local/?role=distributor

2、希望此入口网址中,所以的链接都自动添加上请求参数:role=distributor ,现在是没有的。如图1

希望此入口网址中,所以的链接都自动添加上请求参数:role=distributor ,现在是没有的

图1

3、创建自定义 UrlManager 组件 重写 createUrl 方法,当网址上的角色参数为 distributor 或者 service 时自动附加当前角色参数。


<?php

namespace management\components;

use Yii;

class UrlManager extends \yii\web\UrlManager
{
    public function createUrl($params): string
    {
        $role = Yii::$app->request->get('role', 'management');
        if (in_array($role, ['distributor', 'service'])) {
            $params['role'] = $role;
        }

        return parent::createUrl($params);
    }
}


4、配置应用使用自定义 UrlManager 在 backend 配置文件中替换默认的 urlManager。


        'urlManager' => [
            'class' => 'management\components\UrlManager',
        ],


5、此入口网址中,所有的链接都自动添加上请求参数:role=distributor。符合预期。如图2

此入口网址中,所有的链接都自动添加上请求参数:role=distributor。符合预期
图2

6、但是,其中有几个链接 不应该添加上请求参数:role=distributor。恰是需要取消掉。如图3

但是,其中有几个链接 不应该添加上请求参数:role=distributor。恰是需要取消掉
图3

7、在生成链接时,手动加一个标志位

‘_skip_role’ => true

,然后在 createUrl() 中判断


<?php

namespace management\components;

use Yii;

class UrlManager extends \yii\web\UrlManager
{
    public function createUrl($params): string
    {
        if (!isset($params['_skip_role'])) {
            // 仅当 role 为 distributor|service 时,才支持参数 role
            $role = Yii::$app->request->get('role', 'management');
            if (in_array($role, ['distributor', 'service']) && !isset($params['role'])) {
                $params['role'] = $role;
            }
        } else {
            unset($params['_skip_role']); // 清除这个临时参数,避免出现在 URL 中
        }

        return parent::createUrl($params);
    }
}


8、在视图中按照如下方式使用,生成的 链接 符合预期。如图4

在视图中按照如下方式使用,生成的 链接 符合预期

图4


<div class="col-6 mb-3 text-right">
        <a class="btn btn-warning btn-rounded" href="<?php echo Url::toRoute(['/', '_skip_role' => true]); ?>">管理 <?php echo $eventCount['management'];?></a>  <!-- / -->
        <a class="btn btn-danger btn-rounded" href="<?php echo Url::toRoute(['/', 'role' => 'distributor']); ?>">联络 <?php echo $eventCount['distributor'];?></a> <!-- /?role=distributor -->
        <a class="btn btn-purple btn-rounded" href="<?php echo Url::toRoute(['/', 'role' => 'service']); ?>">接待 <?php echo $eventCount['service'];?></a> <!-- /?role=service -->
    </div>



]]>
https://www.shuijingwanwq.com/2025/06/09/9104/feed/ 0
在 Lighthouse 5 中,基于 PHPUnit 编写 Mutation 的测试 https://www.shuijingwanwq.com/2022/04/01/6233/ https://www.shuijingwanwq.com/2022/04/01/6233/#respond Fri, 01 Apr 2022 01:27:44 +0000 https://www.shuijingwanwq.com/?p=6233 浏览量: 87

1、在 Altair GraphQl Client 中运行成功。如图1

在 Altair GraphQl Client 中运行成功。

图1


mutation CreateThemeAsset {
  onlineStoreThemeAssetCreate(
    input: { themeId: "vogue", content: "string", key: "js/20220307.4.js" }
  ) {
    themeAsset {
      themeId
      key
      content
    }
  }
}





{
  "data": {
    "onlineStoreThemeAssetCreate": {
      "themeAsset": {
        "themeId": "vogue",
        "key": "js/20220307.4.js",
        "content": "string"
      }
    }
  }
}


2、编辑测试文件,/Modules/ThemeStore/Tests/Functional/GraphQl/MutationThemeAssetGraphQlApiTest.php。

<?php
 
namespace Modules\ThemeStore\Tests\Functional\GraphQl;
 
use Nuwave\Lighthouse\Testing\MakesGraphQLRequests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Nuwave\Lighthouse\Testing\ClearsSchemaCache;
use Sentry\Util\JSON;
use Tests\CreatesApplication;
 
class MutationThemeAssetGraphQlApiTest extends BaseTestCase
{
    use CreatesApplication,
        ClearsSchemaCache,
        MakesGraphQLRequests;
 
    public function testCreateThemeAsset(): void
    {
 
        $input = [
            'themeId' => 'vogue',
            'content' => 'string',
            'key' => 'js/20220307.8.js',
        ];
 
        $response = $this->graphQL('
            mutation CreateThemeAsset($input: ThemeAssetCreateInput!) {
                onlineStoreThemeAssetCreate(input: $input) {
                    themeAsset {
                        themeId
                        key
                        content
                    }
                }
            }
        ', [
            'input' => json_encode($input)
        ]);
 
        $response->assertJson(
            [
                'data' => [
                    'onlineStoreThemeAssetCreate' => [
                        'themeAsset' => $input
                    ],
                ],
            ]
        );
    }
 
    protected function setUp(): void
    {
        parent::setUp();
 
        $this->bootClearsSchemaCache();
    }
}
 
 
 

3、运行测试用例,报错:Expected type ThemeAssetCreateInput to be an object.。如图2

运行测试用例,报错:Expected type ThemeAssetCreateInput to be an object.。

图2


PS E:\wwwroot\object> ./vendor/bin/phpunit --process-isolation .\Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest.php
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 2.89 seconds, Memory: 16.00 MB

There was 1 failure:

1) Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest::testCreateThemeAsset
Unable to find JSON:

[{
    "data": {
        "onlineStoreThemeAssetCreate": {
            "themeAsset": {
                "themeId": "vogue",
                "content": "string",
                "key": "js/20220307.8.js"
            }
        }
    }
}]

within response JSON:

[{
    "errors": [
        {
            "message": "Variable \"$input\" got invalid value \"{\"themeId\":\"vogue\",\"content\":\"string\",\"key\":\"js\\/20220307.8.js\"}\"; Expected type ThemeAssetCreateInput to be an object.",
            "extensions": {
                "category": "graphql"
            },
            "locations": [
                {
                    "line": 2,
                    "column": 39
                }
            ]
        }
    ]
}].


Failed asserting that an array has the subset Array &0 (
    'data' => Array &1 (
        'onlineStoreThemeAssetCreate' => Array &2 (
            'themeAsset' => Array &3 (
                'themeId' => 'vogue'
                'content' => 'string'
                'key' => 'js/20220307.8.js'
            )
        )
    )
).
--- Expected
+++ Actual
@@ @@
       ),
     ),
   ),
-  'data' =>
-  array (
-    'onlineStoreThemeAssetCreate' =>
-    array (
-      'themeAsset' =>
-      array (
-        'themeId' => 'vogue',
-        'content' => 'string',
-        'key' => 'js/20220307.8.js',
-      ),
-    ),
-  ),
 )

E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Assert.php:108
E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:479
E:\wwwroot\object\Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest.php:56

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
PS E:\wwwroot\object>


4、重新编辑测试文件

<?php
 
namespace Modules\ThemeStore\Tests\Functional\GraphQl;
 
use Nuwave\Lighthouse\Testing\MakesGraphQLRequests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Nuwave\Lighthouse\Testing\ClearsSchemaCache;
use Sentry\Util\JSON;
use Tests\CreatesApplication;
 
class MutationThemeAssetGraphQlApiTest extends BaseTestCase
{
    use CreatesApplication,
        ClearsSchemaCache,
        MakesGraphQLRequests;
 
    public function testCreateThemeAsset(): void
    {
        $input = [
            'themeId' => 'vogue',
            'content' => 'string',
            'key' => 'js/20220307.9.js',
        ];
 
        $response = $this->graphQL('
            mutation CreateThemeAsset($input: ThemeAssetCreateInput!) {
                onlineStoreThemeAssetCreate(input: $input) {
                    themeAsset {
                        themeId
                        key
                        content
                    }
                }
            }
        ', [
            'input' => json_decode(json_encode($input))
        ]);
 
        $response->assertJson(
            [
                'data' => [
                    'onlineStoreThemeAssetCreate' => [
                        'themeAsset' => $input
                    ],
                ],
            ]
        );
    }
 
    protected function setUp(): void
    {
        parent::setUp();
 
        $this->bootClearsSchemaCache();
    }
}
 

5、再次运行测试,测试通过。


PS E:\wwwroot\object> ./vendor/bin/phpunit --process-isolation .\Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest.php
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 2.61 seconds, Memory: 16.00 MB

OK (1 test, 1 assertion)


6、再运行一次测试,测试未通过。原因在于同样的请求参数,不允许重复,否则验证失败,进而测试未通过断言。


PS E:\wwwroot\object> ./vendor/bin/phpunit --process-isolation .\Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest.php
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 2.77 seconds, Memory: 18.00 MB

There was 1 failure:

1) Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest::testCreateThemeAsset
Unable to find JSON:

[{
    "data": {
        "onlineStoreThemeAssetCreate": {
            "themeAsset": {
                "themeId": "vogue",
                "content": "string",
                "key": "js/20220307.9.js"
            }
        }
    }
}]

within response JSON:

[{
    "errors": [
        {
            "message": "Validation failed for the field [onlineStoreThemeAssetCreate].",
            "extensions": {
                "validation": {
                    "input.key": [
                        "The input.key has already been taken"
                    ]
                },
                "category": "validation"
            },
            "locations": [
                {
                    "line": 3,
                    "column": 17
                }
            ],
            "path": [
                "onlineStoreThemeAssetCreate"
            ],
            "trace": [
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Schema\\Directives\\ArgTraversalDirective.php",
                    "line": 29,
                    "call": "Nuwave\\Lighthouse\\Validation\\ValidateDirective::Nuwave\\Lighthouse\\Validation\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Schema\\Directives\\TrimDirective.php",
                    "line": 56,
                    "call": "Nuwave\\Lighthouse\\Schema\\Directives\\ArgTraversalDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Schema\\Factories\\FieldFactory.php",
                    "line": 99,
                    "call": "Nuwave\\Lighthouse\\Schema\\Directives\\TrimDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 623,
                    "call": "Nuwave\\Lighthouse\\Schema\\Factories\\FieldFactory::Nuwave\\Lighthouse\\Schema\\Factories\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 550,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::resolveFieldValueOrError(instance of GraphQL\\Type\\Definition\\FieldDefinition, instance of GraphQL\\Language\\AST\\FieldNode, instance of Closure, null, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 474,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::resolveField(GraphQLType: Mutation, null, instance of ArrayObject(1), array(1))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 857,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::GraphQL\\Executor\\{closure}(array(0), 'onlineStoreThemeAssetCreate')"
                },
                {
                    "call": "GraphQL\\Executor\\ReferenceExecutor::GraphQL\\Executor\\{closure}(array(0), 'onlineStoreThemeAssetCreate')"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 859,
                    "function": "array_reduce(array(1), instance of Closure, array(0))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 490,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::promiseReduce(array(1), instance of Closure, array(0))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 263,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::executeFieldsSerially(GraphQLType: Mutation, null, array(0), instance of ArrayObject(1))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
                    "line": 215,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::executeOperation(instance of GraphQL\\Language\\AST\\OperationDefinitionNode, null)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\Executor.php",
                    "line": 156,
                    "call": "GraphQL\\Executor\\ReferenceExecutor::doExecute()"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\GraphQL.php",
                    "line": 162,
                    "call": "GraphQL\\Executor\\Executor::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(1), null, null)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\GraphQL.php",
                    "line": 94,
                    "call": "GraphQL\\GraphQL::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(1), null, null, array(29))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
                    "line": 268,
                    "call": "GraphQL\\GraphQL::executeQuery(instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(1), null, null, array(29))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
                    "line": 203,
                    "call": "Nuwave\\Lighthouse\\GraphQL::executeParsedQuery(instance of GraphQL\\Language\\AST\\DocumentNode, instance of Nuwave\\Lighthouse\\Schema\\Context, array(1), null, null)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
                    "line": 162,
                    "call": "Nuwave\\Lighthouse\\GraphQL::parseAndExecuteQuery('\n            mutation CreateThemeAsset($input: ThemeAssetCreateInput!) {\n                onlineStoreThemeAssetCreate(input: $input) {\n                    themeAsset {\n                        themeId\n                        key\n                        content\n                    }\n                }\n            }\n        ', instance of Nuwave\\Lighthouse\\Schema\\Context, array(1), null, null)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
                    "line": 121,
                    "call": "Nuwave\\Lighthouse\\GraphQL::executeOperation(instance of GraphQL\\Server\\OperationParams, instance of Nuwave\\Lighthouse\\Schema\\Context)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Utils.php",
                    "line": 99,
                    "call": "Nuwave\\Lighthouse\\GraphQL::Nuwave\\Lighthouse\\{closure}(instance of GraphQL\\Server\\OperationParams)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
                    "line": 120,
                    "call": "Nuwave\\Lighthouse\\Support\\Utils::applyEach(instance of Closure, instance of GraphQL\\Server\\OperationParams)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Controllers\\GraphQLController.php",
                    "line": 32,
                    "call": "Nuwave\\Lighthouse\\GraphQL::executeOperationOrOperations(instance of GraphQL\\Server\\OperationParams, instance of Nuwave\\Lighthouse\\Schema\\Context)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php",
                    "line": 48,
                    "call": "Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController::__invoke(instance of Illuminate\\Http\\Request, instance of Nuwave\\Lighthouse\\GraphQL, instance of Illuminate\\Events\\Dispatcher, instance of Laragraph\\Utils\\RequestParser, instance of Nuwave\\Lighthouse\\Execution\\SingleResponse, instance of Nuwave\\Lighthouse\\Execution\\ContextFactory)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
                    "line": 219,
                    "call": "Illuminate\\Routing\\ControllerDispatcher::dispatch(instance of Illuminate\\Routing\\Route, instance of Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController, '__invoke')"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
                    "line": 176,
                    "call": "Illuminate\\Routing\\Route::runController()"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
                    "line": 681,
                    "call": "Illuminate\\Routing\\Route::run()"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 130,
                    "call": "Illuminate\\Routing\\Router::Illuminate\\Routing\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Middleware\\AttemptAuthentication.php",
                    "line": 34,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AttemptAuthentication::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Middleware\\AcceptJson.php",
                    "line": 27,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AcceptJson::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 105,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
                    "line": 683,
                    "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
                    "line": 658,
                    "call": "Illuminate\\Routing\\Router::runRouteWithinStack(instance of Illuminate\\Routing\\Route, instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
                    "line": 624,
                    "call": "Illuminate\\Routing\\Router::runRoute(instance of Illuminate\\Http\\Request, instance of Illuminate\\Routing\\Route)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
                    "line": 613,
                    "call": "Illuminate\\Routing\\Router::dispatchToRoute(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
                    "line": 170,
                    "call": "Illuminate\\Routing\\Router::dispatch(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 130,
                    "call": "Illuminate\\Foundation\\Http\\Kernel::Illuminate\\Foundation\\Http\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\barryvdh\\laravel-debugbar\\src\\Middleware\\InjectDebugbar.php",
                    "line": 60,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Barryvdh\\Debugbar\\Middleware\\InjectDebugbar::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\app\\Http\\Middleware\\ChangeAppUrlMiddleware.php",
                    "line": 23,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "App\\Http\\Middleware\\ChangeAppUrlMiddleware::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php",
                    "line": 21,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php",
                    "line": 21,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php",
                    "line": 27,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode.php",
                    "line": 63,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\fideloper\\proxy\\src\\TrustProxies.php",
                    "line": 57,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Fideloper\\Proxy\\TrustProxies::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\dingo\\api\\src\\Http\\Middleware\\Request.php",
                    "line": 111,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 171,
                    "call": "Dingo\\Api\\Http\\Middleware\\Request::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
                    "line": 105,
                    "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
                    "line": 145,
                    "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
                    "line": 110,
                    "call": "Illuminate\\Foundation\\Http\\Kernel::sendRequestThroughRouter(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests.php",
                    "line": 470,
                    "call": "Illuminate\\Foundation\\Http\\Kernel::handle(instance of Illuminate\\Http\\Request)"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests.php",
                    "line": 442,
                    "call": "Illuminate\\Foundation\\Testing\\TestCase::call('POST', 'https://object.local/graphql', array(0), array(0), array(1), array(3), '{\"query\":\"\\n            mutation CreateThemeAsset($input: ThemeAssetCreateInput!) {\\n                onlineStoreThemeAssetCreate(input: $input) {\\n                    themeAsset {\\n                        themeId\\n                        key\\n                        content\\n                    }\\n                }\\n            }\\n        \",\"variables\":{\"input\":{\"themeId\":\"vogue\",\"content\":\"string\",\"key\":\"js\\/20220307.9.js\"}}}')"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests.php",
                    "line": 301,
                    "call": "Illuminate\\Foundation\\Testing\\TestCase::json('POST', 'https://object.local/graphql', array(2), array(3))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Testing\\MakesGraphQLRequests.php",
                    "line": 79,
                    "call": "Illuminate\\Foundation\\Testing\\TestCase::postJson('https://object.local/graphql', array(2), array(0))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Testing\\MakesGraphQLRequests.php",
                    "line": 62,
                    "call": "Modules\\ThemeStore\\Tests\\Functional\\GraphQl\\MutationThemeAssetGraphQlApiTest::postGraphQL(array(2), array(0))"
                },
                {
                    "file": "E:\\wwwroot\\object\\Modules\\ThemeStore\\Tests\\Functional\\GraphQl\\MutationThemeAssetGraphQlApiTest.php",
                    "line": 36,
                    "call": "Modules\\ThemeStore\\Tests\\Functional\\GraphQl\\MutationThemeAssetGraphQlApiTest::graphQL('\n            mutation CreateThemeAsset($input: ThemeAssetCreateInput!) {\n                onlineStoreThemeAssetCreate(input: $input) {\n                    themeAsset {\n                        themeId\n                        key\n                        content\n                    }\n                }\n            }\n        ', array(1))"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\phpunit\\phpunit\\src\\Framework\\TestCase.php",
                    "line": 1154,
                    "call": "Modules\\ThemeStore\\Tests\\Functional\\GraphQl\\MutationThemeAssetGraphQlApiTest::testCreateThemeAsset()"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\phpunit\\phpunit\\src\\Framework\\TestCase.php",
                    "line": 842,
                    "call": "PHPUnit\\Framework\\TestCase::runTest()"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\phpunit\\phpunit\\src\\Framework\\TestResult.php",
                    "line": 693,
                    "call": "PHPUnit\\Framework\\TestCase::runBare()"
                },
                {
                    "file": "E:\\wwwroot\\object\\vendor\\phpunit\\phpunit\\src\\Framework\\TestCase.php",
                    "line": 796,
                    "call": "PHPUnit\\Framework\\TestResult::run(instance of Modules\\ThemeStore\\Tests\\Functional\\GraphQl\\MutationThemeAssetGraphQlApiTest(1))"
                },
                {
                    "file": "C:\\Users\\Lenovo\\AppData\\Local\\Temp\\PHP57E0.tmp",
                    "line": 261,
                    "call": "PHPUnit\\Framework\\TestCase::run(instance of PHPUnit\\Framework\\TestResult(1))"
                },
                {
                    "file": "C:\\Users\\Lenovo\\AppData\\Local\\Temp\\PHP57E0.tmp",
                    "line": 1040,
                    "function": "__phpunit_run_isolated_test()"
                }
            ]
        }
    ],
    "data": {
        "onlineStoreThemeAssetCreate": null
    }
}].


Failed asserting that an array has the subset Array &0 (
    'data' => Array &1 (
        'onlineStoreThemeAssetCreate' => Array &2 (
            'themeAsset' => Array &3 (
                'themeId' => 'vogue'
                'content' => 'string'
                'key' => 'js/20220307.9.js'
            )
        )
    )
).
--- Expected
+++ Actual
@@ @@
   ),
   'data' =>
   array (
-    'onlineStoreThemeAssetCreate' =>
-    array (
-      'themeAsset' =>
-      array (
-        'themeId' => 'vogue',
-        'content' => 'string',
-        'key' => 'js/20220307.9.js',
-      ),
-    ),
+    'onlineStoreThemeAssetCreate' => NULL,
   ),
 )

E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Assert.php:108
E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:479
E:\wwwroot\object\Modules\ThemeStore\Tests\Functional\GraphQl\MutationThemeAssetGraphQlApiTest.php:43

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
PS E:\wwwroot\object>



7、虽然现在针对测试用例配置了一个单独的测试数据库,无需要担心影响到开发数据库。但是要避免多次测试时,测试不通过的问题,决定尽量避免掉请求参数的重复。将变量 key 的值基于时间戳生成。其值示例:js/20220307144656.js。这样可以保证在每一秒钟可以运行一次测试,且能够通过。后续可以在此测试文件中添加一个测试删除此条创建的记录的方法。如图3

虽然现在针对测试用例配置了一个单独的测试数据库,无需要担心影响到开发数据库。但是要避免多次测试时,测试不通过的问题,决定尽量避免掉请求参数的重复。将变量 key 的值基于时间戳生成。其值示例:js/20220307144656.js。这样可以保证在每一秒钟可以运行一次测试,且能够通过。后续可以在此测试文件中添加一个测试删除此条创建的记录的方法。

图3


        $input = [
            'themeId' => 'vogue',
            'content' => 'string',
            'key' => 'js/' . date('YmdHis') . '.js',
        ];


 

]]>
https://www.shuijingwanwq.com/2022/04/01/6233/feed/ 0
在 Laravel 6、Module、Lighthouse 中实现 安全 验证 的流程(使用验证器类来支持复杂的验证规则) https://www.shuijingwanwq.com/2022/03/25/6196/ https://www.shuijingwanwq.com/2022/03/25/6196/#respond Fri, 25 Mar 2022 01:16:13 +0000 https://www.shuijingwanwq.com/?p=6196 浏览量: 172

1、当请求响应成功时的结构。如图1

当请求响应成功时的结构。

图1



mutation {
  onlineStoreThemeAssetCreate(
    input: { themeId: "vogue", content: "string", key: "string" }
  ) {
    themeAsset {
      id
      themeId
      content
      key
      mimeType
      category
      schema
      createdAt
      updatedAt
      deletable
      renameable
      updatable
    }
  }
}




{
  "data": {
    "onlineStoreThemeAssetCreate": {
      "themeAsset": {
        "id": "653",
        "themeId": "vogue",
        "content": "string",
        "key": "string",
        "mimeType": "text/x-php",
        "category": "unknown",
        "schema": null,
        "createdAt": "2022-02-25 01:49:53",
        "updatedAt": "2022-02-25 01:49:53",
        "deletable": false,
        "renameable": false,
        "updatable": false
      }
    }
  }
}


2、但是,现阶段并未针对请求参数进行安全验证。参考:https://lighthouse-php.com/master/security/validation.html#single-arguments 。Lighthouse 允许您在查询和变更中使用 Laravel 的验证。如图2

但是,现阶段并未针对请求参数进行安全验证。参考:https://lighthouse-php.com/master/security/validation.html#single-arguments 。Lighthouse 允许您在查询和变更中使用 Laravel 的验证。

图2

3、此 GraphQL API 的变更虽然在输入对象中仅有 3 个参数,但是验证规则比较复杂。包含如下规则:
(1)验证表中是否存在 themeId: “vogue” 的记录,如果不存在,验证失败;


SELECT * FROM `object_store`.`theme_asset` WHERE `theme_id` = 'vogue' LIMIT 0,1


(2)验证 key: “string” 的格式,其必须为一个有效的相对路径,例:assets/iconfont/iconfont.css。其值等于 string ,验证失败;
(3)验证 key: “string” 的格式,其为一个有效的相对路径后,其文件后缀名必须属于一个预先定义的数组中,例:[‘json’, ‘css’, ‘js’];
(4)验证表中 themeId: “vogue”, key: “string” 记录的唯一性,如果已存在,验证失败;


SELECT * FROM `object_store`.`theme_asset` WHERE `theme_id` = 'vogue' AND `asset_key` = 'string' LIMIT 0,1


(5)验证 content: “string” 的格式,例:当 key 的值的文件后缀名为 .json 时,需要验证 content 的值格式为 json 格式;
(6)mime_type 的值需要基于 key 的值转换得出;
(7)category 的值需要基于 key 的值转换得出;

4、使用验证器类来支持复杂的验证规则。Lighthouse 对验证器类使用简单的命名约定,只需使用输入类型的名称并附加 Validator 。最终生成文件:/app/GraphQL/Validators/CreateOnlineStoreThemeAssetInputValidator.php


PS E:\wwwroot\lighthouse-tutorial> php artisan lighthouse:validator CreateOnlineStoreThemeAssetInputValidator
Validator created successfully.


5、由于现在需要在 Module ThemeStore 中使用此验证器类,将文件:/app/GraphQL/Validators/CreateOnlineStoreThemeAssetInputValidator.php 剪切至:/Modules/ThemeStore/Validators/CreateOnlineStoreThemeAssetInputValidator.php

<?php
 
namespace Modules\ThemeStore\Validators;
 
use Nuwave\Lighthouse\Validation\Validator;
 
class CreateOnlineStoreThemeAssetInputValidator extends Validator
{
    /**
     * Return the validation rules.
     *
     * @return array<string, array<mixed>>
     */
    public function rules(): array
    {
        return [
            'themeId' => [
                'exists:theme_asset,theme_id'
            ],
        ];
    }
}

6、编辑文件:/Modules/ThemeStore/Resources/graphql/theme_asset.graphql,修改输入对象,使用 @validator 指令,以指定验证器类


input OnlineStoreThemeAssetCreateInput @validator(class: "Modules\\ThemeStore\\Validators\\CreateOnlineStoreThemeAssetInputValidator") {
    "主题ID"
    themeId: String!,
    "内容"
    content: String!,
    "路径,相对于主题的路径,如 pages/index.blade.php"
    key: String!,
}


7、测试验证规则是否有效,确定有效。如图3

测试验证规则是否有效,确定有效。

图3



mutation {
  onlineStoreThemeAssetCreate(
    input: { themeId: "vogue1", content: "string", key: "string" }
  ) {
    themeAsset {
      id
      themeId
      content
      key
      mimeType
      category
      schema
      createdAt
      updatedAt
      deletable
      renameable
      updatable
    }
  }
}




{
  "errors": [
    {
      "message": "Validation failed for the field [onlineStoreThemeAssetCreate].",
      "extensions": {
        "validation": {
          "input.themeId": [
            "The selected input.theme id is invalid."
          ]
        },
        "category": "validation"
      },
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "onlineStoreThemeAssetCreate"
      ],
      "trace": [
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Schema\\Directives\\ArgTraversalDirective.php",
          "line": 29,
          "call": "Nuwave\\Lighthouse\\Validation\\ValidateDirective::Nuwave\\Lighthouse\\Validation\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Schema\\Directives\\TrimDirective.php",
          "line": 56,
          "call": "Nuwave\\Lighthouse\\Schema\\Directives\\ArgTraversalDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Schema\\Factories\\FieldFactory.php",
          "line": 99,
          "call": "Nuwave\\Lighthouse\\Schema\\Directives\\TrimDirective::Nuwave\\Lighthouse\\Schema\\Directives\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 623,
          "call": "Nuwave\\Lighthouse\\Schema\\Factories\\FieldFactory::Nuwave\\Lighthouse\\Schema\\Factories\\{closure}(null, array(1), instance of Nuwave\\Lighthouse\\Schema\\Context, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 550,
          "call": "GraphQL\\Executor\\ReferenceExecutor::resolveFieldValueOrError(instance of GraphQL\\Type\\Definition\\FieldDefinition, instance of GraphQL\\Language\\AST\\FieldNode, instance of Closure, null, instance of GraphQL\\Type\\Definition\\ResolveInfo)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 474,
          "call": "GraphQL\\Executor\\ReferenceExecutor::resolveField(GraphQLType: Mutation, null, instance of ArrayObject(1), array(1))"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 857,
          "call": "GraphQL\\Executor\\ReferenceExecutor::GraphQL\\Executor\\{closure}(array(0), 'onlineStoreThemeAssetCreate')"
        },
        {
          "call": "GraphQL\\Executor\\ReferenceExecutor::GraphQL\\Executor\\{closure}(array(0), 'onlineStoreThemeAssetCreate')"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 859,
          "function": "array_reduce(array(1), instance of Closure, array(0))"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 490,
          "call": "GraphQL\\Executor\\ReferenceExecutor::promiseReduce(array(1), instance of Closure, array(0))"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 263,
          "call": "GraphQL\\Executor\\ReferenceExecutor::executeFieldsSerially(GraphQLType: Mutation, null, array(0), instance of ArrayObject(1))"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\ReferenceExecutor.php",
          "line": 215,
          "call": "GraphQL\\Executor\\ReferenceExecutor::executeOperation(instance of GraphQL\\Language\\AST\\OperationDefinitionNode, null)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\Executor\\Executor.php",
          "line": 156,
          "call": "GraphQL\\Executor\\ReferenceExecutor::doExecute()"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\GraphQL.php",
          "line": 162,
          "call": "GraphQL\\Executor\\Executor::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\webonyx\\graphql-php\\src\\GraphQL.php",
          "line": 94,
          "call": "GraphQL\\GraphQL::promiseToExecute(instance of GraphQL\\Executor\\Promise\\Adapter\\SyncPromiseAdapter, instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null, array(29))"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
          "line": 268,
          "call": "GraphQL\\GraphQL::executeQuery(instance of GraphQL\\Type\\Schema, instance of GraphQL\\Language\\AST\\DocumentNode, null, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null, array(29))"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
          "line": 203,
          "call": "Nuwave\\Lighthouse\\GraphQL::executeParsedQuery(instance of GraphQL\\Language\\AST\\DocumentNode, instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
          "line": 162,
          "call": "Nuwave\\Lighthouse\\GraphQL::parseAndExecuteQuery('mutation {\n  onlineStoreThemeAssetCreate(\n    input: { themeId: \"vogue1\", content: \"string\", key: \"string\" }\n  ) {\n    themeAsset {\n      id\n      themeId\n      content\n      key\n      mimeType\n      category\n      schema\n      createdAt\n      updatedAt\n      deletable\n      renameable\n      updatable\n    }\n  }\n}', instance of Nuwave\\Lighthouse\\Schema\\Context, array(0), null, null)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
          "line": 121,
          "call": "Nuwave\\Lighthouse\\GraphQL::executeOperation(instance of GraphQL\\Server\\OperationParams, instance of Nuwave\\Lighthouse\\Schema\\Context)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Utils.php",
          "line": 99,
          "call": "Nuwave\\Lighthouse\\GraphQL::Nuwave\\Lighthouse\\{closure}(instance of GraphQL\\Server\\OperationParams)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\GraphQL.php",
          "line": 120,
          "call": "Nuwave\\Lighthouse\\Support\\Utils::applyEach(instance of Closure, instance of GraphQL\\Server\\OperationParams)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Controllers\\GraphQLController.php",
          "line": 32,
          "call": "Nuwave\\Lighthouse\\GraphQL::executeOperationOrOperations(instance of GraphQL\\Server\\OperationParams, instance of Nuwave\\Lighthouse\\Schema\\Context)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php",
          "line": 48,
          "call": "Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController::__invoke(instance of Illuminate\\Http\\Request, instance of Nuwave\\Lighthouse\\GraphQL, instance of Illuminate\\Events\\Dispatcher, instance of Laragraph\\Utils\\RequestParser, instance of Nuwave\\Lighthouse\\Execution\\SingleResponse, instance of Nuwave\\Lighthouse\\Execution\\ContextFactory)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
          "line": 219,
          "call": "Illuminate\\Routing\\ControllerDispatcher::dispatch(instance of Illuminate\\Routing\\Route, instance of Nuwave\\Lighthouse\\Support\\Http\\Controllers\\GraphQLController, '__invoke')"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
          "line": 176,
          "call": "Illuminate\\Routing\\Route::runController()"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
          "line": 681,
          "call": "Illuminate\\Routing\\Route::run()"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 130,
          "call": "Illuminate\\Routing\\Router::Illuminate\\Routing\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Middleware\\AttemptAuthentication.php",
          "line": 34,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AttemptAuthentication::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\nuwave\\lighthouse\\src\\Support\\Http\\Middleware\\AcceptJson.php",
          "line": 27,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Nuwave\\Lighthouse\\Support\\Http\\Middleware\\AcceptJson::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 105,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
          "line": 683,
          "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
          "line": 658,
          "call": "Illuminate\\Routing\\Router::runRouteWithinStack(instance of Illuminate\\Routing\\Route, instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
          "line": 624,
          "call": "Illuminate\\Routing\\Router::runRoute(instance of Illuminate\\Http\\Request, instance of Illuminate\\Routing\\Route)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php",
          "line": 613,
          "call": "Illuminate\\Routing\\Router::dispatchToRoute(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
          "line": 170,
          "call": "Illuminate\\Routing\\Router::dispatch(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 130,
          "call": "Illuminate\\Foundation\\Http\\Kernel::Illuminate\\Foundation\\Http\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\barryvdh\\laravel-debugbar\\src\\Middleware\\InjectDebugbar.php",
          "line": 67,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Barryvdh\\Debugbar\\Middleware\\InjectDebugbar::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\app\\Http\\Middleware\\ChangeAppUrlMiddleware.php",
          "line": 23,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "App\\Http\\Middleware\\ChangeAppUrlMiddleware::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php",
          "line": 21,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php",
          "line": 21,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php",
          "line": 27,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode.php",
          "line": 63,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\fideloper\\proxy\\src\\TrustProxies.php",
          "line": 57,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Fideloper\\Proxy\\TrustProxies::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\dingo\\api\\src\\Http\\Middleware\\Request.php",
          "line": 111,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 171,
          "call": "Dingo\\Api\\Http\\Middleware\\Request::handle(instance of Illuminate\\Http\\Request, instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php",
          "line": 105,
          "call": "Illuminate\\Pipeline\\Pipeline::Illuminate\\Pipeline\\{closure}(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
          "line": 145,
          "call": "Illuminate\\Pipeline\\Pipeline::then(instance of Closure)"
        },
        {
          "file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php",
          "line": 110,
          "call": "Illuminate\\Foundation\\Http\\Kernel::sendRequestThroughRouter(instance of Illuminate\\Http\\Request)"
        },
        {
          "file": "E:\\wwwroot\\object\\public\\index.php",
          "line": 57,
          "call": "Illuminate\\Foundation\\Http\\Kernel::handle(instance of Illuminate\\Http\\Request)"
        }
      ]
    }
  ],
  "data": {
    "onlineStoreThemeAssetCreate": null
  }
}


8、查看 Laravel Telescope 中请求中的 SQL 语句。如图4

查看 Laravel Telescope 中请求中的 SQL 语句。

图4


select count(*) as aggregate from `theme_asset` where `theme_id` = 'vogue1'


]]>
https://www.shuijingwanwq.com/2022/03/25/6196/feed/ 0
在 PHP 7.4 中,带索引检查计算数组的差集,以对比 Body 中的请求参数与缓存中的数组是否相等 https://www.shuijingwanwq.com/2020/06/22/4268/ https://www.shuijingwanwq.com/2020/06/22/4268/#respond Mon, 22 Jun 2020 02:41:22 +0000 https://www.shuijingwanwq.com/?p=4268 浏览量: 86 1、在 Postman 中 POST:http://api.pcs-api.localhost/v1/mobile/rtcs/invite-accept ,将 Body 中的数据以数组的格式写入 Redis 缓存中,如图1
在 Postman 中 POST:http://api.pcs-api.localhost/v1/mobile/rtcs/invite-accept ,将 Body 中的数据以数组的格式写入 Redis 缓存中

图1

2、每一次请求时,Body 中的数据会发生变化,其程序中的实现逻辑如下:


RTC 邀请接受通话:/mobile/rtcs/invite-accept ( mobile/rtc/invite-accept )

1、请求参数列表
( 1 ) user_name:必填,用户名称
( 2 ) call_mode:必填,通话方式,voice_call:语音通话;video_call:视频通话

2、输入数据验证规则
( 1 ) 必填:user_name、call_mode
( 2 ) 字符串:user_name、call_mode
( 3 ) 范围([voice_call, video_call]):call_mode
( 4 ) 判断房间是否存在,是:响应失败

3、操作数据
( 1 ) 设置RTC 邀请接受通话数据的缓存键
( 2 ) 从缓存中取回RTC 邀请接受通话数据
A、如果不存在,则序列化,将RTC 邀请接受通话数据存放到缓存供下次使用,在缓存中永久保留
B、如果存在,则反序列化,带索引检查计算数组的差集,如果差集不为空,将RTC 邀请接受通话数据存放到缓存供下次使用,在缓存中永久保留


3、带索引检查计算数组的差集,以对比数组是否相等。由于 Body 中的数据经过了严格的验证,因此,可以确保 Body 中的数据仅会小于等于缓存中的数据。代码实现如下:


        // 设置RTC 邀请接受通话数据的缓存键
        $redisCache = Yii::$app->redisCache;
        $gisRtcInviteAcceptCacheKey = implode(':', ['gis', 'rtc', 'invite', 'accept', $identity->group_id]);

        // 从缓存中取回RTC 邀请接受通话数据
        $gisRtcInviteAcceptCacheData = $redisCache[$gisRtcInviteAcceptCacheKey];

        $requestGisRtcInviteAccept = [
            'user_name' => $user_name,
            'call_mode' => $call_mode,
        ];

        if ($gisRtcInviteAcceptCacheData === false) {
            // 将RTC 邀请接受通话数据存放到缓存供下次使用,在缓存中永久保留
            $redisCache->set($gisRtcInviteAcceptCacheKey, serialize($requestGisRtcInviteAccept));
        } else {
            $gisRtcInviteAccept = unserialize($gisRtcInviteAcceptCacheData);

            // 带索引检查计算数组的差集
            $result = array_diff_assoc($gisRtcInviteAccept, $requestGisRtcInviteAccept);

            if (!empty($result)) {
                // 将RTC 邀请接受通话数据存放到缓存供下次使用,在缓存中永久保留
                $redisCache->set($gisRtcInviteAcceptCacheKey, serialize($requestGisRtcInviteAccept));
            }
        }


4、array_diff_assoc() 返回一个数组,该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 不同的是键名也用于比较。分别打印缓存中的数组、Body 中的请求数据、带索引检查计算数组的差集。符合预期。仅当 带索引检查计算数组的差集 不为空时,才重新设置覆盖缓存中的数据。


$gisRtcInviteAccept
Array
(
    [user_name] => huaqiyun
    [call_mode] => voice_call
)

{
    "user_name": "huaqiyun1",
    "call_mode": "voice_call"
}

array(1) {
  ["user_name"]=>
  string(8) "huaqiyun"
}



$gisRtcInviteAccept
Array
(
    [user_name] => huaqiyun
    [call_mode] => voice_call
)

{
    "user_name": "huaqiyun",
    "call_mode": "video_call"
}

array(1) {
  ["call_mode"]=>
  string(10) "voice_call"
}



$gisRtcInviteAccept
Array
(
    [user_name] => huaqiyun
    [call_mode] => voice_call
)

{
    "user_name": "huaqiyun2",
    "call_mode": "video_call"
}

array(2) {
  ["user_name"]=>
  string(8) "huaqiyun"
  ["call_mode"]=>
  string(10) "voice_call"
}


 ]]>
https://www.shuijingwanwq.com/2020/06/22/4268/feed/ 0