Log in

No account? Create an account
Oracle, PHP, and references. (Oh My!) - Chaz Meyers [entries|archive|friends|userinfo]
Chaz Meyers

[ website | chazmeyers.com ]
[ profile | view profile ]
[ archive | view archive ]

[Links:| chazmeyers.com Twitter ]

Oracle, PHP, and references. (Oh My!) [Nov. 2nd, 2007|04:32 pm]
Chaz Meyers
I'm pretty sure I stumbled into this problem twice already, so this time I'm going to write about it in hopes of committing this to memory.

Most databases let you bind variables. If not, the library you use to connect to your database might do it for you. Binding means you say something like:

$sth = prepare("SELECT * FROM foo WHERE col=:val"); $result = execute($sth, ["val" => "Some value"]);

"val" gets automatically escaped for you, you are less vulnerable to SQL injection attacks, and life is good.

If you were writing a generalized PHP database library for Oracle on top of the oci_* API, you might in inclined to write something like:

 foreach( $binds as $name => $value ) { 
    oci_bind_by_name($sth, $name, $value); 

However, you would be wrong to do so. $value is passed by reference, not by value. When you're in a foreach loop, the address of $value is the same each time. So if your $binds look like:
["first_name" => "John", "last_name" => "Doe"]

The oracle library is going to think it got:
["first_name" => "Doe", "last_name" => "Doe"]

Because of this, I got ORA-01460 errors, but you might get entirely different errors!

A safer way to accomplish this goal:
 foreach( $binds as $name => $value ) { 
    oci_bind_by_name($sth, $name, $binds[$name]); 

As long as you don't change your $binds array between when you bind and execute, that should be safe.