2016-06-23 34 views
2

所以我一直在一个项目上工作了几个星期,并且刚刚拿起Laravel,因为它(迄今为止绝对是一个粉丝!)尽管我今天遇到了一些问题:雄辩的查找表格和模型创建

我有一个应用程序需要根据我们用户提供的凭据向不同的API发出请求。所有这些任务都是为了提供相同的服务,但以不同的方式让我觉得应该有一个很好的面向对象的方法。我提出了一些使用策略模式和工厂模式的想法,但在Eloquent的简单布局旁边,它们看起来不起眼。作为我所谈论的更好的例子,我有可以提供用户名,电子邮件或电话号码(取决于他们选择的API的要求)的用户。我做了4桌,到目前为止,看起来是这样的:

users: id, username, passhash

api_list: id, api_name, api_table_name, logo_url

user_api_lookup: id, user_id, api_list_id

api1_table: id, user_api_lookup_id, email

这是否看起来正确的设置做什么我试?

更新: 我可能已经提到我的应用程序是什么样子,以及

每个用户都有许多API集成和

class User 
{ 
... 
    public function rewardMethods() 
    { 
     return $this->hasMany(APIIntegration::class); 
    } 
... 
} 

希望这澄清了这些用雄辩的关系助手访问bit

+0

因此,一个API将需要其中的一个:*用户名,电子邮件或电话号码*?或者它可能需要多于一个?这个'api1_table'是用于一个api,下一个api是否有它自己的数据库表? –

+0

到目前为止,我们只处理那些需要其中一个的API。 是的,这就是我正在考虑的'apiN_table's –

+0

这不是一个好的方法,imho,当使用像mysql这样的关系数据库。 –

回答

1

请先阅读。

这个例子假设下面的语句:

  • 的API可以有多个凭证。
  • 用户可以有多个API。

但这并不意味着您将无法支持一对一关系。

我创建了一个很好的方法的简单示例,它可以支持N个API并避免为每个API分别创建一个数据库表。

这里是数据库表。

apis表格将等于您的api_list,它将保存有关API的信息。在我的示例中(正如我所说的那样非常简单),我只添加了一列name

CREATE TABLE `apis` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

我做了一个简单的users表只是这个例子:

CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `email` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

然后我做了一个新的表名为credentials将举行所有凭据类型的API可以有。例如:用户名称电子邮件电话号码name列将保存人性化的凭证名称。

CREATE TABLE `credentials` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

我去将覆盖apis不止一个要求credential有办法。这就是为什么我需要在apiscredentials之间的数据透视表。

CREATE TABLE `api_credential` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `api_id` int(11) NOT NULL, 
    `credential_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

下一页表我需要的是一种保持其api一个user有一个表。这相当于您的user_api_lookup表格。

CREATE TABLE `api_user` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `api_id` int(11) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

而且最后一个表是什么将持有的实际凭据api_credential_user

CREATE TABLE `api_credential_user` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `api_credential_id` int(11) NOT NULL, 
    `value` text NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

然后,我们将需要生成(至少我的用户artisan这个)我们的模型,并设置它们之间的关系。

php artisan make:model Api 
php artisan make:model ApiCredential 
php artisan make:model ApiCredentialUser 
php artisan make:model ApiUser 
php artisan make:model Credential 

User模型附带Laravel的安装。

Api模型看起来是这样的: (我添加了注释上的每个关系

class Api extends Model 
{ 
    protected $table = 'apis'; 

    /** 
    * As I said an API might have multiple credential types/fields. 
    */ 
    public function credentials() 
    { 
     return $this->belongsToMany('App\Credential'); 
    } 

    /** 
    * This will return all users that have a specific api attached. 
    */ 
    public function users() 
    { 
     return $this->belongsToMany('App\User'); 
    } 
} 

Credential型号:

class Credential extends Model 
{ 
    protected $table = 'credentials'; 

    /** 
    * Get all apis this credential belongs to. 
    */ 
    public function apis() 
    { 
     return $this->belongsToMany('App\Api'); 
    } 

    public function apiCredential() { 
     return $this->hasOne('App\ApiCredential'); 
    } 
} 

ApiCredential型号:

class ApiCredential extends Model 
{ 
    protected $table = 'api_credential'; 

    /** 
    * Those are defined in the sake of consistency. 
    * Probably will not be used. 
    */ 
    public function api() 
    { 
     return $this->belongsTo('App\Api'); 
    } 

    /** 
    * Those are defined in the sake of consistency. 
    * Probably will not be used. 
    */ 
    public function credential() 
    { 
     return $this->belongsTo('App\Credential'); 
    } 

    public function user() 
    { 
     return $this->hasOne('App\ApiCredentialUser'); 
    } 
} 

ApiCredentialUser型号:

class ApiCredentialUser extends Model 
{ 
    protected $table = 'api_credential_user'; 
} 

User型号:用于演示目的

class User extends Model 
{ 
    protected $table = 'users'; 

    public function apis() 
    { 
     return $this->belongsToMany('App\Api'); 
    } 
} 

虚拟数据:

INSERT INTO `users` (`id`, `email`) VALUES (NULL, '[email protected]'), (NULL, '[email protected]'); 
INSERT INTO `credentials` (`id`, `name`) VALUES (NULL, 'phone_number'), (NULL, 'username'), (NULL, 'email'); 
INSERT INTO `apis` (`id`, `name`) VALUES (NULL, 'Github API'), (NULL, 'StackOverflow API'), (NULL, 'Twitter API'), (NULL, 'Facebook API'), (NULL, 'LinkedIn API'); 
INSERT INTO `api_credential` (`id`, `api_id`, `credential_id`) VALUES (NULL, '1', '1'), (NULL, '2', '2'),(NULL, '3', '3'), (NULL, '4', '1'),(NULL, '5', '2'); 
INSERT INTO `api_user` (`id`, `api_id`, `user_id`) VALUES (NULL, '1', '1'), (NULL, '2', '2'); 
INSERT INTO `api_credential_user` (`id`, `api_credential_id`, `value`) VALUES (NULL, '1', '0700-1111-2222'), (NULL, '2', 'myUsername'); 

这些关系的用法示例:

Route::get('/test', function() { 
    //Fetching all users (dummy data) 
    $user_1 = App\User::find(1); 
    $user_2 = App\User::find(2); 

    //To list every user's apis 
    echo '<h3>User: ' . $user_1->email . '</h3>'; 
    echo 'Apis attached: <br />'; 
    echo '<ul>'; 
    foreach ($user_1->apis as $api) { 
     echo '<li>' . $api->name . '</li>'; 
     //You can get required credentials per api. 
     echo '<ul>'; 
     foreach ($api->credentials as $credential) { 
      //And for every credential you can get user's value. 
      echo '<li><b>Name:</b> ' . $credential->name . ' - <b>User value</b>: ' . $credential->apiCredential->user->value . '</li>'; 

     } 
     echo '</li></ul>'; 
    } 
    echo '</ul>'; 


    //To list every user's apis 
    echo '<h3>User: ' . $user_2->email . '</h3>'; 
    echo 'Apis attached: <br />'; 
    echo '<ul>'; 
    foreach ($user_2->apis as $api) { 
     echo '<li>' . $api->name . '</li>'; 
     //You can get required credentials per api. 
     echo '<ul>'; 
     foreach ($api->credentials as $credential) { 
      //And for every credential you can get user's value. 
      echo '<li><b>Name:</b> ' . $credential->name . ' - <b>User value</b>: ' . $credential->apiCredential->user->value . '</li>'; 
     } 
     echo '</li></ul>'; 
    } 
    echo '</ul>'; 

    //To list all apis 
    echo '<h3>All apis:</h3>'; 
    $apis = \App\Api::all(); 
    foreach ($apis as $api) { 
     echo $api->name . '<br />'; 
    } 

    //To list all credentials: 
    echo '<h3>All credentials:</h3>'; 
    $credentials = \App\Credential::all(); 
    foreach ($credentials as $credential) { 
     echo $credential->name . '<br />'; 
    } 
}); 

以上提供的虚拟数据将给出:screenshot

+0

实施这个例子后,我发现这有点令人困惑,但这并不是说这不是一个好方法。 相反,我抬头约多态性雄辩一些教程,发现这些链接: https://laravel.com/docs/5.1/eloquent-relationships https://adamwathan.me/2015/09/03/推送多态到数据库/ 我已经提前使用那些目前已经很成功的工具 –

+0

@AlexC如果你的工作似乎更好,你应该自己回答你的问题并接受答案。 :) –