【问题标题】:PHP - refactoring this if statement to avoid duplicationPHP - 重构此 if 语句以避免重复
【发布时间】:2013-10-23 15:05:49
【问题描述】:

在这段代码的 sn-p 中,我们键入 $inputs['user_id'] 3 次。

if (isset($inputs['user_id']) && $inputs['user_id']) { // The consumer is passing a user_id
    doSomethingWith($inputs['user_id']);
}

为了避免重复并避免注意到索引 user_id 不存在,我可以做的最易读和最健壮的重构是什么?

谢谢。

【问题讨论】:

    标签: php if-statement code-duplication


    【解决方案1】:

    这里的重复没有任何问题。在检查变量是否已设置之前,不能将 $inputs['user_id'] 分配给变量,否则会产生 Notice undefined index ...

    这里唯一可以做的就是省略isset 调用并改用!empty,如下所示:

    if(!empty($inputs['user_id'])) {
        doSomething($inputs['user_id']);
    }
    

    现在您只需输入两次并检查

    !empty($inputs['user_id'])
    

    等于

    isset($inputs['user_id']) && $inputs['user_id']
    

    编辑: 基于一个 cmets,这里引用 documentation:

    以下的东西被认为是空的:

    "" (an empty string)
    0 (0 as an integer)
    0.0 (0 as a float)
    "0" (0 as a string)
    NULL
    FALSE
    array() (an empty array)
    $var; (a variable declared, but without a value)
    

    所以empty(0)empty('0') 将返回true,这意味着

    if(!empty('0') || !empty(0)) { echo "SCREW YOU!"; }
    

    什么都不回应...或者,以礼貌的方式,我将重复上面的陈述:

    !empty($inputs['user_id']) === (isset($inputs['user_id']) && $inputs['user_id'])
    

    编辑 2:

    通过省略isset 并用!empty 替换变量仍然检查,索引是否已设置,请阅读documentation,其中说:

    如果变量不存在,则不会生成警告。这意味着 empty() 本质上是与 !isset($var) || 的简明等效。 $var == false.

    【讨论】:

    • empty('0') = true,应该知道这一事实。
    【解决方案2】:

    这个呢:

    // put validation check to the function body
    function doSomethingWith($userId) {
         if($userId === -1) {
             // if this is not a valid user id -> return
             return;
         }
         // do something ...
    }
    
    // initalize $user with proper default values.
    // doing so you can be sure that the index exists
    $user = array(
        'id' => -1,
        'name' => '',
        ...
    );
    
    // merge inputs with default values:
    $user = array_merge($user, $request);
    
    // now you can just pass the value:
    doSomethingWith($user['id']);
    

    【讨论】:

    • @AmalMurali 你说的重构是什么意思?
    • 这与我要建议的类似;如果存在doSomethingWith 无法接受的“默认”无效有效值(我通常会选择null,而不是-1-1 通常最终会是error,因为它是ID 的正确数据类型),在开头有一个保护语句,所以它会提前返回。
    • @hek2mgl - 您可能需要在参数 doSomethingWith(&$userId) 之前添加 & 以防变量未定义,因此 php 不会抱怨
    • @i-- 你能解释一下吗?
    • @hek2mgl - 我不完全确定为什么在函数声明中通过引用而不是值传递没有警告,我只知道它有效。很想知道自己到底为什么。在这种情况下猜测与变量自动分配有关。
    【解决方案3】:

    下面可能不是所有情况的最佳方法,但肯定会减少重复。

    您的示例代码将变成:

    doSomethingWith($inputs['user_id']);
    

    你的函数看起来像这样(注意通过引用提供的参数,以避免未定义的变量警告)

    function doSomethingWith(&$userID) {
       if (empty($userID)) return;
       // ... actual code here ...
    }
    

    【讨论】:

    • 在 PHP 中通过引用传递有很多(有时是意想不到的)副作用,应该小心处理。这就是为什么我不建议将此作为一般解决方案。但是,它在这种情况下有效,黑客 +1!但我不会在生产代码中使用它...
    • 谢谢。同意这种护理,但如果人们知道他/她在做什么,它也会赋予语言另一种权力。
    • 这个真的不错(解决这个问题)! :) 当我说解决这个问题时,我的意思是不仅在处理字符串或数字时可能会出现意外的副作用(尤其是性能问题)。但正如你所说,如果小心处理应该没问题。
    【解决方案4】:

    假设0""null 不是有效的user_ids:

    if ($id = $inputs['user_id']) { 
        doer($id);
    }
    

    你也可以用 evil @ 来避免在你的日志中被注意到,(我不喜欢这种方式):

    if ($id = @$inputs['user_id']) { 
        doer($id);
    }
    

    【讨论】:

    • 这也假定索引 user_id 始终设置 - 我从原始问题中的 isset 假设情况可能并非如此。
    • 没有。我假设一个空的 var 不会通过检查,而有效的会通过。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 2016-06-12
    相关资源
    最近更新 更多