与Laravel中DB Facade的接口

时间:2018-01-31 14:18:15

标签: php design-patterns laravel-5.5

首先,如果这是一个愚蠢的问题,我道歉。我最近阅读了一篇关于存储库设计模式的文章,我在为Laravel Query Builder(Illuminate \ Support \ Facades \ DB)进行接口实现时遇到了问题。

DatabaseService.php     

<?php namespace Modules\Core\Interfaces;
interface IDatabase
{
  public function select($str);
  public function table($tableName);
  public function raw($rawQuery);
  public function transaction($callback);
  public function first();
  public function get();
}

IDatabase.php

...

public function register()
{
  ...
  $this->app->bind('Modules\Core\Interfaces\IDatabase', function($app) {
    $db = $app->make(DB::class);

    return new DatabaseService($db);
  });
  ...
}

CoreServiceProvider.php

<?php namespace Modules\Mailbox\Repositories;

use Illuminate\Database\Eloquent\Model;
use Modules\Core\Interfaces\IDatabase;
use Modules\Mailbox\Interfaces\IMailbox;

class MailboxRepository implements IMailbox
{
  public function __construct(..., IDatabase $db)
  {
  ...
    $this->db = $db;
  }
  ...
  public function getBadges()
  {
    $badges = $this->db->table('mailbox as a')
              ->select($this->db->raw(
                "SUM(a.type = 'inbox') as inbox, 
                 SUM(a.is_read = 0 AND a.type = 'inbox') as unread,
                 SUM(a.type = 'sent') as sent,
                 SUM(a.type = 'draft') as draft,
                 SUM(a.type = 'outbox') as outbox,
                 SUM(a.type = 'spam') as spam,
                 SUM(a.type = 'trash') as trash,
                 SUM(a.is_starred = 1) as starred"
              ))
              ->first();

    return $badges;
  }
  ...
}

MailboxRepository.php

<?php namespace Modules\Mailbox;

...
use Modules\Mailbox\Interfaces\IMailbox;
use Modules\Mailbox\Repositories\MailboxRepository;
use Modules\Core\Interfaces\IDatabase;
use Illuminate\Support\ServiceProvider;

class MailboxServiceProvider extends ServiceProvider 
{
  protected $defer = true;

  public function register()
  {
    $this->app->bind(IMailbox::class, function($app) {
      return new MailboxRepository(
        ..., $app->make(IDatabase::class)
      );
    });
  }

  public function provides()
  {
    return [IMailbox::class];
  }
}

MailboxServiceProvider.php

[2018-01-31 13:45:04] local.ERROR: Call to undefined method Illuminate\Support\Facades\DB::select() 
{"userId":1,"email":"info@narpandi.com","exception":"[object] 
(Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call 
to undefined method Illuminate\\Support\\Facades\\DB::select() at 
/var/www/personal-
website/app/Modules/Mailbox/Repositories/MailboxRepository.php:86)

显示错误消息:

HTML

如何正确执行此操作?谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

我认为这不是一个常见的存储库模式,在存储库模式中,您尝试创建类似的方法:

Object get(Object id);
void create(Object entity);
void update(Object entity);
void delete(Object entity);

编辑,尝试执行类似文档的操作:Database

use Modules\Core\Interfaces\IDatabase;
use Illuminate\Support\Facades\DB;

class DatabaseService implements IDatabase
{  

  public function select($str, $args)
  {
    return DB::select($str, $args);
  }
}

但我再次说这看起来不像repository

答案 1 :(得分:0)

经过反复试验,我终于弄清楚如何做到这一点。如https://stackoverflow.com/a/26356144/3050636中所述,您不能直接使用Facade DB,而是需要显式传递数据库外观后面的类。

就我而言,我使用桥接模式和流畅的界面(CMIIW),所以我将提供两个版本:

  • 没有桥梁模式

<强> MailboxServiceProvider.php

<?php namespace Modules\Mailbox\Repositories;

use Illuminate\Database\DatabaseManager;
use Modules\Mailbox\Interfaces\IMailbox;

class MailboxRepository implements IMailbox
{
  ...
  protected $db;

  public function __construct(..., DatabaseManager $db)
  {
    ...
    $this->db = $db;
  }
  ...
}

<强> MailboxRepository.php

<?php namespace Modules\Core;

....
use Modules\Core\Services\DatabaseService;
use Modules\Mailbox\Repositories\MailboxRepository;
use Modules\Core\Interfaces\IDatabase;
use Modules\Mailbox\Interfaces\IMailbox;

/* Use these instead of DB facade */
use Illuminate\Database\DatabaseManager;
use Illuminate\Database\Connectors\ConnectionFactory;

use Illuminate\Support\ServiceProvider;

class CoreServiceProvider extends ServiceProvider 
{
  public function register()
  {
    ...
    $this->app->bind(IDatabase::class, function($app) {
      return new DatabaseService(new DatabaseManager($app, new ConnectionFactory($app)));
    });

    $this->app->bind(IMailbox::class, function($app) {
      return new MailboxRepository(
        ..., $app->make(IDatabase::class)
      );
    });
    ...
  }
}
  • 具有桥接模式和流畅的界面

<强> CoreServiceProvider.php

<?php namespace Modules\Core\Services;

use Modules\Core\Interfaces\IDatabase;
use Illuminate\Database\DatabaseManager;

class DatabaseService implements IDatabase
{  
  protected $db;

  public function __construct(DatabaseManager $db)
  {
    $this->db = $db;
  }

  public function select($str)
  {
    $this->db = $this->db->select($str);
    return $this->db;
  }

  public function table($tableName)
  {
    $this->db = $this->db->table($tableName);
    return $this->db;
  }
  ...
}

<强> DatabaseService.php

<?php namespace Modules\Mailbox\Repositories;

use Modules\Core\Interfaces\IDatabase;
use Modules\Mailbox\Interfaces\IMailbox;

class MailboxRepository implements IMailbox
{
  ...
  protected $db;

  public function __construct(..., IDatabase $db)
  {
    ...
    $this->db = $db;
  }
  ...
}

<强> MailboxRepository.php

{{1}}