Laravel - 在哪里存储通用模型函数以及如何从控制器访问它们?

Laravel - where to store common model functions & how to access them from controllers?

我的 大多数 模型
使用了一些函数 因此将它们集中存储而不是重复代码是有意义的。

例如,我有一个函数可以从我需要的 table 中找到一个随机行:

function getRandomRow() {
    $rowCount = DB::connection('mydatabasename')
                ->table('my_table_name')
                ->selectRaw("FLOOR(RAND() * COUNT(*)) AS offset")
                ->first();

    $offset = $rowCount->offset;

    $randomRow = DB::connection('mydatabasename')
                    ->table('my_table_name')
                    ->select()
                    ->offset($offset)
                    ->limit(1)
                    ->first();

    return $randomRow;
}

我看过 inheritance (extends) and - as well as the docs on polymorphic relations - 但不清楚哪个最有效以及如何在通用函数中访问 table 名称(与正在使用的模型相关联)。

我的问题:
- 我应该把这个功能放在哪里,以便它可以被所有模型使用?
- 如何编写代码以便 'my_table_name' 使用正确的模型 table?

我找到的最简单的解决方案是创建一个 parent 模型/class - 如 中针对不同问题所述 - 对于当前示例,我们称之为 BaseModel.

对于 Laravel 这与其他模型一起存储,直接在 App 目录中

...在我的例子中,parent 模型/class 可以是 abstract,因为它不需要拥有自己的 table(也意味着BaseModel 函数只能通过 child 模型访问):

namespace App;

use Illuminate\Database\Eloquent\Model;

abstract class BaseModel extends Model
{
    // ...put common model functions here
}

实现此功能的技巧(BaseModel 函数需要访问 child 模型的 table)是:
- 有每个 child 模型 / class extend BaseModel class
- 确保 $table 在所有 child 模型中定义 - 如前所述 :

class MyFunkyModel extends BaseModel
{
    protected $table = 'funktown';

    // ...put child specific functions here

}

表示$this->table可以在BaseModel摘要中使用parentclass引用child模型的指定$table / class:

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

abstract class BaseModel extends Model
{
    function getRandomRow() {
        $rowCount = DB::connection('mydatabasename')
                        ->table($this->table)
                        ->selectRaw("FLOOR(RAND() * COUNT(*)) AS offset")
                        ->first();

        $offset = $rowCount->offset;

        $profileRow = DB::connection('mydatabasename')
                        ->table($this->table)
                        ->select()
                        ->offset($offset)
                        ->limit(1)
                        ->first();

        return $profileRow;
    }
}

现在,您可以从控制器访问存储在 BaseModel 中的任何功能,只需通过 child 模型:

namespace App\Http\Controllers;

use App\MyFunkyModel;
use App\MySeriousModel;
use App\MyHappyModel;

class MyController extends Controller
{
    public function getRandomName($type){
        switch ($type) {
            case 'funky':
                $modelFunky = new MyFunkyModel;
                $funkyRow = $modelFunky->getRandomRow();
                $randomName = $funkyRow->funky_name_column;
                break;
            case 'serious':
                $modelSerious = new MySeriousModel;
                $seriousRow = $modelSerious->getRandomRow();
                $randomName = $seriousRow->serious_name_column;
                break;
            case 'happy':
                $modelHappy = new MyHappyModel;
                $happyRow = $modelHappy->getRandomRow();
                $randomName = $happyRow->happy_name_column;
                break;
        return $randomName;
    }
}

您可以同时使用 inheritancetrait。但强烈建议使用 Eloquent 模型而不是 DB::table()。原因是如果 table 名称以某种方式被更改,您必须在所有地方更改它。使用 Eloquent,您只需在模型中提及一次 table 名称。

protected $table = 'new_table_name'

使用继承

按如下方式构建您的 BaseModelclass

class BaseModel extends Model {
    public static function getRandomRow()
    {
        $rowCount = self::selectRaw("FLOOR(RAND() * COUNT(*)) AS offset")
            ->first();

        $offset = $rowCount->offset;

        $randomRow = self::select()
            ->offset($offset)
            ->limit(1)
            ->first();

        return $randomRow;
    }
}

class YourModel extends BaseModel {
    // getRandomRow() available here
}

使用特征

按如下方式构建您的 traitclass

trait BaseTrait {
    public static function getRandomRow()
    {
        $rowCount = self::selectRaw("FLOOR(RAND() * COUNT(*)) AS offset")
            ->first();

        $offset = $rowCount->offset;

        $randomRow = self::select()
            ->offset($offset)
            ->limit(1)
            ->first();

        return $randomRow;
    }
}

class YourClass {
    use BaseTrait;
    // getRandomRow() available here
}

无论哪种方式,您都可以像

一样访问您的方法
class yourController {
    public function youMethod()
    {
        $rows = YourModel::getRandomRow();
    }
}