如何使用 laravel 关系在 laravel 中的 3 个表之间建立关系?

How to make relation between 3 tables in laravel using laravel relation?

我有三个table:

SET NAMES utf8;
SET time_zone = '+00:00';

DROP TABLE IF EXISTS `api_credentials`;
CREATE TABLE `api_credentials` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `user_id` bigint(20) unsigned NOT NULL,
    `api_provider_id` bigint(20) unsigned NOT NULL,
    `access` text COLLATE utf8_unicode_ci,
    `created_at` timestamp NULL DEFAULT NULL,
    `updated_at` timestamp NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `api_credentials_user_id_foreign` (`user_id`),
    KEY `api_credentials_api_provider_id_index` (`api_provider_id`),
    CONSTRAINT `api_credentials_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
    CONSTRAINT `api_credentials_api_provider_id_foreign` FOREIGN KEY (`api_provider_id`) REFERENCES `api_providers` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

DROP TABLE IF EXISTS `api_providers`;
CREATE TABLE `api_providers` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `name` char(255) COLLATE utf8_unicode_ci NOT NULL,
    `table_prefix` char(255) COLLATE utf8_unicode_ci NOT NULL,
    `created_at` timestamp NULL DEFAULT NULL,
    `updated_at` timestamp NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `email_verified_at` timestamp NULL DEFAULT NULL,
    `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
    `created_at` timestamp NULL DEFAULT NULL,
    `updated_at` timestamp NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

-- 2019-12-05 13:38:06

这是我的模型: 1.ApiCredential

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;

class ApiCredential extends Pivot
{

}
  1. Api 提供者
<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class ApiProvider extends Model
{
    protected $fillable = [
        'name',
        'table_prefix'
    ];

    public function users()
    {
        return $this->belongsToMany('App\Models\User')->using('App\Models\ApiCredential');
    }
}
  1. 用户模型
namespace App\Models;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

use App\Models\ApiProvider;
use App\Models\ApiCredential;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
    */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    public function apiProvider()
    {  
        return $this->belongsToMany('App\Models\ApiProvider','api_providers','user_id','api_provider_id');
    } 

    public function hasCredentials(String $apiProvider)
    {
        return $this->apiProvider()->where('name', $apiProvider)->get();
    } 
}

现在我想要什么: 我想根据 userapi_providerapi_credentials table 获取记录。假设我在 api_providers 中有三个记录(名称是 adscane、cpalead、offertorro)。

我运行这个函数得到cpalead的api_credential。

User::find(1)->hasCredentials('cpalead');

但它没有给出预期的结果。

谁能帮我解决这个问题。

我相信

# User model
public function apiProvider()
{  
    return $this->belongsToMany('App\Models\ApiProvider','api_providers','user_id','api_provider_id');
}

应该是

# User model
public function apiProvider()
{  
    return $this->belongsToMany('App\Models\ApiProvider','api_credentials','user_id','api_provider_id');
}

编辑 访问 api_credentials:

  1. 使用 hasMany 关系
# User model
public function apiCredentials()
{
    return $this->hasMany('App\Models\ApiCredential')
}
# ApiProvider model
public function apiCredentials()
{
    return $this->hasMany('App\Models\ApiCredential');
}
# ApiCredential model
public function user()
{
    return $this->belongsTo('App\Models\User');
}

public function apiProvider()
{
    return $this->belongsTo('App\Models\ApiProvider');
}

然后,我们重新定义 hasCredentials() 函数,使其工作如下:

# User model
public function hasCredentials(String $apiProvider)
{
    $this->apiCredentials()->whereHas('apiProvider', function ($query) use ($apiProvider) {
         $query->where('name', '=', $apiProvider);
    })
    ->get();
}

使用数据如下所示:

$user = User::find($id);

foreach($user->hasCredentials('api_provider_name') as $apiCredential)
{
    // $apiCredential->name
    // $apiCredential->table_prefix
}

这样使用

namespace App\Model;


use Illuminate\Database\Eloquent\Model;

class ApiCredential extends Model
{

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function apiProvider()
    {
        return $this->belongsTo(ApiProvider::class);
    }
}

namespace App\Model;


use Illuminate\Database\Eloquent\Model;

class ApiProvider extends Model
{

    public function ApiCredentials()
    {
        return $this->hasMany(ApiCredential::class);
    }

}

namespace App\Model;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
use Spatie\Activitylog\Traits\LogsActivity;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    public function ApiCredentials()
    {
        return $this->hasMany(ApiCredential::class);
    }

}

现在这样查询

    User::with('apiCredentials.apiProvider',)
        ->where('id',1)
        ->whereHas('apiCredentials.apiProvider', function ($query)  {
        $query->where('name','cpalead' );
    })->get();