2017-03-03 191 views
1

我正在Laravel 5.2中工作,我試圖使其與Vertica協同工作。幾個月前,我和我的同事提出了this解決方案,但我們現在試圖讓事情變得更簡單一些,並使用服務提供商來完成工作,以便我們可以更輕鬆地升級Laravel。那麼,我們迄今所做的是:使用Laravel服務提供商來覆蓋連接器類

1)創建兩個新的類,擴展他們的同行:

新BaseConnector:

namespace App\Vertica; 
include 'clsPDOVertica.php'; 

use Illuminate\Support\Arr; 
use \Illuminate\Database\Connectors\Connector as BaseConnector; 

class Connector extends BaseConnector 
{ 
    /** 
    * Create a new PDO connection. 
    * 
    * @param string $dsn 
    * @param array $config 
    * @param array $options 
    * @return \PDO 
    */ 
    public function createConnection($dsn, array $config, array $options) 
    { 
     $username = Arr::get($config, 'username'); 

     $password = Arr::get($config, 'password'); 

     return new PDOVertica($dsn, $username, $password, $options); 
    } 
} 

新PostgresConnector:

namespace App\Vertica; 

use \Illuminate\Database\Connectors\PostgresConnector as BasePostgresConnector; 

class PostgresConnector extends BasePostgresConnector 
{ 

    /** 
    * Create a DSN string from a configuration. 
    * 
    * @param array $config 
    * @return string 
    */ 
    protected function getDsn(array $config) 
    { 
     // First we will create the basic DSN setup as well as the port if it is in 
     // in the configuration options. This will give us the basic DSN we will 
     // need to establish the PDO connections and return them back for use. 
     extract($config, EXTR_SKIP); 

     $host = isset($host) ? "host={$host};" : ''; 

     $dsn = "Driver={$driverpath};{$host}Database={$database}"; 

     // If a port was specified, we will add it to this Postgres DSN connections 
     // format. Once we have done that we are ready to return this connection 
     // string back out for usage, as this has been fully constructed here. 
     if (isset($config['port'])) { 
      $dsn .= ";port={$port}"; 
     } 

     if (isset($config['sslmode'])) { 
      $dsn .= ";sslmode={$sslmode}"; 
     } 

     return $dsn; 
    } 
} 

現在,我們試圖定義一個服務提供者來告訴Laravel使用我們的類而不是默認的類......但是目前爲止沒有成功。下面是供應商代碼:

namespace App\Providers; 

use Illuminate\Support\ServiceProvider; 

class VerticaServiceProvider extends ServiceProvider 
{ 
    /** 
    * Register bindings in the container. 
    * 
    * @return void 
    */ 
    public function register() 
    { 
     // dd(new \Illuminate\Database\Connectors\PostgresConnector); 
     $this->app->singleton('\Illuminate\Database\Connectors\Connector', function() 
     { 
      return new \App\Vertica\Connector(); 
     }); 

     $this->app->singleton('\Illuminate\Database\Connectors\PostgresConnector', function() 
     { 
      return new \App\Vertica\PostgresConnector(); 
     }); 
    } 
} 

到目前爲止,我們的VerticaServiceProvider的登記方法被調用,但很明顯,裏面的結合是錯誤的,因爲我們的類不獲取調用。任何人都知道我們做錯了什麼?

回答

2

Laravel無法從容器中解析Connector類,因此嘗試按類名覆蓋連接器將不起作用。

您可以在Illuminate/Database/Connectors/ConnectionFactory::createConnector中看到連接器是如何解決的。 Laravel只是做了一個return new PostgresConnector(或者哪一個適合司機),所以它不會在容器中尋找類名。

然而,「新的」 S了Connector之前,它檢查容器,看是否有必然要使用字符串'db.connector.[driver]',其中[driver]是DB驅動程序名稱驅動程序的連接器。

因此,而不是嘗試綁定容器中的類名稱,您需要綁定字符串'db.connector.your-driver-name'。因此,如果您創建了自己的自定義驅動程序(例如vertica),則可以將連接器綁定到'db.connector.vertica'。或者,如果您想覆蓋內置的postgres連接器,則可以將連接器綁定到'db.connector.pgsql'

基於你想覆蓋的Postgres連接器的假設下,服務提供商註冊方法如下所示:

public function register() 
{ 
    $this->app->bind('db.connector.pgsql', \App\Vertica\PostgresConnector::class); 
}