【问题标题】:helper vs controller performace in laravel 5.*laravel 5.* 中的助手与控制器性能
【发布时间】:2019-09-17 07:23:09
【问题描述】:

假设我有一个名为 enginehelper

if( ! function_exists('engine') )
{
    function engine($user_id_1, $user_id_2, $league, $log = true)
    {
        /*
         * variables
         */
        $questionsLevel = 1;

        $user1 = \App\User::where('id', $user_id_1)->first();
        $user2 = \App\User::where('id', $user_id_2)->first();

        $league = \App\Models\League::where('id', $league)->first();

        $users = $league->all_users;

        /*
         * check if users joined to league correctly
         */
         $user1_ok = $user2_ok = false;
         foreach($users as $user)
         {

             if( $user->id == $user_id_1 )
             {
                 $user1_ok = true;
             }
             if( $user->id == $user_id_2)
             {
                 $user2_ok = true;
             }

             $check_users = [
                 $user1_ok,
                 $user2_ok
             ];
         }

        if( in_array(false, $check_users) )
        {
            return [
                'errcode' => 404,
                'errmessage' => 'one ro both user/s did not joined to league'
            ];
        }

       //DO SOME STUFF

    }//function engine
}

如你所知,我可以写一个controller 来做同样的事情。

有谁知道基于 Laravel 架构哪个更快?以及如何在这两种情况下测试性能?

我正在使用laravel 5.7.*

【问题讨论】:

  • 我不确定你在问什么。控制器方法将与 HTTP 请求一起使用。助手可以在代码中的任何地方使用。如果您仍然响应 HTTP 请求,则会调用相同的引导程序。
  • 两种“方法”都同样慢,因为您正在查询数据库。这增加了最多的时间,因此摆弄微优化不会让你有任何收获,这是一种浪费。

标签: php laravel laravel-5 helper php-7.1


【解决方案1】:

关于性能,我认为不会有任何变化,因为将执行相同的查询以及执行相同数量的操作,例如foreach()循环在这两种情况下都是O(n),那么会有什么不同,但是您可能希望将代码更改为如下所示的内容,或者也可以使用三元运算符。不同之处在于代码的组织。在控制器中测试会更容易。

注意:但是id 将如何同时是 $user1$user2,所以让我们用 OR 代替 AND

foreach($users as $user)
 {
     if( $user->id == $user_id_1 )
     {
         $user1_ok = true;
     }elseif( $user->id == $user_id_2)
     {
         $user2_ok = true;
     }

     $check_users = [
         $user1_ok,
         $user2_ok
    ];
}

foreach($users as $user)
{
    if( in_array($user->id, [$user_id_1, $user_id_2])
    {
        $user1_ok = true;
    }

    $check_users = [
        $user1_ok,
        $user2_ok
    ];
}

foreach($users as $user)
{
    if( $user->id == $user_id_1 )
    {
        $check_users['user1_ok'] = $user->id == $user_id_1 ? true : false;
    }
    if( $user->id == $user_id_2)
    {
        $check_users['user2_ok'] = true;
    }
}

如果您想获得user1_okuser2_ok 的工程师,您可能希望按照@Namoshek 的建议运行查询。

或者您可能想将查询更改为类似

League::query()->where('id', $league)
        ->whereHas('users', function($query) use ($user1, $user2) {
            $query->where('id', $user1)->where('id', $user2);
    })->exists();

但是,$user1 和 $user2 的 id 将如何?所以,如果它是 OR 而不是 AND。

League::query()->where('id', $league)
    ->whereHas('users', function($query) use ($user1, $user2) {
        $query->whereIn('id', [$user1, $user2]);
})->exists();

甚至$users = [$user1, $user2];

League::query()->where('id', $league)
    ->whereHas('users', function($query) use ($users) {
        $query->whereIn('id', $users);
})->exists();

顺便说一句,如果你想使用这些查询,你可以把它放在引擎模型和用户中,或者在需要时重用它。同样对于助手,它可以在控制器中不可重复使用的地方重复使用。

【讨论】:

  • 复制答案是一回事。但是将它们更改为返回错误结果的东西是另一回事。
  • @Namoshek 我认为你的代码可以用不同的方式编写,所以我提到了你的名字并改写了我的想法。
  • 我明白了,但不能。您的版本不能确保两个用户都是联盟的成员。
  • @Namoshek 如果您认为这会给出错误的结果,请指出,以便对我和其他人都有帮助。
  • @Namoshek 你是对的,就像 orWhere() 一样,你是对的。
【解决方案2】:

最快的解决方案是不加载不必要的数据:

if(! function_exists('engine'))
{
    function engine(int $user1, int $user2, int $league)
    {
        return League::query()
            ->where('id', $league)
            ->whereHas('users', function($query) use ($user1) {
                $query->where('id', $user1);
            })
            ->whereHas('users', function($query) use ($user2) {
                $query->where('id', $user2);
            })
            ->exists();
    }
}

一般来说,我不认为这样的函数应该返回复杂的结果,比如错误消息。对于这个特定的工作,您应该使用控制器操作。在我看来,辅助方法应该只返回truefalse。不过,您也可以将相同的逻辑放在服务类中(可能是最好的解决方案)。

【讨论】:

  • 我觉得你应该把use ($user)改成use ($user1)
  • 顺便问一下id 将如何同时成为$user1$user2
  • 有趣的是,您的代码现在超级快,因为它总是会返回 false ?
猜你喜欢
  • 2018-07-03
  • 2020-07-03
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 2017-05-25
  • 1970-01-01
  • 2023-03-02
  • 1970-01-01
相关资源
最近更新 更多