Use interfaces to abstract connection type

Asked

Viewed 186 times

1

In college we learn to use the model FACTORY for connections, but I wonder if it is possible to apply interfaces too, as in the following example:

Case study

I have a php application that follows the pattern as closely as possible MVC, but that should have the independent connection, that is, if it is necessary to change the bank, there is no need to rewrite the whole application.

So, it was created in the model, a class called MySQ_LConnect, providing connection to the bank Mysql, and the implementation of querys passed down to her:

class MYSQL_connect {

    private $hostname = 'myHost';
    private $username = 'DBUser';
    private $senha = '';
    private $banco = 'database';
    private $conn;

    public function conectar(){
        $this->conn = mysql_pconnect($this->hostname, $this->username, $this->senha);
        $db = mysql_select_db($this->banco,$this->conn);
        return $this->conn;
    }

    public function executarQuery($query,$conn){
        $result = mysql_query($query,$conn);
        return $result;
    }

    public function desconectar($conn){
        mysql_close($conn);
    }

Thinking about a future migration to the sql server, a connection class has been created for this database and an interface, only to parameterize the two existing connection classes:

Interface

interface iConnect{

    public function conectar();
    public function executarQuery($query,$conexao);
    public function desconectar($conexao);
}

Class of connection with sqlserver

class MSSQL_connect implements iConnect{

    private $hostname = 'myHost';
    private $connInfo = array("Database"=>"database", "UID"=>"DBUser", "PWD"=>"");
    private $conn;

    public function conectar(){
        $this->conn = sqlsrv_connect($this->hostname, $this->connInfo) or die(sqlsrv_errors());
        return $this->conn;
    }

    public function executarQuery($sql,$conn){
        $result = sqlsrv_query($conn,$sql,array(),array("Scrollable"=>"buffered"));
        return $result;
    }



    public function desconectar($conn){
        sqlsrv_close($conn);
    }
}

Obs.: in the class MYSQL_connect the interface was also implemented.

Then, in the test environment, it is possible to switch between banks using a connection Fabrica, where BANCO is a constant in the seat prefix (just to make it easier to switch between banks):

require_once 'MySQL_connect.php';
require_once 'MSSQL_connect.php';
define("BANCO","MySQL");//ou pode ser MSSQL
    class Fabrica{

        public function fabricar(){
            $classeDAO  = BANCO."_connect";

            return new $classeDAO;
        }       
    }

Doubt

How to use interfaces in this case to abstract the type of connection, similar to that of the class Fabrica is trying to do so that for the rest of the application does not make a difference in which bank is connecting?

If the interface does not meet this requirement well, such as abstracting without using Factory?

  • 1

    Two considerations: 1 - you are returning the connection $this->conn and receives $conn in some methods, which seems wrong to me, receive the connection as a parameter and you already have it inside the object; 2 - each implementation of executarQuery() returns a different type of resource, so that it makes no difference in the application you must always return the same type (a array for example). PHP does not have a native way of forcing a return type, so you should handle it manually.

  • @Sanction this running Uery() thing was purposeful, I have other methods that make this conversion that you said, but I removed it so that the code would not be giant, but within each connection class I do have a method that converts the result into an array. As for variable $conn was a tip from the teacher, I confess that I did not even think of this side kkkk

  • 1

    So the only way to improve your classes would be to modify Fabrica::fabricar() to receive a parameter with the type of the bank, with default value, recommend using constants (const TIPO_MYSQL)

  • I edited the question, BANCO is a constant already.

  • What does this class have to do with factory ?

  • I don’t consider using Interfaces something that generalizes. Thinking is wrong. It’s more like abstraction. To generalize, is to do something that serves for any case. Abstraction is when you create simple ways to meet in a way that gives minimal conditions for a functionality.

  • In addition, interfaces were made to bureaucratize your code, preventing other developers from destroying its basic functionality.

  • @Ivanferrer thanks for the correction, I meant abstraction, I will correct the question.

  • @Edilson in this activity, the suggestion was to use something similar to the standard Factory, in this case it was the class Fabrica. You’re not 100% following this pattern, it was just an inspiration.

  • Look, I’ll give you a very simple example of a factory.

Show 5 more comments

3 answers

0


One way to do it would be like this:

interface InterfaceFabrica {

   public function __construct(DatabaseConnect $databaseConnect);

}

It would have a class for the type as addiction injection:

class DatabaseConnect {

    const TYPE = 'MySQL';

    public function __construct($type = self::TYPE) {
        $classeDAO = $type. "_connect";
        return new $classeDAO;
   }

}

And the factory class implemantada with its manufacturing interface:

class Fabrica implements InterfaceFabrica {

   public function __construct(DatabaseConnect $databaseConnect) {
       return $this;
   }
}

Forcing the type through a constant, initiating manufacturing through the builder:

define('DATABASE_TYPE', 'MySQL');

$databaseConnect = new DatabaseConnect(DATABASE_TYPE);

$fabrica = new Fabrica($databaseConnect);

0

I suggest only an improvement in class Fabrica, use class constants:

class Fabrica {

    const TIPO_MYSQL = 'MySQL';
    const TIPO_MSSQL = 'MSSQL';

    public function fabricar($banco = self::TIPO_MYSQL) {
        $classeDAO  = $banco . "_connect";
        return new $classeDAO;
    }

}

0

To create a factory, it is not necessary to own an interface, interfaces maintain only consistency. One of the main priorities of this pattern, if I may say so, is to create objects without having to specify the exact class. They are useful when you want to use completely different objects in the same way. That is, different logics, but the same behavior when applied.

<?php

namespace Build;

class Forma
{
    public static function getForma($forma, $area)
    {
        switch($forma):
            case 'circulo';
                return new Circulo($area);
            case 'quadrado':
                return new Quadrado($area);
            default:
                return new stdClass();          
        endswitch;  
    }
    public function getArea()
    {
        // return get_class($this)
        return $this->getArea();
    }
}

class Circulo extends Forma 
{
    private $area;
    public function __construct($area)
    {
        $this->area = $area;
    }
    public function getArea(){
        return M_PI * ($this->area)**2;
    }
}

class Quadrado extends Forma 
{
    private $area;
    public function __construct($area)
    {
        $this->area = $area;
    }
    public function getArea()
    {
        return ($this->area)**2;
    }
}

?>

In this example, the classes circulo and quadrado are derived from the class forma, and have the same methods, but are different in logic, but continue to produce the same result, which is to return the corresponding area. It’s on that principle that you should start working in factories.

<?php

include_once 'class.forma.php';

$forma = \Build\Forma::getForma('circulo', 3);
print $forma->getArea();
print "<br/>";
$forma = \Build\Forma::getForma('quadrado', 4);
print $forma->getArea();
print "<br/>";

?>

See the example in operation.

Another rich example is this, with the use of interfaces, where the Sedan factory, can produce different models of the same brand, using the same processes. This must be your starting point.

  • My class Fabrica doesn’t do that already?

  • I see only interfaces, so I added this example.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.