【问题标题】:Scope And Relationship on Same Model同一模型的范围和关系
【发布时间】:2015-04-30 00:40:55
【问题描述】:

我有一个名为 payments 的表,其中包含一个名为 Vendor ZIP 的字段。

我有一个名为201502_postcodes 的表,在这种情况下我的“加入”是该表中的postcode 字段。

如何使用 Eloquent 返回 201502_postcodes 表中的字段值?

我的模特是;

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Payment extends Model {

public function postcodeExtract()
{
    return $this->belongsTo('App\Models\PostcodeExtract', 'postcode', 'Vendor ZIP');
}

_

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class PostcodeExtract extends Model {

protected $connection = 'postcodes';

public function scopeFromTable($query, $tableName) 
{
    return $query->from($tableName);
}

public function payment()
{
    return $this->hasMany('App\Models\Payment', 'Vendor ZIP', 'postcode');
}

所以,我在这个模型上有一个 scope,因为我的表名中的 201502 部分是一个变量(也就是说,每个季度都会出现一个新变量)。

在我的控制器中...我不知道该放什么。我不知道如何让范围和关系都发挥作用。如何编写一个查询,该查询将采用邮政编码/zip 并从(我是否将它们称为“方法”?)邮政编码提取表中输出其中一个字段?

这不是这个问题Laravel 4: Dynamic table names using setTable() 的重复,因为该问题没有涉及或讨论关系。

--- 更新 ---

如果我要使用getTable - 会是这样吗...

class PostcodeExtract {

  public function setTableByDate($selected_tablename)
  {
    $this->table = $selected_tablename;

    // Return $this for method chaining
    return $this;
  }

  public function getTable()
  {
    if (isset($this->table))
        $this->setTableByDate($this->table);

    return $this->table;
  }
}

然后我会在我的控制器中使用它;

$selected_tablename = 201502_postcode //created by some other controller
$postcode_extract = new PostcodeExtract;
$data = $postcode_extract->setTableByDate($selected_tablename)->get()->toArray();

Carbon 的东西并不真正相关。我有一个查找以获取这些表名,事实是带有日期值的前缀不应该意味着它被视为日期。

【问题讨论】:

标签: php laravel laravel-5


【解决方案1】:

这里发生了几件事。

scopeFromTable() 是多余的

Laravel 使用魔法方法来处理对未定义方法的调用。在模型上调用 from() 实际上会在模型内部 Query 对象上调用 from()(假设您没有在模型本身上定义名为“from”的方法)。值得一读 Model 类的 __call and __callStatic 方法。

关系使用 getTable()

Laravel 的另一个方面是约定优于配置的概念。这基本上意味着框架假设了一些事情,因此您不必定义每个细节。关于表命名约定,它自然会使用从类名派生的表名。

// Uses table 'foos'
class Foo {}

有几种方法可以改变这种行为。首先,您可以像这样定义一个“表”数据成员。

class Foo {
    protected $table = 'bars';
}

如果您需要更动态的行为,那么您可以重新定义 getTable 方法。

class Foo {
    public function getTable()
    {
        // return your special table name based on today's date
    }
}

最终模型及其关系参考getTable 以确定表名应该是什么。

您的用例

如果您只需要查询 current 表,那么我建议重新定义 getTable。

如果您需要同时查询 currentpast 表,那么我建议在重新定义 getTable 的同时搭配一个新方法

class Foo {
    public function setTableByDate(\DateTime $date)
    {
        $this->table = // generate table name from $date

        // Return $this for method chaining
        return $this;
    }

    public function getTable()
    {
        if (isset($this->table))
            $this->setTableByDate(\Carbon\Carbon::now());

        return $this->table;
    }
}

有了这个,您不必担心控制器或其他任何地方的表名,除非您需要查询过去的记录。

按每个用户的日期设置表格

$foos = Foo::setTableByDate($user->some_date)->where(...)->get();

【讨论】:

  • 日期前缀(即使用的表)由用户定义——因此它并不总是最新的日期。那么我的控制器代码应该是什么样的呢?
  • 我对 OOP 还是很陌生...但是如果我使用 getTable - 那不是吸气剂吗?我不需要像 setTable 这样的东西来更改我的表名吗?
  • 是和不是。模型和关系调用 getTable。因此,如果您在模型中重新定义 getTable,那么您会影响所有相关的数据库调用。您需要了解 OOP 中的继承
  • @ColinJames 我想我关注了.. 我在原始帖子中的更新有意义吗?
  • 经过测试,它似乎工作得很好:) 虽然我仍然没有得到让关系正常工作的答案。但是现在我使用 getTable() 应该更容易了。因此,我将暂时保持开放状态,如果找到解决方案,我会回来。
猜你喜欢
  • 2021-12-12
  • 2012-12-28
  • 2012-11-23
  • 1970-01-01
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
相关资源
最近更新 更多