1

So I am trying to make an easy way to manage a bunch of mysql connections.

I have 2 basic classes: server and Connections.

server is just setup to hold a row of data as you see it. (Is there a better way to do this?)

In connections I would like to just call the connection by it's ID and create the connection, and be able to query it.

This works with the mysql library, but when I try to use mysqli library it won't pass $mysqli to $msi as a connection handle. $mysqli->query() works, but $msi->query() doesn't.

   PHP Fatal error:  Call to undefined method Connections::query()

Do I need to extend/implement my Connections class with mysqli or return the $mysqli in a different fashion?

Thank you!

    <?php
    class server {
        public $id, $type, $subid, $host, $user, $pw, $port, $db;

        public function __construct($id,$type,$subid,$host,$user,$pw,$port,$db) {
            $this->id = $id;
            $this->type = $type;
            $this->subid = $subid;
            $this->host = $host;
            $this->user = $user;
            $this->pw = $pw;
            $this->port = $port;
            $this->db = $db;
        }
    }

    class Connections {
        public $servers;

        function __construct($id) {
            $this->servers[] = new server("mysql","mysql","main","hostname","username","password","3306","dbname");
            $this->servers[] = new server("mysql2","mysqli","main","hostname","username","password","3306","dbname");

            $rt = null;
            foreach($this->servers as $server) {
                if ($id == $server->id) {
                    $rt = $server;
                    break;
                }
            }

            if($rt->type == "mysql"){
                $con = mysql_connect($rt->host,$rt->user,$rt->pw);
                mysql_select_db($rt->db, $con);
                    if($con) { return $con; }
            }
            elseif($rt->type == "mysqli"){
                $mysqli = new mysqli($rt->host, $rt->user, $rt->pw, $rt->db, $rt->port);
                        if ($mysqli->connect_errno) {
                              echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
                        }
                        else{
                              return $mysqli;
                        }
            }

        }
    }

    /*
    ### this works
    $nc = new Connections("mysql");
    $q = "select 1+2 as asdf";
    $r = mysql_query($q);
    while($row = mysql_fetch_array($r)){
        echo $row['asdf']."\n";
    }
    */

    #### this does not work
    $msi = new Connections("mysql2");
    $res = $msi->query("SELECT 2+2 as asdf");
    while($row = $res->fetch_assoc()){
        echo $row['asdf']."\n";
    }
    ?>
#

EDIT -> I was able to make this work in a different way with help of another post here

here is my revised code:

<?php
class server {
    public $id, $type, $subid, $host, $user, $pw, $port, $alt; 
    public function __construct($id,$type,$subid,$host,$user,$pw,$port,$alt) {
        $this->id = $id;
        $this->type = $type;
        $this->subid = $subid;
        $this->host = $host;
        $this->user = $user;
        $this->pw = $pw;
        $this->port = $port;
        $this->alt = $alt;
    }  
}

class MySQLiContainer extends SplObjectStorage{
    var $server, $servers;
    function __construct($id) {
        $this->servers[] = new server("mysql","mysql","main","hostname","username","password","3306","dbname");
        $this->servers[] = new server("mysql2","mysqli","main","hostname","username","password","3306","dbname");

         foreach($this->servers as $server) {
                if ($id == $server->id) {
                    $this->server = $server;
                    break;
                }
            }
    }
  public function newConnection() {

    $mysqli = new mysqli($this->server->host, $this->server->user, $this->server->pw, $this->server->alt, $this->server->port);
    $this->attach($mysqli);
    return $mysqli;
  }
}

//usage
$mysqliContainer = new MySQLiContainer("mysql2");
$c1 = $mysqliContainer->newConnection();
$res = $c1->query('SELECT 2+4 as asdf');
while($row = $res->fetch_assoc()){
    echo $row['asdf']."\n";
}
echo $c1->host_info . "\n";

$ms2 = new MySQLiContainer("mysql");
$c2 = $ms2->newConnection();
$r = $c2->query('SELECT 2+4 as dfdf');
while($ra = $r->fetch_assoc()){
    echo $ra['dfdf']."\n";
}
echo $c2->host_info . "\n";
?>
Community
  • 1
  • 1
neutron
  • 81
  • 7

1 Answers1

2

Your code is based on a false premise: that you can return anything from a constructor.

You can't return anything from a constructor. The result of the new operator is always an instance of the class.

Lemme rephrase, in case that wasn't clear. You can't return anything from a constructor, as the value of return is discarded.

What you seem to want to do is extend mysqli.

However, you don't actually want to do this for two big reasons:

  1. mysqli doesn't make it possible to return related classes, like the statement handle or the results handle, as derived classes. This can severely limit functionality. If you really want to extend a database handler, use PDO.
  2. Why are you writing your own database abstraction library? There are dozens of them. Go take a look at Zend Db or whatever Doctrine uses. They are going to be far more useful to you -- created by qualified third parties and well tested.
Charles
  • 50,943
  • 13
  • 104
  • 142
  • Thank you for clarifying my misunderstanding with the __construct() method. I am trying to write my own database abstraction library because I have several sites that use a shared Amazon RDS instance behind multiple load balanced EC2 instances. I want to in a way shard the data and pull non critical information off the RDS instance and run it on the EC2 instances to increase our overall connection capacity while not increasing current costs. – neutron Dec 26 '12 at 06:37
  • I don't envy that task. Good luck! – Charles Dec 26 '12 at 07:27