I have a function that return a string (with the database credentials), this string called $conn_db is like this:
host= localhost ;username= root ;password= 123456 ;database= test ;
now in my function for establish a database connection if I pass the value like so:
mysqli_connect($host, $username, $password, $dbname)
all working good but. If I pass the connection string only:
mysqli_connect($conn_db)
an exception is returned in the:
if (mysqli_connect_errno())
{
throw new Exception("Can't establish db connection");
}
isn't possible use a connection string instead of 4 variables in mysqli_connect?
Not possible. mysqli_connect() expects multiple arguments. When you do mysqli_connect($db_conn), you're passing ONE argument. The mysqli library, and underlying mysql driver, are NOT going to parse that string to try and extract whatever other parameters are necessary. You can't embed multiple values in a single argument either, and expect that to make sense.
Since you only provide $db_conn, that's what MySQL will try to use as the hostname (argument #1), and try to do a DNS lookup on some nonsensical "username=foo&password=bar"-type hostname, which will obviously fail.
If you want to use a single string/argument, then switch to PDO. Its constructor allows for such things.
Related
Connection file is as below
$host="localhost";
$username="root";
$password="123";
$database = "order";
$con = mysqli_connect($host, $username, $password, $database);
$sel_db=mysqli_select_db($con,$database) or die("Cannot Select Database");
In each file I include above connection file
My older code for mysql is like
mysql_query("select * from order_detail");
and new query for mysqli is as below
mysqli_query($con,"select * from order_detail");
Above query required $con for connection
and mysql_fetch_array($var) becomes mysqli_fetch_array($var) it does not required $con
mysql_real_escape_string($var) becomes mysql_real_escape_string($con,$var);
So my question is that which query required $con as connection
The mysql functions implicitly used the last connection that was made if no connection was explicitly given. Note that you already could pass in a connection, even to the old function as you can read here. This behavior is confusing and error prone, so fortunately they made that more explicit in the mysqli functions.
I'm not sure that is the main reason though. It probably might have more to do with the fact that mysqli also has an object syntax, and that one syntax wraps another. The $con variable in the procedural version and the object instance in the objective version both serve the same purpose: telling the function/method which connection to use. Actually, the doc says that the connection parameter for mysqli_query is a mysqli object instance, so mysqli_query might just be implemented like this as a wrapper function to make it easier to convert your code from mysql to mysqli:
function mysqli_query($link, $query, $resultmode = MYSQLI_STORE_RESULT) {
return $link->query($query, $resultmode);
}
If you didn't understand anything I said in this last paragraph, don't worry, it's not really important. ;)
Anyway, while mysql_query performs a query on a connection, mysql_fetch_array fetches values from a query result. The $var your pass to it already contains all the information it needs. It doesn't need a connection at that point, so there is no need to pass it as an argument. There is no mysqli_fetch_array by the way. Instead you should use mysqli_stmt_fetch, to which the same applies: it doesn't need a connection, but a statement object (mysqli_stmt), which represents the query result.
Many of the mysqli functions have the same or similar parameters as their predecessors, but there may be differences. So for every function you use, I'd check the official documentation.
And also, I'd use an IDE or editor that will help you with the function syntax by providing built in code insight. Netbeans for PHP is a quite elaborate one that can be used for free, but there are even better ones (like PHPStorm) if you can spend some money.
PS: If you use prepared statements, you can get rid of mysql_real_escape_string completely.
Code:
echo pg_escape_bytea(45);
Result:
45
Code:
pg_connect ("host=$host dbname=$db user=$user password=$pass");
echo pg_escape_bytea(45);
Result:
\x3435
I don't want to change the result. How can I do that?
Please help!
SHORT ANSWER:
Never call the pg_escape_bytea function before pg_connect.
LONG ANSWER:
The pg_escape_bytea function is charset-aware function.
Function definition:
pg_escape_bytea ([ resource $connection ], string $data ) : string
As you can see from the funnction definition, you can pass a $connection as the first parameter. You can obtain this connection as a result from the pg_connect or pg_pconnect functions. However, I don't know how to obtain this "connection resource" from a PDO object.
Every connection has a charset associated with it. So when you pass a connection as the first parameter to pg_escape_bytea it will "read" the associated charset and encode the result accordingly.
If you don't pass the connection as the first parameter, then the pg_escape_bytea function will simply use the latest PostgreSQL connection.
And here is the problem:
If you call the pg_escape_bytea before you connect to your PostgreSQL database (using pg_connect or pg_pconnect or PDO ...) then the pg_escape_bytea function WILL NOT KNOW how to encode the result!
If you connect to your database and then call the pg_escape_bytea function with the exactly same input data it may return different output because the charset of the latest PostgreSQL connection changed!
SOLUTION:
So I think the easiest workaround is simply to never call the pg_escape_bytea function before pg_connect function (or other "connect" functions / PDO) because it will simply doesn't know how to encode the result properly.
PS: If you want to experiment with different outputs, you can change the charset like this:
$pdo->query("SET NAMES UTF8")
From the manual:
When you SELECT a bytea type, PostgreSQL returns octal byte values
prefixed with '\' (e.g. \032). Users are supposed to convert back to
binary format manually.
So after the connection is made, you need to deal with it manually.
I have marked many of developers using
$con1 = mysql_connect('localhost', 'username', 'password');
$rv1 = mysql_select_db('db1'); // not added connection
Instead
$con1 = mysql_connect('localhost', 'username', 'password');
$rv1 = mysql_select_db('db1', $con1); // added connection
Can I know the difference between this both?
Actually this both are giving same result
The mysql_ functions will implicitly use the last connection which was opened with mysql_connect, if you do not pass an explicit connection parameter. So, yes, in this case it's the same result whether you pass the parameter or not. You will get different results should you happen to open more than one connection using mysql_connect.
Note that implicitly relying on an open connection is bad practice, precisely because your application will screw up if you need to open more connections sometime later. Also note that the mysql_ API is dead, switch to mysqli or PDO.
Take a look at the PHP manual:
http://www.php.net/manual/en/function.mysql-select-db.php
Without a link identifier, mysql_select_db will use the last connection opened with mysql_connect or it will try to connect without any parameter. So the second one is safer and you could use multiple connections.
mysql_select_db and mysql_connect is deprecated though. You should switch to PDO or mysqli.
Taken from the documentation:
bool mysql_select_db ( string $database_name [, resource $link_identifier = NULL ] )
link_identifier
The MySQL connection. If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If no connection is found or established, an E_WARNING level error is generated.
Basically it will used the last known connection object if none is provided. In your case, the last known connection was created on the previous line. This is an optional parameter so the function will operate in the same way if the connection is passed explicitly or not.
On a related note, please notice the big red warning at the top of the documentation page I have linked to. The mysql_* extensions are deprecated and it is recommended that you use a different extension. For a more detailed explanation, please take a look at this thread:
Why shouldn't I use mysql_* functions in PHP?
In every blog/article/Q&A I have read, nobody suggested to check the value returned by mysql_real_escape_string().
The way I see it, this check is very important to ensure data consistency, because if this function fails, the value inserted in the database would be a false possitive: a boolean FALSE type-casted as string, resulting an empty string, not what you would expect.
According to the documentation:
Returns the escaped string, or FALSE on error.
A MySQL connection is required before using mysql_real_escape_string() otherwise an error of level E_WARNING is generated, and FALSE is returned. If link_identifier isn't defined, the last MySQL connection is used.
The warning is good if you go in the logs to see what was happened, but would not prevent it from happening.
I know that there are very little changes to fail, but if there is at least one change it should be expected by your application.
This function will fail if:
developer did not connect to the database before calling this function
the connection to the database failed before calling this function
the memory of the server (where mysql client resides) is low and cannot copy the string for escaping
...
This is an exemple of "normal" usage:
$db = mysql_connect() or die('Cannot connect to database');
$value = mysql_real_escape_string($_POST['value'], $db);
mysql_query('insert into tablex (value) values ("'.$value.'")', $db) or die('Cannot insert data in database');
I am using something like this (in am OO wrapper for mysql):
class mywrapper{
// ... [code ...]
// $this->db is the mysql link identifier
public function escape($string)
{
if(mysql_real_escape_string($string, $this->db) === false)
{
throw new Exception('Some message');
}
}
} // end class
// I'm calling it as
// $myWrapper->insert('insert into tablex (value) values ("'.($myWrapper->escape($value)).'")');
This will throw an exception that will be capture by the exception handler, and most important I prevented the insertion of false positive values in the database, ensuring data consistency.
I am missing something ? I am playing safe or I am beeing paranoic ? :)
In a sense you are missing something as it's no longer recommended to use the mysql_ family of functions. Instead use mysqli or PDO. Both of these provide parameterised queries which will automatically escape your input data for you.
No, I don't think you're being paranoid. (or we're both paranoid)
I do think too that it's definitely a good practice to avoid sending nothing in a mysql query (pretty much as you wouldn't want to send a nothing valued $_POST variable).
I noted the problems you mentioned:
This is an exemple of "normal" usage:
$db = mysql_connect();
Well, at this point you should definitely check that the connection succeeded.. Also, with a good database abstraction layer you can prevent that the user "forgot" to connect to the database (because he never has to do that manually). (1).
If you lose connection in the meantime, then your query will fail, so it doesn't matter what you've sent (2).
mysql_real_escape_string is done at client side, so memory usage of mysql server is not an issue (3).
When I connect to a MySQL database using PDO, the way I need to connect is:
$pdoConnection = new PDO("mysql:host=hostname;dbname=databasename",user,password);
But, for PostgreSQL, the DSN is more standard (IMO):
$pdoConnection = new PDO("pgsql:host=hostname;dbname=databasename;user=username;password=thepassword");
Is there any reason why MySQL cannot use a single string? Or is this just because of the versions I am using (PHP 5.2, MySQL 5.0, PostgreSQL 8.1)?
As the person that implemented both, I can tell you that the reason is that by passing the string through as-is to postgres (and ODBC) the PDO driver code for those databases does not need to be updated as the underlying library adds new features.
Since MySQL does not have its own connection string parsing code, we invented a mechanism for passing data in to the underlying MySQL function calls, which have a very specific API with fixed parameters.
No accident; it's very deliberate.
This has been resolved in PHP 7.4, as can be seen in the new features.
I have confirmed it locally that we can write:
$dbh = new PDO('mysql:host=localhost;dbname=my_db;charset=utf8mb4;user=root;password=')
Yep, this API inconsistency is a major annoyance.
As a work-around, I pack the actual DSN string with an optional username and password using query-string syntax - then parse and construct like this:
parse_str($connection_string, $params);
$pdo = new PDO($params['dsn'], #$params['username'], #$params['password']);
So for PostgreSQL, use a $connection_string like:
dsn=pgsql:host=localhost;dbname=test;user=root;password=root
And for MySQL, use a string like:
dsn=mysql:host=localhost;dbname=testdb&username=root&password=root
Kind of lame, but it's simple and it works.
This question is more than 10 years old, but I still end up here every time I create a new project that uses PDO... I'm writing my solution here so that I can save myself the trouble next time :P
class MyPDO extends PDO {
public function __construct($dsn, $options = null) {
$user=null;
$pass=null;
if (preg_match("/user=([^;]*)/", $dsn, $matches)) {
$user=$matches[1];
}
if (preg_match("/password=([^;]*)/", $dsn, $matches)) {
$pass=$matches[1];
}
parent::__construct($dsn, $user, $pass, $options);
}
}