Link to home
Start Free TrialLog in
Avatar of Jorge Batres
Jorge BatresFlag for United States of America

asked on

mysql_connect PHP 7

Hello, I have a script to connect to a database that I need to update  to PHP 7 but I don't know the proper way to set up mysql_connect and mysql_select_db. I know this extension has been removed from PHP 7 and I need to know what to enter or replace to make this class work in PHP 7.

Please help.

Thanks,
Jorge

class Database {
  /*This is a modular class that masks the underlying MySQL calls and provides a generic interface to its client. */
  function __construct($host, $port, $dbname, $user, $password, $transactional = true) {
    /* Ignore SSL since MySQL does not support it */
    if ($port) {
      $host = "$host:$port";
    }
    $this->Connection = mysql_connect($host, $user, $password);
    mysql_select_db($dbname, $this->Connection);
    if ($transactional){
      $this->Query("SET AUTOCOMMIT=0");
    }
  }

  function Query($sql){
    $this->Result = @mysql_query($sql, $this->Connection);
    if ($this->Result === false){
      $this->HandleError($sql);
    }
  }

  function Select($sql){
    $this->Query($sql);
  }

  function Update($sql){
    /* Right now this does the same thing as select...but it leaves room for expansion with replication */
    $this->Query($sql);
  }

  function Next($associative = True){
    /* Return the next row in the result set */
    if($associative){
      return mysql_fetch_assoc($this->Result);
    }
    else {
      return mysql_fetch_row($this->Result);
    }
  }

  function ResultLength(){
    return mysql_num_rows($this->Result);
  }

  function HandleError($sql) {
    /* This function should be overridden to provide custom error handling for the application */
    die(ErrorMessage("mysql", "MySQL Error in $sql: " . mysql_error($this->Connection)));
  }

  function Commit(){
    $this->Query("COMMIT");
  }

  function Rollback(){
    $this->Query("ROLLBACK");
  }
}

Open in new window

Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Please see this article.  The MySQL extension has been removed.  The article shows the alternatives - MySQLi or PDO.
https://www.experts-exchange.com/articles/11177/PHP-MySQL-Deprecated-as-of-PHP-5-5-0.html
This may not be 100% right, but it's probably close (except for the error handler).  Worth testing, at least.
class Database {
  /*This is a modular class that masks the underlying MySQL calls and provides a generic interface to its client. */
  function __construct($host, $port, $dbname, $user, $password, $transactional = true) {
    /* Ignore SSL since MySQL does not support it */
    if ($port) {
      $host = "$host:$port";
    }
    $this->Connection = new MySQLi($host, $user, $password, $dbname);
    if ($transactional){
      $this->Query("SET AUTOCOMMIT=0");
    }
  }

  function Query($sql){
    $this->Result = $this->Connection->query($sql);
    if ($this->Result === false){
      $this->HandleError($sql);
    }
  }

  function Select($sql){
    $this->Query($sql);
  }

  function Update($sql){
    /* Right now this does the same thing as select...but it leaves room for expansion with replication */
    $this->Query($sql);
  }

  function Next($associative = True){
    /* Return the next row in the result set */
    if($associative){
      return $this->Result->fetch_assoc();
    }
    else {
      return $this->Result->fetch_array();
    }
  }

  function ResultLength(){
    return $this->Result->num_rows;
  }

  function HandleError($sql) {
    /* This function should be overridden to provide custom error handling for the application */
    // die(ErrorMessage("mysql", "MySQL Error in $sql: " . mysql_error($this->Connection))); NOT SURE WHAT TO DO WITH THIS
  }

  function Commit(){
    $this->Query("COMMIT");
  }

  function Rollback(){
    $this->Query("ROLLBACK");
  }
}

Open in new window

Avatar of Jorge Batres

ASKER

Thank you so much Ray, I have implemented your changes and the errors went away, but I should have entered the first part of the script where now I realize I get an error mysql_escape_string.

here is the rest of the code and thank you so much for your help.

include("shared.inc.php");
class StoredProcedure {
  /*This is a modular class that provides a generic interface for calling stored procedures or the equivalent */
  function StoredProcedure($name, $update, $parameters, $defaults){
    $this->name = $name;
    $this->update = $update;
    $this->parameters = $parameters;
    $this->defaults = $defaults;
  }

  function GetQuery($arguments){
    global $StoredProcedures;
    $callparameters = array();
    foreach($this->parameters as $parameter){
      if(isset($arguments[$parameter])){
        $callparameters[] = $this->Escape($arguments[$parameter]);
      }
      else if (isset($this->defaults[$parameter])){
        $callparameters[] = $this->Escape(DefaultParameter($this->defaults[$parameter]));
      }
      else {
        die(MissingParameterError($parameter));
      }
    }
    return vsprintf($StoredProcedures[$this->name], $callparameters);
  }
  
  function ReturnsRows() { //Does this stored procedure return a recordset?
    return ($this->update == false);
  }

  function Escape($value){
    if ($value === false){
      return "NULL";
    }
    return "'" . mysql_escape_string($value) . "'";
  }

  function Call(&$database, $arguments){
    if ($this->update){
      $database->Update($this->GetQuery($arguments));
    }
    else {
      $database->Select($this->GetQuery($arguments));
    }
  }
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you Ray, I will try to work with this as much as I can
Ok, so in line 37 where I'm getting the error I entered this but I'm missing the first parameter  but I can't figure it out
return "'" . mysqli_real_escape_string($value) . "'";

Open in new window

That's where you need access to the MySQLi object.  The correct syntax will look like this:
return "'" . $mysqli->real_escape_string($value) . "'";

Open in new window

But that is just the syntax for that one statement.  The function will need to get the $mysqli object via dependency injection, or it will need to make another connection to the database.
So should I use this to replace my database class, and try to make another connection?

error_reporting(E_ALL);


// SINGLETON DATA BASE CONNECTION CLASS
class Database
{
    // CLASS PROPERTIES ARE ALL PRIVATE
    private static $connection;
    private static $instance;

    // PUT YOUR CONNECTION VALUES HERE
    const DB_HOST = 'localhost';
    const DB_USER = '??';
    const DB_PASS = '??';
    const DB_NAME = '??';

    // NULLIFY THE CLONE AND THE WAKEUP
    final private function __clone() {}
    final private function __wakeup() {}

    // OUR ONLY PUBLIC METHOD RETURNS THE CONNECTION
    final public static function getConnection()
    {
        if (!self::$instance) self::$instance = new self();
        return self::$connection;
    }

    // CONSTRUCTOR CREATES THE CONNECTION
    final private function __construct()
    {
        self::$connection
        = new mysqli
        ( self::DB_HOST
        , self::DB_USER
        , self::DB_PASS
        , self::DB_NAME
        )
        ;
        if (self::$connection->connect_error)
        {
            trigger_error(self::$connection->connect_error, E_USER_ERROR);
        }
    }
}


// SHOW WHAT HAPPENS WHEN YOU TRY TO MAKE TWO CONNECTIONS
$dbc_1 = database::getConnection();
$dbc_2 = database::getConnection();


// PROVE THAT THESE VARIABLES POINT TO THE SAME OBJECT
if ($dbc_1 === $dbc_2) echo 'EQUAL! ';

// SHOW THE OBJECT
echo '<pre>';
var_dump($dbc_2);

Open in new window

No, I wouldn't recommend that.  Singletons are like globals -- they are considered to be a bad programming practice because you cannot isolate them for testing.  A better strategy would be to refactor the existing classes.

It looks like the database object is passed into the Call() method.  You can probably pass it into the Escape() method, too.  Something like this might work.
  function Escape(MySQLi $database, $value){
    if ($value === false){
      return "NULL";
    }
    return "'" . $database->real_escape_string($value) . "'";
  }

Open in new window

Thank you Ray, now I'm getting this:

Argument 1 passed to StoredProcedure::Escape() must be an instance of mysqli,  called in mysql.php on line 17 and defined in mysql.php:33

It is referring to this line
 $callparameters[] = $this->Escape($arguments[$parameter]);
      }

Open in new window

Yes, that is where "dependency injection" comes into play.  Your script needs to change so that the method call matches the method signature.

A method signature is the function definition.  It looks like this:
function Escape(MySQLi $database, $value){...

Open in new window

A method call looks like this, but it is wrong because the arguments do not match:
$callparameters[] = $this->Escape($arguments[$parameter]);

Open in new window

They would match if you use something like this:
$callparameters[] = $this->Escape($database, $arguments[$parameter]);

Open in new window

Without getting too verbose, refactoring is almost certainly needed here.  One-line changes probably will not get you the results you need.  Every place that touches the database must be inspected and may need to be revised.
Thank you Ray, I will continue working on the changes for this script.
Thanks for the points, and please post again if you run into any issues while refactoring!