【问题标题】:Extended User Model in a Package包中的扩展用户模型
【发布时间】:2019-03-17 10:11:14
【问题描述】:

您能否帮助我了解扩展现有模型的正确方法?我正在开发一个包,并希望尽可能多地与主应用程序分开。

我想拥有User 模型的所有现有功能,但只添加与另一个模型的关系。在我的包裹User 我可以有几个(hasManyArticle。我没有向\App\User 添加方法,而是在我的包class User extends \App\User 中创建了一个新模型:

namespace Package\Sample;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;

/**
 * Class User
 * @package Package\Sample
 */
class User extends \App\User
{
    use HasApiTokens, Notifiable;

    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}

为了让它工作,我为我的包auth.php添加了配置:

'providers' => [
        'users' => [
        'driver' => 'eloquent',
        'model'  => \Package\Sample\User::class,
    ],
],
'guards' => [
        'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

我的问题:扩展现有模型的功能是否是“最佳实践”?

【问题讨论】:

  • 看看 spatie 是怎么做的:他们不接触用户模型,他们要求用户使用特征。 github.com/spatie/laravel-permission/tree/master/src/Traits
  • @Kyslik 不错!一个很好的例子。谢谢!在 [文档|github.com/spatie/laravel-permission#usage] 中,假设将特征 Spatie\Permission\Traits\HasRoles 添加到 User 模型中,这是我想要避免的。我想以编程方式执行此操作,并且在安装包时不需要它。我不知道这是否可能,这就是我要求最佳实践的原因。也许在安装过程中要求添加一个特征是一个最佳实践:)

标签: laravel laravel-5.7 package-development


【解决方案1】:

我尝试使用 class_alias,虽然它适用于基本用法,但当事情变得更复杂时,我的用户类无法削减它。例如,我的通知使用本地包用户类型而不显示在应用程序中。

在进行更多研究后,我发现使用特质是正确的方式,就像其他人提到的那样。

我在这里找到了一份综合指南:https://laravelpackage.com/08-models-and-migrations.html#approach-2-using-a-polymorphic-relationship

要点:

在你的包中创建一个特征:

重要的是,您可以根据您的数据库建模设置您需要的任何关系。

 // 'src/Traits/HasPosts.php'
<?php

namespace JohnDoe\BlogPackage\Traits;

use JohnDoe\BlogPackage\Models\Post;

trait HasPosts
{
  public function posts()
  {
    return $this->morphMany(Post::class, 'author');
  }
}

在应用中适用的任何用户类中添加使用

 // 'App\Models\User.php'
<?php

namespace App\Models;

use JohnDoe\BlogPackage\Traits\HasPosts;

class User extends Authenticatable
{
   use HasPosts;
   ...

最后,您需要在数据库中为您使用 user_id 的 user_type 添加一个额外字段。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddUserTypeToPostTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->tinyText('user_type')
                ->comment('User class type')
                ->nullable();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->dropColumn('user_type');
        });
    }
}

【讨论】:

    【解决方案2】:

    我通过使用class_alias() php 函数解决了它。

    在我的包服务提供者中,我设置了在/config/auth.php 中为身份验证定义的模型类的别名,如下所示:

    public function boot(){   
    
           class_alias(config("auth.providers.users.model"), 'ParentModel');
    
    }
    

    然后我在需要的地方使用ParentModel 类:

    use ParentModel;
    
    class Agent extends ParentModel {
    ...
    
    }
    

    希望对某人有意义

    【讨论】:

      【解决方案3】:

      您需要将config(['auth.providers.users.model' =&gt; Myname\Myproject\App\Models\User::class]); 添加到我的package-service-provider 中的引导方法中。

      并在您的包中创建新类。

      namespace Myname\Myproject\App\Models;
      
      class User extends \App\User
      {
      
          public function roles(){
              return $this->belongsToMany('Myname\Myproject\App\Models\Role', 'user_role', 'user_id', 'role_id');
          }
      }
      

      【讨论】:

        【解决方案4】:

        这将阻止对\Package\Sample\User::class 的编辑。任何需要的新方法都会导致包更新。

        为什么不在你的包中声明一个包含你的方法的 trait 并在 App\User::class 中使用它们,就像 laravel 正在使用的一样。

        namespace App;
        
        use Illuminate\Notifications\Notifiable;
        use Illuminate\Foundation\Auth\User as Authenticatable;
        
        class User extends Authenticatable
        {
            use Notifiable;
        

        【讨论】:

        • 没错,我必须在任何地方使用\Package\Sample\User 模型并在其他包中扩展它。我不明白的是 - 如何让我的包尽可能独立而不改变主应用程序代码。
        • 如答案中所述,使用Traits。以Illuminate\Notifications\Notifiable 为例
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-12
        • 2011-02-28
        • 2013-12-06
        • 2018-01-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多