Home » Php » php – I need to convert all the PDO in my function to MYSQLI but can't find the PDO alternatives

php – I need to convert all the PDO in my function to MYSQLI but can't find the PDO alternatives

Posted by: admin February 25, 2020 Leave a comment

Questions:

I am trying to find a way to convet my PDO::PARAM_INT and the other pdo values in the switch statement below to use mysqli. I am doing a portfolio project and for school and found out we are not allowed to use PDO for some reason so now I have to restructure 10 pages. Thanks in advance!

public function bind($param, $value, $type = null){
    if(is_null($type)){
        switch(true){
            case is_int($value):
                $type = PDO::PARAM_INT;
                break;
            case is_bool($value):
                $type = PDO::PARAM_BOOL;
                break;
            case is_null($value):
                $type = PDO::PARAM_NULL;
                break;
                default:
                $type = PDO::PARAM_STR;
        }
    }
    $this->stmt->bindValue($param, $value, $type);
}
How to&Answers:

mysqli has a method called bind_param(). It works quite different, so it is not so easy to replace your code with it. The first parameter passed to bind_param() is a string composed of letters signifying the type of parameters. For the most part you can use s for all types. In your case you would need to map booleans to integers presumably. MySQL doesn’t have a true boolean data type so all booleans are saved as 0 or 1.

An example would look like this:

$int = 2;
$bool = (int) false;
$string = '0';

$stmt = $mysqli->prepare('INSERT INTO dates VALUES(?,?,?)');
$stmt->bind_param('sss', $int, $bool, $string);
$stmt->execute();

All parameters must be bound in a single call to bind_param and the variables must be passed by reference, so they can’t be literals.

You can’t just replace your method with a mysqli equivalent. You would need to rewrite your code logic. I would strongly recommend to stick with PDO; it is easier and better than mysqli. If you must use mysqli, then you should probable write or use an existing database abstraction class. Using mysqli on its own is not recommended.

This is en example of what such class could look like:

class DBClass extends mysqli {
    public function __construct(
        $host = null,
        $username = null,
        $passwd = null,
        $dbname = null,
        $port = null,
        $socket = null
    ) {
        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
        parent::__construct($host, $username, $passwd, $dbname, $port, $socket);
        $this->set_charset('utf8mb4');
    }

    public function safeQuery(string $sql, array $params = []): ?array {
        $stmt = $this->prepare($sql);
        if ($params) {
            $stmt->bind_param(str_repeat("s", count($params)), ...$params);
        }
        $stmt->execute();
        if ($result = $stmt->get_result()) {
            return $result->fetch_all(MYSQLI_BOTH);
        }
        return null;
    }
}

$int = 2020;
$bool = false;
$string = '0';

$conn = new DBClass('localhost', 'inet', '5432', 'test');
$conn->safeQuery('INSERT INTO dates VALUES(?,?,?)', [$int, (int) $bool, $string]);

var_dump($conn->safeQuery('SELECT * FROM dates WHERE year=2020'));

This is by means not the best class ever, but I use it to illustrate how one could go about extending mysqli with a simpler helper method. It has the same constructor as mysqli class, but the constructor enables error reporting and sets the proper charset. The new method is just a wrapper around the cumbersome prepare/bind/execute pattern. It should work for all kinds of queries.

Answer:

First off, this whole function is useless by itself. You never need such a function with PDO when you can send all values directly to execute().

Also, it is useless because PDO::PARAM_NULL always being applied automatically, PDO::PARAM_BOOL doesn’t work with mysql and most values you are sending to database are strings, making PDO::PARAM_INT of no use either.

Moreover, it could be even harmful in some circumstances. Sending an int as string is all right but sending a string as int could be a disaster.

Either way, there is no way to bind values in mysqli manually, you only have an option to bind all values at once.

As you are already have to rewrite some code, I would suggest you a code which is much simpler yet more powerful than your current approach. Here is a mysqli helper function I wrote. You can use it instead your PDO class. Check out the Examples section there, but just to give you an idea:

Suppose before you had to write something like

$sql = "SELECT * FROM tmp_mysqli_helper_test WHERE id=?";
$db->prepare($sql);
$db->bind(1, $id);
$db->execute();
$row = $db->results();

With this helper function you can have almost the same but simpler:

$sql = "SELECT * FROM tmp_mysqli_helper_test WHERE id=?";
$row = prepared_query($conn, $sql, [$id])->get_result()->fetch_assoc();