分离验证数据的最佳方法

时间:2019-06-12 13:58:19

标签: php laravel

我的代码确实没有问题,更像是代码结构方面的问题。

我的项目是用Laravel编写的,我使用laravel为我们生成的资源控制器。在我的Update()函数中,我进行了大量数据处理。

一些例子:

Update()

public function update(Request $request)
{

    $post = (object) $request->all();

    unset($post->XDEBUG_SESSION_START);

    $this->preparePassword($post);

    $this->prepareMail($post);

    $this->prepareAvailability($post);

    $this->prepareZip($post);

    $this->prepareSofttags($post);

    $user = User::find(Auth::id());

    $user->update((array) $post);
}

更新调用功能可处理数据。一些例子:

private function prepareAvailability(stdClass &$data) : void
{
    // If no days or a date is selected, return
    if (empty($data->available_days) && empty($data->available_from)) {
        return;
    }

    // when days are given (available)
    if ($data->available_days) {
        $days = (int) $data->available_days;
        $avail_level = 0.2 * $days;

        $data->avail_level = $avail_level;
        $data->avail_from = mysqldate(strtotime('today'), true);

        unset($data->available_days);
    }

    // When a date is given (no available)
    if ($data->available_from) {
        $data->avail_level = 0;
        $data->avail_from = mysqldate(strtotime($data->available_from), true);

        unset($data->available_from);
    }
}

和:

private function prepareZip(stdClass &$data) : void
{
    if (empty($data->zip)) {
        return;
    }

    $zip4d = (int) substr($data->zip, 0, 4);
    $zipData = Zip::check($zip4d);
    $data->city = $zipData->name;
}

我向您展示了2个功能,甚至还有更多,而且还会更多。现在,我的控制器中充满了私有功能,这些私有功能可以通过多种方式处理数据。

有没有更好的方法,我在考虑特质,但特质应该与每个班级兼容。不特定于一个控制器。

对这个人有任何想法吗?

P.S。如果您不了解“ mysqldate”之类的代码中使用的某些功能,我会使用一些辅助功能。

2 个答案:

答案 0 :(得分:1)

据我所知,您的控制器负有很多责任,这通常意味着是拆分这些内容的好时机。我认为以下内容可以提取到其他类中:

  1. 输入验证(检查数据是否存在)。例如available_days是必填字段。为此,可以使用laravel form request validation
  2. 数据验证(检查数据是否正确)。例如,邮政编码应分为数字和字母。为此,您可以为邮政编码example
  3. 引入值对象
  4. 域验证(包含您所遇到问题的规则),例如,如果未给出available_from日期,则available_from将是今天。这些通常是确保它们不会处于无效状态的类(意味着在构造它们之后总是完整的并且数据有意义)。它们是通过在构造函数中以及其他修改其所包含数据的方法中强制执行域规则来实现的。

作为奖励,当像这样分担责任时,通常意味着(单元)测试会变得更容易。

如果您想了解更多,请告诉我。现在,我只写了一篇简短的文章。

答案 1 :(得分:1)

有了建议,我开始使用Laravel FormRequest类/方法/概念

https://laravel.com/docs/5.8/validation#form-request-validation

我清理了代码,更新功能现在变成了“一个班轮”,如您所见,以前是一团糟。结果:

public function update(UpdateUserRequest $request)
{
    user()->update($request->all());
    // user() helper function short for Auth::user()
}

很少解释。我的$ request不是Request类,而是UpdateUserRequest类:

update(UpdateUserRequest $request)

'php artisan make:request UpdateUserRequest'

此类具有一个名为

的函数。
public function withValidator($validator)

此功能在发出请求时触发,因此在进入控制器逻辑之前,我在此类中验证数据并像以前一样重新分配$ request值。

最终结果:

public function withValidator()
{
    $post = (object) $this->all();
    // Update password if possible
    $this->preparePassword($post);
    // Update mail
    $this->prepareMail($post);
    // Update availability
    $this->prepareAvailability($post);
    //
    $this->prepareZip($post);
    //
    $this->prepareSofttags($post);

    $this->merge((array) $post);
}

所有调用的函数都是此类内的私有函数。所以我将私有功能从控制器移到了这里,以便控制器再次干净。

我将在此代码库中进行更多更改,因为现在我将所有请求数据插入每个私有函数中,但最好只插入要检查的数据并更改$ request($ this (在这种情况下)直接在验证之后。所以我最后没有合并它。

P.S。我的英语不太好,所以如果我有错别字或不明白自己在说什么,请询问我。

P.S.S 如果您发现我可以改善的地方,请不要后退并告诉我:)

谢谢大家的建议!