As I know PDO support has been added to codeigniter recently but I can't find any documentation or tutorial about how to actually use it. Can anyone tell how can I use it?
You can edit /application/config/database.php and to enable the PDO driver:
$db['default']['hostname'] = 'pgsql:localhost';
// or mysql:localhost
// or sqlite::memory:
$db['default']['dbdriver'] = 'pdo';
If you want to directly get you hand on the active DB connection. This might work, but I am not CI developer .. so no guarantees. I tried to understand that brain rotting code, but i suspect, that i failed. I'm not good at PHP4 + eval():
$CI = get_instance();
var_dump($CI->db->conn_id);
// should show that conn_id is instance of PDO
Well, since CodeIgniter is merely a PHP framework, nothing prevents you from using it natively, as in $pdo = new PDO(...);.
However, when they say PDO is now supported, I think they mean their normal Database class now uses PDO (rather than MySQLi or the such).
Related
php is about to stop support for mysql functions, and there are lots of tools/recommendations for how to upgrade to upgrade to mysqli from mysql. I came up with this design, and I wonder if there are any issues that my solutions can have:
Create a file called translate.php and require_once it in all php files that use any mysql functions.
Create global variable in that file and call it $_CONN
overwrite default mysql function with the following (using overwrite_function which is not shown here)
$_CONN;
mysql_query($q)
{mysqli_query($_CONN,$q);}
mysql_error()
{mysqli_error($_CONN);}
mysql_connect($h,$u,$p)
{$_CONN=mysqli_connect($h,$u,$p);}
mysql_fetch_assoc($r)
{mysqli_fetch_assoc($r);}
mysql_fetch_array($r)
{mysqli_fetch_array($r);}
Are there any issues with my solution?
To move from mysql to mysqli in a painless way you have to move towards PDO
I have developed a project under which several sql query have been used. Now I want to monitor some query in order increase security. So I want every query to be passed through a function first. As there are too many queries so I can not go back and edit every file and query. Is there a way that I can trap into queries before they are sent to mysql server?
There are four ways to accomplish this depending on what you are using, the last being the much more reliable.
The General Query Log
MySQL provides a mechanism to log just about everything that the mysqld process is doing, via the general query log. As you described in your question you probably do not have persistent connections, so you will need to either:
Enable the MySQL general query log when the mysqld process is started, with the --log[=file_name]
Set a global/session variable with SET GLOBAL general_log = 'ON'.
Fore more information about the general query log, see the MySQL 5.1 reference manual.
Using sed (or manually!)
This technique involves creating a a new function, and renaming all of the mysqli_* function calls to call another function.
Presuming your newly created function is named proxy_query(), you can use sed to traverse through all files and change them automatically:
sed i '.bck' 's/mysqli_query/proxy_query/'
The -i paramater specifies that the file should be edited in place, and that a copy should be made of the original file and have a .bck extension appended.
The runkit extension
I must admit that I'm being naive here, and that I haven't used this particular extension before - but it is possible to rename functions with this PECL extension.
The requirements for this extension can be found here, and note that it is not bundled with PHP.
As with above, you can create a proxy function where all calls will go through. Let's assume it's also called proxy_query. Usage would go something like this:
// rename the function (a very bad idea, really!)
runkit_function_renam('mysqli_connect', 'proxy_super');
function mysqli_query($query, $resultmode = MYSQLI_STORE_RESULT)
{
// do something with the SQL in $query
// .. and call mysqli_query, now proxy_super
return proxy_super($query, $resultmode);
}
I have to note here that this method is highly discouraged. You shouldn't ever need to set default PHP functions.
Using Pdo/OO-mysqli
This is the simplest technique, and probably the most reliable as well. If you're using Pdo already, you can simply extend the \Pdo class. A similar approach could be used with MySQL Improved(mysqli):
class MyPdo extends \Pdo
{
public function query($query [, ... ])
{
// do something with $query
return parent::query($query [, ... ]);
}
}
Also note here, that this will only work if you are using Pdo, and if you are able to change the instantiation of the Pdo object, to overwrite it to your own class: MyPdo.
For more information about the \Pdo class, and it's children, see the manual.
If you want to monitor incoming queries using SQL profiler can be an excellent way to gather information on what's going on inside SQL without passing it all through a single function or procedure.
I'm using PDO to access two SQLite 3 databases in PHP. I want to switch the database files during a query by renaming them but I can't do that while the files are open as it gives an error that the file is being used by another process. I've tried turning off persistent connections and setting the handles to null but neither work.
Is there really no way to close a PDO handle and release the lock on the database file?
I believe unset($var) does that, I use it on my pdo sqlite project and it works like I want it to :)
Set all references to the handle to null (or to anything except the PDO object, really) and the runtime will destruct the object, which will close the connection.
$db = new PDO('...');
// Do some stuff
$db = null;
// Assuming this was the last reference to that PDO
// object, the runtime will destroy the object and
// its connection.
The SQLite3 Class has an option like this.
$db = new SQLite3('mysqlitedb.db', SQLITE3_OPEN_READONLY);
In PDO you would simply open with:
$db = new PDO('sqlite:mysqlitedb.db');
My question is however, is there a way to open a database with PDO, in READONLY mode?
This will become possible with the release of PHP 7.3 (estimated for release in late 2018).
The syntax is as follows:
$db = new PDO('sqlite:mysqlitedb.db', null, null, [PDO::SQLITE_ATTR_OPEN_FLAGS => PDO::SQLITE_OPEN_READONLY]);
Upstream commit
I don't think that's possible with pdo (yet?).
The pdo_sqlite driver of php 5.3 uses sqlite3_open() in pdo_sqlite_handle_factory() but you need sqlite3_open_v2() to pass the read only flag.
edit:
But a patch would be fairly easy. Take a look at pdo_mysql_handle_factory() in ext/pdo_mysql/mysql_driver.c and how it uses struct pdo_data_src_parser vars[] to parse the dns string.
How can I detect, using php, if the machine has oracle (oci8 and/or pdo_oci) installed?
I'm working on a PHP project where some developers, such as myself, have it installed, but there's little need for the themers to have it. How can I write a quick function to use in the code so that my themers are able to work on the look of the site without having it crash on them?
if the oci extension isn't installed, then you'll get a fatal error with farside.myopenid.com's answer, you can use function_exists('oci_connect') or extension_loaded('oci8') (or whatever the extension's actually called)
The folks here have pieces of the solution, but let's roll it all into one solution.
For just a single instance of an oracle function, testing with function_exists() is good enough; but if the code is sprinkled throughout to OCI calls, it's going to be a huge pain in the ass to wrap every one in a function_exists() test.
Therefore, I think the simplest solution would be to create a file called nodatabase.php that might look something like this:
<?php
// nodatabase.php
// explicitly override database functions with empty stubs. Only include this file
// when you want to run the code without an actual database backend. Any database-
// related functions used in the codebase must be included below.
function oci_connect($user, $password, $db = '', $charset='UTF-8', $session_mode=null)
{
}
function oci_execute($statement, $mode=0)
{
}
// and so on...
Then, conditionally include this file if a global (say, THEME_TESTING) is defined just ahead of where the database code is called. Such an include might look like this:
// define("THEME_TESTING", true) // uncomment this line to disable database usage
if( defined(THEME_TESTING) )
include('nodatabase.php'); // override oracle API with stub functions for the artists.
Now, when you hand the project over to the artists, they simply need to make that one modification and they're good to go.
I dont know if I fully understand your question but a simple way would be to do this:
<?php
$connection = oci_connect('username', 'password', 'table');
if (!$connection) {
// no OCI connection.
}
?>
As mentioned above by Greg, programmatically you can use the function_exists() method. Don't forget you can also use the following to see all the environment specifics with your PHP install using the following:
<?php
phpinfo();
?>