Bonjour,
J'ai besoin de me connecter à une base de données SQL Server 2008 R2 et j'ai créé mon propre driver Cake pour ce faire. Cela "marchouille", dans le sens ou model->schema() fonctionne mais dès que je veux faire un model->find(), cela plante.
La classe du driver :
<?php namespace App\Database\Driver;
use Cake\Database\Driver;
use Cake\Database\Driver\PDODriverTrait;
use Cake\Database\Schema\SqlserverSchema;
use PDO;
/**
* Class DblibDriver
*
* @package App\Database\Driver
*/
class DblibDriver extends Driver{
use PDODriverTrait;
/**
* Base configuration settings for Sqlserver driver
*
* @var array
*/
protected $_baseConfig = [
'persistent' => false,
'host' => 'localhost\SQLEXPRESS',
'username' => '',
'password' => '',
'database' => '',
'encoding' => 65001,
'flags' => [],
'init' => [],
'settings' => [],
];
/**
* Establishes a connection to the database server
*
* @return bool true con success
*/
public function connect()
{
if ($this->_connection) {
return true;
}
$config = $this->_config;
$config['flags'] += [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ
];
$dsn = "dblib:version=8.0;charset=UTF-8;host={$config['host']};dbname={$config['database']}";
$this->_connect($dsn, $config);
$connection = $this->connection();
if (!empty($config['init'])) {
foreach ((array)$config['init'] as $command) {
$connection->exec($command);
}
}
if (!empty($config['settings']) && is_array($config['settings'])) {
foreach ($config['settings'] as $key => $value) {
$connection->exec("SET {$key} {$value}");
}
}
return true;
}
/**
* Establishes a connection to the database server
*
* @param string $dsn A Driver-specific PDO-DSN
* @param array $config configuration to be used for creating connection
* @return bool true on success
*/
protected function _connect($dsn, array $config)
{
$connection = new PDO(
$dsn,
$config['username'],
$config['password'],
$config['flags']
);
$this->connection($connection);
return true;
}
/**
* Disconnects from database server
*
* @return void
*/
public function disconnect()
{
$this->_connection = null;
}
/**
* Returns correct connection resource or object that is internally used
* If first argument is passed,
* @param null $connection
*
* @return null|\PDO
*/
public function connection($connection = null)
{
if ($connection !== null) {
$this->_connection = $connection;
}
return $this->_connection;
}
/**
* Returns whether php is able to use this driver for connecting to database
*
* @return bool true if it is valid to use this driver
*/
public function enabled()
{
return in_array('dblib', PDO::getAvailableDrivers());
}
/**
* Starts a transaction
*
* @return bool true on success, false otherwise
*/
public function beginTransaction()
{
// TODO: Implement beginTransaction() method.
}
/**
* Commits a transaction
*
* @return bool true on success, false otherwise
*/
public function commitTransaction()
{
// TODO: Implement commitTransaction() method.
}
/**
* Rollsback a transaction
*
* @return bool true on success, false otherwise
*/
public function rollbackTransaction()
{
// TODO: Implement rollbackTransaction() method.
}
/**
* Get the SQL for releasing a save point.
*
* @param string $name The table name
*
* @return string
*/
public function releaseSavePointSQL($name)
{
// TODO: Implement releaseSavePointSQL() method.
}
/**
* Get the SQL for creating a save point.
*
* @param string $name The table name
*
* @return string
*/
public function savePointSQL($name)
{
// TODO: Implement savePointSQL() method.
}
/**
* Get the SQL for rollingback a save point.
*
* @param string $name The table name
*
* @return string
*/
public function rollbackSavePointSQL($name)
{
// TODO: Implement rollbackSavePointSQL() method.
}
/**
* Get the SQL for disabling foreign keys
*
* @return string
*/
public function disableForeignKeySQL()
{
// TODO: Implement disableForeignKeySQL() method.
}
/**
* Get the SQL for enabling foreign keys
*
* @return string
*/
public function enableForeignKeySQL()
{
// TODO: Implement enableForeignKeySQL() method.
}
/**
* Returns whether the driver supports adding or dropping constraints
* to already created tables.
*
* @return bool true if driver supports dynamic constraints
*/
public function supportsDynamicConstraints()
{
// TODO: Implement supportsDynamicConstraints() method.
}
/**
* Returns a value in a safe representation to be used in a query string
*
* @param mixed $value The value to quote.
* @param string $type Type to be used for determining kind of quoting to perform
*
* @return string
*/
public function quote($value, $type)
{
// TODO: Implement quote() method.
}
/**
* Returns a callable function that will be used to transform a passed Query object.
* This function, in turn, will return an instance of a Query object that has been
* transformed to accommodate any specificities of the SQL dialect in use.
*
* @param string $type the type of query to be transformed
* (select, insert, update, delete)
*
* @return callable
*/
public function queryTranslator($type)
{
// TODO: Implement queryTranslator() method.
}
/**
* Get the schema dialect.
*
* Used by Cake\Database\Schema package to reflect schema and
* generate schema.
*
* If all the tables that use this Driver specify their
* own schemas, then this may return null.
*
* @return \Cake\Database\Schema\BaseSchema
*/
public function schemaDialect()
{
return new SqlserverSchema($this);
}
/**
* Quotes a database identifier (a column name, table name, etc..) to
* be used safely in queries without the risk of using reserved words
*
* @param string $identifier The identifier expression to quote.
*
* @return string
*/
public function quoteIdentifier($identifier)
{
// TODO: Implement quoteIdentifier() method.
}
}
C'est relativement simple, j'aimerais utiliser l'ORM de Cake pour attaquer une base SQL Server 2008 R2.
Lors de l'appel de la méthode find sur mon model, j'obtiens le message d'erreur suivant :
Function name must be a string in /home/dev/www/lab/erpdash/vendor/cakephp/cakephp/src/Database/Driver.php on line 331.
Ce qui correspond à la ligne suivante $query = $translator($query); dans le code ci-dessous.
public function compileQuery(Query $query, ValueBinder $generator)
{
$processor = $this->newCompiler();
$translator = $this->queryTranslator($query->type());
$query = $translator($query);
return [$query, $processor->compile($query, $generator)];
}
En effet cette méthode (queryTranslator) n'est pas implémentée dans mon driver car je n'arrive pas à déterminer ce que je dois retourner (un callable dit la doc).
Merci pour votre aide !
Dans ce cas là, tu devrais penser à ne plus utiliser dblib, car après quelques petites recherches, voici ce qu'il en sort :
PDO_DBLIB est un pilote qui implémente l'interface de PHP Data Objects (PDO) pour autoriser l'accès de PHP au Microsoft SQL Server et aux bases de données Sybase par la bibliothèque FreeTDS.
Cette extension n'est plus disponible sous Windows avec PHP 5.3 et suivant.
Sous Windows, vous devriez utiliser SqlSrv, un driver alternatif pour MS SQL disponible chez Microsoft : » http://msdn.microsoft.com/en-us/sqlserver/ff657782.aspx .
Si vous ne pouvez pas utiliser SqlSrv, vous pouvez utiliser le driver PDO_ODBC pour se connecter à un serveur de bases de données Microsoft SQL et Sybase, sachant que le driver natif Windows DB-LIB est ancien, non sécurisé niveau thread et plus supporté par Microsoft.
Re,
Et merci de ton aide (te l'avais pas dit tout à l'heure).
Mon serveur est sous Debian8, cela veut dire que je ne peux pas utiliser le driver sous Windows. Il ne me reste plus alors qu'une connexion ODBC ?
Pour y avoir goûté sur d'autres projets, les performances ne sont pas au rendez-vous et je manipule de "grosses" bases de données pas forcément bien indexées. C'est pour cette raison que je suis parti direct sur Dblib.
Au vu de l'infomation que tu me donnes (techno obsolète), je crois que je n'ai pas le choix... :(
Encore merci de ton aide.
Bonsoir.
Pourquoi est-ce que tu crées un Driver pour SQL Server, alors qu'il en existe déjà un sur CakePHP ?
namespace Cake\Database\Driver; » Sqlserver.
Bonsoir,
Car le driver natif ne fonctionne pas sur mon environnement. Le message que j'obtiens lors de l'utilisation du driver natif (dès le lancement de l'application) :
Database driver Cake\Database\Driver\Sqlserver cannot be used due to a missing PHP extension or unmet dependency
Je me suis aperçu que dans ce driver, la méthode enabled teste l'existence du driver PDO qui se nomme sqlsrv... N'existe pas chez moi. C'est "dblib" qui fonctionne.
public function enabled()
{
return in_array('sqlsrv', PDO::getAvailableDrivers());
}
De rien.
Il y a une chose que j'ai du mal à suivre.
Tu dis que ton serveur est sur un Debian 8, soit sur un système d'exploitation Linux et tu utilises Microsoft SQL server dans ton serveur Linux ?
Pourquoi tu n'utilises pas directement du MySQL ou autre à la place ?
Il ne me reste plus alors qu'une connexion ODBC ?
Seulement s'il t'est impossible d'installer le driver Sqlsrv, mais si tu le peux, il est préférable que tu installes ce dernier, si tu restes bien sûr sur du SQL Server.
Bonjour,
J'ai un serveur Apache sur Debian qui possède bien MySQL et que j'utilise pour le fonctionnement de mon site (navigation, paramètres...) Mais j'accède à des données d'un ERP hébergées sur un autre serveur qui est évidement en Windows pour faire tourner SQL Server.
Je vais donc ce matin me lancer dans l'installation du pilote pdo-odbc...
Il y a moi aussi un truc que je ne comprends pas. Dans Cake, quel driver utiliser pour PDO-ODBC ?