【问题标题】:How can I access attributes using camel case?如何使用驼峰式大小写访问属性?
【发布时间】:2014-10-22 22:49:14
【问题描述】:

为了在我的编码风格上保持一致,我想使用camelCase 而不是snake_case 来访问属性。在不修改核心框架的情况下,这在 Laravel 中是否可行?如果有,怎么做?

例子:

// Database column: first_name

echo $user->first_name; // Default Laravel behavior
echo $user->firstName; // Wanted behavior

【问题讨论】:

    标签: laravel eloquent naming-conventions


    【解决方案1】:

    创建您自己的BaseModel 类并覆盖以下方法。确保您的所有其他型号 extend 您的 BaseModel

    namespace App;
    
    use Illuminate\Foundation\Auth\User;
    use Illuminate\Support\Str;
    
    class BaseUser extends User
    {
        public function getAttribute($key) {
            if (array_key_exists($key, $this->relations)) {
                return parent::getAttribute($key);
            } else {
                return parent::getAttribute(Str::snake($key));
            }
        }
    
        public function setAttribute($key, $value) {
            return parent::setAttribute(Str::snake($key), $value);
        }
    }
    

    然后使用:

    // Database column: first_name
    
    echo $user->first_name; // Still works
    echo $user->firstName; // Works too!
    

    这个技巧围绕着通过覆盖Model 中使用的魔法方法来强制转换为snake case。

    【讨论】:

    • 您还必须扩展 __isset() 和 __unset() 方法。否则 isset()、empty() 和 unset() 函数将无法与驼峰式按键一起正常工作。这个bug我花了半天时间。
    • 这也可能是特质吗?
    【解决方案2】:

    只是想我会发布这个以防它帮助其他人。尽管Bouke 的条目很棒,但它并没有解决使用驼峰式名称的延迟加载关系。发生这种情况时,除了其他检查之外,我们只需要检查方法名称即可。以下是我所做的:

    class BaseModel extends Eloquent
    {
    
        public function getAttribute($key)
        {
    
            if (array_key_exists($key, $this->relations)
              || method_exists($this, $key)
            )
            {
                return parent::getAttribute($key);
            }
            else
            {
                return parent::getAttribute(snake_case($key));
            }
        }
    
        public function setAttribute($key, $value)
        {
            return parent::setAttribute(snake_case($key), $value);
        }
    }
    

    【讨论】:

      【解决方案3】:

      由于 SO 不允许在 cmets 中粘贴代码 sn-ps,因此我将其发布为新答案。

      为了确保快速加载不会中断,我不得不修改@Lazlo 的答案。当通过不同的键访问急切加载的关系时,它们会被重新加载。

      <?php
      
      class BaseModel extends Eloquent
      {
      
          public function getAttribute($key)
          {
              if (array_key_exists($key, $this->relations)) {
                  return parent::getAttribute($key);
              } else {
                  return parent::getAttribute(snake_case($key));
              }
          }
      
          public function setAttribute($key, $value)
          {
              return parent::setAttribute(snake_case($key), $value);
          }
      }
      

      【讨论】:

      • 您能解释一下您在这里解决的问题吗?我并没有真正关注您在关系数组上所做的验证?
      • 假设您运行查询User::with('likedPosts'),它将存储为$user-&gt;attributes['likedPosts']。但是,当您覆盖getAttribute 并将所有内容更改为snake_case 时,当您编写不存在的$user-&gt;likedPosts 时,它会尝试访问$user-&gt;attributes['liked_posts']。然后 laravel 将延迟加载关系,即使关系已经加载(如 likePosts)。为了防止这种情况,if 语句是必要的。
      猜你喜欢
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      相关资源
      最近更新 更多