Laravel 基于相关模型的 Lighthouse GraphQL 验证
Laravel Lighthouse GraphQL validation based on related model
使用 Laravel Lighthouse GraphQL,我想验证一个模型中的值,以便它始终与相关模型中的值匹配。
在这种情况下,Program
有一个 year_id
,Category
也有一个 year_id
。我想验证 Program
和 Category
使用相同的 year_id
.
GraphQL 架构如下所示:
input CreateCategory {
year_id: ID!
name: String!
}
input CreateProgram {
year_id: ID!
name: String!
category: CreateCategoryRelation
}
input CreateCategoryRelation {
connect: ID
}
现在,如果我用 year_id: 1
创建一个 Category
(return 类别 id=1):
mutation {
createCategory(input:{
year_id: 1
name: "category in year 1"
}) {
name
id
}
}
然后尝试创建一个 Program
与 year_id: 2
相关的新 Category
mutation {
createProgram(input:{
year_id: 2
name: "Program in year 2"
category: {
connect: 1
}
}) {
id
name
}
}
我希望验证失败并显示类似 "You cannot create a Program in a different year as it's Category!"
的消息
到目前为止,我找不到基于另一个模型中的任何值进行验证的方法。
我该怎么做?
您可以使用 https://lighthouse-php.com/4.7/security/validation.html#validate-fields
进行自己的验证
感谢 Enzo Notario 的回答,我找到了解决方案。
如果其他人想了解更多关于如何可以(我相信这可以做得更漂亮)的详细信息,请编写您自己的验证,这是我的代码:
type Mutation {
createProgram(input: CreateProgram! @spread): Program! @create @yearValidation
}
文件App/GraphQL/Directives/YearValidationDirective.php:
<?php
namespace App\GraphQL\Directives;
use App\Rules\SameYear;
use Illuminate\Support\Facades\DB;
use Nuwave\Lighthouse\Schema\Directives\ValidationDirective;
class YearValidationDirective extends ValidationDirective
{
/**
* List of all relations that should be checked for having the same year
*/
private $relations = [
'category' => true
];
/**
* Name of the directive.
*
* @return string
*/
public function name(): string
{
return 'yearValidation';
}
/**
* @return mixed[]
*/
public function rules(): array
{
if (isset($this->args['year_id'])) {
// year_id is given, get it
$year_id = $this->args['year_id'];
} else {
// year_id not given, get it from the model
$id = $this->args['id'];
$fieldName = $this->resolveInfo->fieldName; // "updateTableName"
$tableName = substr($fieldName, 6);
$year_id= DB::table($tableName)->findOrFail($id)->year_id;
}
$relationFields = [];
foreach($this->args as $field => $arg) {
if (is_array($arg) && isset($this->relations[$field])) {
$relationFields[$field] = [new SameYear($year_id)];
}
}
return $relationFields;
}
}
文件App/Rules/SameYear.php:
<?php
namespace App\Rules;
use Illuminate\Support\Facades\DB;
use Illuminate\Contracts\Validation\Rule;
class SameYear implements Rule
{
protected $year_id;
protected $found_year_id;
protected $tableName;
protected $connect;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct($year_id)
{
$this->year_id = $year_id;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$this->connect = $value['connect'];
$this->tableName = ucfirst($attribute);
$this->found_year_id = DB::table($this->tableName)->find($this->connect)->year_id;
return intval($this->found_year_id) === intval($this->year_id);
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return "Year_id's must be the same! $this->tableName (id: $this->connect) must have year_id: $this->year_id (found: $this->found_year_id)";
}
}
这适合我。
使用 Laravel Lighthouse GraphQL,我想验证一个模型中的值,以便它始终与相关模型中的值匹配。
在这种情况下,Program
有一个 year_id
,Category
也有一个 year_id
。我想验证 Program
和 Category
使用相同的 year_id
.
GraphQL 架构如下所示:
input CreateCategory {
year_id: ID!
name: String!
}
input CreateProgram {
year_id: ID!
name: String!
category: CreateCategoryRelation
}
input CreateCategoryRelation {
connect: ID
}
现在,如果我用 year_id: 1
创建一个 Category
(return 类别 id=1):
mutation {
createCategory(input:{
year_id: 1
name: "category in year 1"
}) {
name
id
}
}
然后尝试创建一个 Program
与 year_id: 2
相关的新 Category
mutation {
createProgram(input:{
year_id: 2
name: "Program in year 2"
category: {
connect: 1
}
}) {
id
name
}
}
我希望验证失败并显示类似 "You cannot create a Program in a different year as it's Category!"
的消息到目前为止,我找不到基于另一个模型中的任何值进行验证的方法。 我该怎么做?
您可以使用 https://lighthouse-php.com/4.7/security/validation.html#validate-fields
进行自己的验证感谢 Enzo Notario 的回答,我找到了解决方案。 如果其他人想了解更多关于如何可以(我相信这可以做得更漂亮)的详细信息,请编写您自己的验证,这是我的代码:
type Mutation {
createProgram(input: CreateProgram! @spread): Program! @create @yearValidation
}
文件App/GraphQL/Directives/YearValidationDirective.php:
<?php
namespace App\GraphQL\Directives;
use App\Rules\SameYear;
use Illuminate\Support\Facades\DB;
use Nuwave\Lighthouse\Schema\Directives\ValidationDirective;
class YearValidationDirective extends ValidationDirective
{
/**
* List of all relations that should be checked for having the same year
*/
private $relations = [
'category' => true
];
/**
* Name of the directive.
*
* @return string
*/
public function name(): string
{
return 'yearValidation';
}
/**
* @return mixed[]
*/
public function rules(): array
{
if (isset($this->args['year_id'])) {
// year_id is given, get it
$year_id = $this->args['year_id'];
} else {
// year_id not given, get it from the model
$id = $this->args['id'];
$fieldName = $this->resolveInfo->fieldName; // "updateTableName"
$tableName = substr($fieldName, 6);
$year_id= DB::table($tableName)->findOrFail($id)->year_id;
}
$relationFields = [];
foreach($this->args as $field => $arg) {
if (is_array($arg) && isset($this->relations[$field])) {
$relationFields[$field] = [new SameYear($year_id)];
}
}
return $relationFields;
}
}
文件App/Rules/SameYear.php:
<?php
namespace App\Rules;
use Illuminate\Support\Facades\DB;
use Illuminate\Contracts\Validation\Rule;
class SameYear implements Rule
{
protected $year_id;
protected $found_year_id;
protected $tableName;
protected $connect;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct($year_id)
{
$this->year_id = $year_id;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$this->connect = $value['connect'];
$this->tableName = ucfirst($attribute);
$this->found_year_id = DB::table($this->tableName)->find($this->connect)->year_id;
return intval($this->found_year_id) === intval($this->year_id);
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return "Year_id's must be the same! $this->tableName (id: $this->connect) must have year_id: $this->year_id (found: $this->found_year_id)";
}
}
这适合我。