雄辩的查找表和模型创建

时间:2016-06-23 07:31:29

标签: php mysql laravel eloquent

所以我已经在一个项目上工作了几个星期,因为它已经拿起了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集成,可以使用Eloquent的关系助手

访问这些集成
class User
{
...
    public function rewardMethods()
    {
        return $this->hasMany(APIIntegration::class);
    }
...
}

希望澄清一点

1 个答案:

答案 0 :(得分: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

我需要的下一张表是一个表格,其中包含apiuser所拥有的内容。这相当于您的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, 'test@user.com'), (NULL, 'test2@user.com');
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