Oracle PHP Troubleshooting
FAQ
By Christopher Jones
Updated April 2006
Here are some troubleshooting hints for users of
Oracle and PHP. For a general Oracle/PHP FAQ see The
Oracle/PHP FAQ by Frank Naudé.
If you use PHP's oci8 extension, I
strongly recommend upgrading to the re-factored version. Although
first shipped with PHP 5.1.2, the new code was designed to work with
PHP 4 onwards and is available as source code in PECL for use with
existing PHP installations. Windows binaries for various PHP versions
are at php_oci8.dll.
Topics
Oracle not
installed or not found
If Oracle support is enabled in PHP,
but the Oracle client libraries can not be found, you will
get an error when trying to start Apache. For example on
Windows if php.ini has "extension=php_oci8.dll" but the
Oracle home cannot be found, an alert "The dynamic link
library OCI.dll could not be found in the specified path" is
displayed.
Make sure that your php.ini file is being found correctly. Create the following script
"phpinfo.php" where your web server can read it and load it in a
browser:
<?php
phpinfo();
?>
If the "Configuration File (php.ini) Path" line shows only a
directory path and does not end
with "php.ini", then your configuration file is not being read.
Move your php.ini to the directory shown and restart your web server.
Make sure the Oracle environment
variables are set correctly before starting web server (see
the next topic).
Linux users might see an Apache error
about being unable to load libclntsh.so, but are more likely
to notice the problem earlier when compiling PHP. The
compiler will fail with the error 'Cannot find file
"ocidfn.h"' or 'Cannot find file "oci.h"'. If you have Oracle
installed but are missing the Oracle header files, do a
"Client" install of Oracle. In Oracle 9i download the
"Oracle9i Database Release 2", run the installer and choose
the "Client" option. In Oracle 10g download the "Oracle
Database 10g Client Release", run the installer and choose
the "Administrator" option.
The Oracle directory that PHP links with
needs to be readable by the owner of the web server process.
If you configure PHP to use Oracle 10gR2 libraries and Apache
crashes at startup, check the directory permissions on the Oracle
software. Oracle 10gR2 is shipped with a more restrictive set of
directory permissions than previous Oracle releases. The 10.2.0.2
patchset contains $ORACLE_HOME/install/changePerm.sh to re-set
permissions on files required by external programs like PHP. With
10.2.0.2 you may need to add the directories lib32, ldap, ldap/adminm,
and srvm/lib32 to the RELAX_DIR_ALL variable in this script before
running it. If you don't want to change your ORACLE_HOME permissions,
consider linking PHP with Oracle Instant Client.
Also see the OTN articles Installing PHP and the Oracle 10g Instant Client for Linux and Windows,
Installing Oracle, PHP, and Apache on Windows 2000/XP and
Installing Oracle, PHP, and Apache on Linux.
Setting Oracle
environment variables prior to starting the web server
Setting all Oracle environment
variables before the web server starts is the only safe way
to get PHP talking to Oracle. Setting the variables in PHP
scripts or the httpd.conf file mostly does not work. There
are numerous mail list and forum posts because of general
confusion about the environment. The behavior on Windows and
Linux also differs.
The environment needs to be set so PHP
can find Oracle's libraries and message files. Environment variables may
also be needed to identify the default local database, needed for
locating configuration files for remote database access, or needed to set Oracle's globalization parameters correctly.
An example shell script for starting
Apache is "start_apache" :
#!/bin/sh
ORACLE_HOME=/u01/app/oracle/product/9.2
ORACLE_SID=orcl
export ORACLE_HOME ORACLE_SID
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${LD_LIBRARY_PATH}
echo "Oracle Home: $ORACLE_HOME"
echo "Oracle SID: $ORACLE_SID"
echo Starting Apache
#export > /tmp/envvars
./apachectl start
Depending where your database server
is and how you connect to it you may also want to set TWO_TASK
or TNS_ADMIN (see the next topic).
Apache, PHP and Oracle error messages
that use phrases like "could not load" or "could not resolve" all
point to environment setup problems. If you think you are seeing this, try uncommenting the "export" line in
"start_apache". After the script is run, the file
/tmp/envvars will contain the environment variables Apache
knows about. This is useful to solve problems starting Apache
at machine boot time - the environment may be very different
to starting Apache in your user shell.
If Apache starts but gives
errors about Oracle libraries, and/or OCI8 function calls fail, try
looking at PHP's environment by using the phpinfo() script.
Triple-check the environment and path
configuration. On UNIX check that
LD_LIBRARY_PATH (or equivalent) contains $ORACLE_HOME/lib. On
Windows the PATH variable may need to contain
%ORACLE_HOME%\bin.
Some messages like the runtime "Warning: ocilogon():
_oci_open_session: OCIHandleAlloc? OCI_HTYPE_SVCCTX:
OCI_INVALID_HANDLE" are also symptoms of an incorrect
ORACLE_HOME.
If OCILogon() gives "ORA-12705 The NLS parameter
value specified in an alter session statement is not valid or
not implemented", try setting ORA_NLS33 to the NLS data file
directory in the ORACLE_HOME used to compile PHP, e.g.
$ORACLE_HOME/ocommon/nls/admin/data.
I did some tests to see what effect
the basic environment in a standard
installation had on a PHP login call:
$mycon = OCILogon("myusername", "mypassword", "MYDB");
I used Red Hat Linux AS 2.1, Apache
1.3 and PHP 4.3.3.
-
With no ORACLE_HOME set prior to
"apachectl start" and no
"putenv('ORACLE_HOME=/usr/oracle/MYDB')" in the PHP
script I got:
Warning: ocilogon(): _oci_open_server: Error while trying to retrieve text for error ORA-12154
This shows the connection failed,
and the message files (which are located under the Oracle
home directory) could not be found. The Oracle environment is incorrect.
-
With
"putenv('ORACLE_HOME=/usr/oracle/MYDB')" in the PHP
script but no ORACLE_HOME set, I got:
Warning: ocilogon(): _oci_open_server: ORA-12154: TNS:could not resolve service name
The connection still failed, but
now the correct message text could be read from the
message file. The Oracle environment is incorrect.
-
With ORACLE_HOME set prior to
"apachectl start" but without "putenv()" the connection
succeeded. This is the recommended configuration.
-
With ORACLE_HOME set correctly
prior to "apachectl start" and with "putenv()" using an
invalid ORACLE_HOME directory, the connection succeeded.
I also tried this on Windows. This time the connection
failed with the same message as my first test
above. Don't do this.
I had a similar set of results when I
replaced the PHP putenv() call with an Apache httpd.conf
directive "setenv ORACLE_HOME /usr/oracle/MYDB".
Having said all this, some variables used
at run time can be set in your PHP scripts. After setting ORACLE_HOME
correctly before starting Apache the following code changed my default
connection and connected to MYDB:
putenv("TWO_TASK=MYDB");
$mycon = OCILogon("myusername", "mypassword");
The environment variables TNS_ADMIN,
NLS_DATE_FORMAT (and there may be others) can probably be set in scripts
too.
Connecting to a
database
-
If Oracle 10g libraries are used
by PHP try the new Easy Connect syntax. No long connection string is needed. No tnsnames.ora
file is required. To connect to the MYDB database service
running on mymachine use:
$c = OCILogon('myusername', 'mypassword', '//mymachine.mydomain/MYDB');
If you are using the free Oracle XE database on the same machine as your web server, the connection string would be:
$c = OCILogon('myusername', 'mypassword', '//127.0.0.1/XE');
The Easy Connection syntax only works if
PHP is linked with Oracle 10g libraries, and works even if
the database is another version. If the database server
is 10g but PHP is using Oracle 8i or 9i libraries it will not
work. See Oracle's
Using the Easy Connect Naming Method documentation
for the Easy Connect syntax.
If you see the error "ORA-12514: TNS:listener does not
currently know of service requested in connect descriptor", then the
service name component is incorrect. On the database server, run
lsnrctl services
to find the service names that will be recognized.
The ORA-12514 error may occur in the scenarios below too.
-
A user chosen net service name is
often used to identify which database to connect to. By
default it is read from the environment variable
ORACLE_SID or it can be explicitly given in the
connection call. The net service name MYDB that is used
in Oracle's command-line SQL*Plus utility like:
sqlplus myusername/mypassword@MYDB
can be used in PHP like:
$mycon = OCILogon("myusername", "mypassword", "MYDB");
The net service name is commonly
mapped to an actual database by an entry in a
tnsnames.ora file :
MYDB =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.mydomain)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = MYDB)
)
)
The default file location is
$ORACLE_HOME/network/admin/tnsnames.ora. On some
operating systems other locations (e.g.
~/.tnsnames.ora) will be checked too. If your tnsnames.ora is in a non-standard
location you can set the environment variable TNS_ADMIN
to the directory containing it. For example if you are
using /home/myuser/tnsnames.ora, add these lines to
start_apache (see the previous topic):
TNS_ADMIN=/home/myuser
export TNS_ADMIN
If the net service name used in
OCILogon() cannot be found in the tnsnames.ora, or the
tnsnames.ora is not found at all by PHP, you may get an
error when logging in:
Warning: ocilogon(): _oci_open_server: ORA-12154: TNS:could not resolve service name
The error ORA-12154 can also occur
if you have a file $ORACLE_HOME/network/admin/sqlnet.ora
and it specifies a NAMES.DEFAULT_DOMAIN value.
Unqualified net service names in OCILogon() calls will
have sqlnet.ora's value for NAMES.DEFAULT_DOMAIN appended
to the alias. For example if sqlnet.ora had:
NAMES.DEFAULT_DOMAIN = au.oracle.com
then 'OCILogon("myusername",
"mypassword", "mydb")' causes Oracle to look for the
alias "MYDB.AU.ORACLE.COM = . . ." in tnsnames.ora. A
quick solution is to change the tnsnames.ora entry
to:
MYDB.AU.ORACLE.COM =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.mydomain)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = MYDB)
)
)
-
If Easy Connect has been disabled
or you are using Oracle 8i or 9i libraries, another
alternative is to use the full connection string:
$db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
(HOST = mymachine.mydomain)(PORT=1521))
(CONNECT_DATA=(SERVER=DEDICATED)
(SERVICE_NAME=MYDB)))";
$mycon = OCILogon("myusername", "mypassword", $db);
Managing
Connections
Connection management was greatly improved with the re-factored
oci8 driver. Many bugs were fixed and there are new php.ini options
for optimizing the behavior of persistent connections. Optimizing database connections in a
frequently used script can improve performance and prevent resource
problems.
If you are using the original oci8 extension these tips may still apply:
-
Avoid multiple connections to
Oracle in a single script.
-
If you have to make multiple
connections use different tnsnames.ora aliases, even when
you want to connect to the same Oracle instance with a
different user. This will avoid PHP context conflicts
since each connection will use a distinct TCP link to the
database.
-
Using the "persistent" OCIPLogon()
call minimizes the number of physical connection requests to the
database.
It has some limitations. If the DBA terminates the
session with ALTER SYSTEM KILL SESSION or worse,
terminates the Oracle shadow process with an operating
system kill command, OCIPLogon() may succeed but
subsequent OCI8 calls may still fail. This can be timing
dependent. When reusing a persistent connection always
check its validity at the start of the script with an
explicit query. If you receive an Oracle error then the
connection is no longer valid and you may need to logoff
and login again. Some developers give the user a message
asking them to retry later and call PHP's
apache_child_terminate() to clean up the session.
-
Use Oracle Database Resource
Manager (which replaces User Profiles) to limit the
resources used by any one connection.
-
Use Oracle Net configuration
parameters such as
SQLNET.EXPIRE_TIME to free up unused database
resources.
-
Refresh the Apache processes after
they have managed a certain number of requests, depending
on site load. An Apache "graceful restart" nightly will
clean up connections.
[Acknowledgment: Massimo Squillace
contributed significantly to this section]
Echoing SQL statements
to check they are well formed
Getting no, or incorrect, results is
surprisingly often due to executing the wrong statement.
During development, echo each complete SQL statement from PHP
to check it is well formed and all variables are correctly
expanded. Quoting errors or misunderstandings with PHP's
variable syntax in strings can cause incorrect statements to
be executed.
Testing SQL statements in SQL*Plus
before executing them in PHP also helps confirm
correctness.
When statements are entered in tools
like SQL*Plus, a semi-colon is often used to tell the tool
that the statement is complete and can now be executed.
However the semi-colon is not considered part of the
statement and is not sent to the database. In PHP do not add
a semi-colon to a SQL statement otherwise an Oracle error
will occur. This example is a valid query:
$sql = "SELECT * FROM EMP_DETAILS_VIEW";
Oracle's inbuilt scripting language
PL/SQL has different syntax to SQL and a final semi-colon is
required:
$plsql = "BEGIN DBMS_OUTPUT.PUT_LINE('Hello, World!'); END;";
Testing return
codes from database function calls
Test all return values from OCI8
functions to prevent hidden problems and misleading
results.
During development set php.ini's
error_reporting directive to
error_reporting = E_ALL | E_STRICT.
Set
display_errors On, or configure the error log file (and
remember to check it!). This will show Oracle errors as they
occur, unless you have explicitly prefixed Oracle functions
calls with
"@".
Inserting strings
containing quotes
Inserting strings containing single
quotes can be handled in several ways:
-
Use bind variables. This also
protects against "SQL Injection" security issues and can greatly improve database performance:
$name = "O'Reilly";
$stmt = 'INSERT INTO CUSTOMERS (NAME) VALUES (:nm)';
$stid = OCIParse($mycon, $stmt);
OCIBindByName($stid, ':nm', $name, -1);
OCIExecute($stid);
This is the recommended
method. It is also the least likely to cause coding errors.
-
Double every single quote:
$name = "O'Reilly";
$name = str_replace("'", "''", $name);
$stmt = "INSERT INTO CUSTOMERS (NAME) VALUES ('".$name."')";
-
Turn on
magic_quotes_sybase in php.ini and use
addslashes():
$name = addslashes("O'Reilly");
$stmt = "INSERT INTO CUSTOMERS (NAME) VALUES ('".$name."')";
This is not recommended for
portability reasons.
Fetching
results using associative arrays
Oracle column names are cases
insensitive by default but when fetching into associative
arrays specify the names in upper case:
$query = 'select dname from dept';
$stid = OCIParse($conn, $query);
OCIExecute($stid);
while (OCIFetchInto($stid, $row, OCI_ASSOC)) {
echo $row['DNAME']."<br>\n";
}
If the table was created with case
sensitive column names this may not be true. Use
var_dump($row) to see the column names and data structure
actually returned by OCIFetchInto(). PHP has an
array_change_key_case() function to change the case of
array keys if needed.
Table name prefixes are not included
in associative array keys. If a column name is used more than
once in a query, use column aliases to distinguish the
columns. Otherwise there will only be one associative array
entry. If the aliases T1N and T2N were not used in the
example below, only results from one of the NAME columns
would be returned:
$query = 'select myt1.name as t1n, myt2.name as t2n from myt1, myt2';
$stid = OCIParse($conn, $query);
OCIExecute($stid);
while (OCIFetchInto($stid, $row, OCI_ASSOC)) {
echo $row['T1N']." ".$row['T2N']."<br>\n";
}
Pre-fetching in
PHP to improve performance
There is no array fetch capability in
PHP to return multiple rows in one operation and thus reduce network traffic, but setting the prefetch row count with OCISetPrefetch()
is effectively the same. It can dramatically improve
performance. The
advantage of setting the prefetch row count instead of adjusting
an array fetch size is that Oracle does the caching for you. Your data
structures only have to handle one row at a time and your
code can be simpler.
An example that sets the prefetch row
count to 100 is:
<?php
$conn = OCILogon('myusername', 'mypassword', 'mydb');
$query = 'SELECT * FROM EMP_DETAILS_VIEW';
$stid = OCIParse($conn, $query);
OCIExecute($stid);
OCISetPrefetch($stid, 100);
while ($succ = OCIFetchInto($stid, $row)) {
foreach ($row as $item) {
echo $item." ";
}
echo "<br>\n";
}
OCILogoff($conn);
?>
With the re-factored oci8 extension you
can set the oci8.default_prefetch php.ini parameter to a suitable
average value for your applications. By default the number of rows
prefetched is 10. You can also tune statement caching with
oci8.statement_cache_size to improve performance.
Using Oracle bind
variables in PHP
Bind variables are strongly
recommended because they help database performance and can improve application security.
-
Problems with binding are often
caused because the data value needs to be accessible at
the time when OCIExecute() is called, not just when
OCIBindByName() is executed.
If OCIBindByName() is called
inside a wrapper function or method and the PHP variable
passed to OCIBindByName() is local to the wrapper
function there may be a problem. The variable needs to be
in scope when OCIExecute() is later called. Otherwise an
Oracle error such as "OCIStmtExecute: ORA-01460:
unimplemented or unreasonable conversion requested" may
occur or, confusingly, it can appear as if no value was
set for an "OUT" variable.
The sample below is a variation on
this. The variable "$val" is local to the "foreach"
command. The code returns no records:
<?php
$qs = 'SELECT * FROM DEPARTMENTS WHERE DEPARTMENT_NAME = :dname AND LOCATION_ID = :loc';
$dn = 'IT Support';
$lc = '1700';
$ba = array(':dname' => $dn, ':loc' => $lc);
$conn = OCILogon('myusername', 'mypassword', 'mydb');
$stmt = OCIParse($conn, $qs);
foreach ($ba as $key => $val)
{
OCIBindByName($stmt, $key, $val, -1);
}
OCIExecute($stmt);
while ($succ = OCIFetchInto($stmt, $o)) {
foreach ($o as $mv) {
echo $mv." ";
}
echo "<br>\n";
}
?>
Changing the OCIBindByName() call
fixes the problem:
. . .
foreach ($ba as $key => $val)
{
OCIBindByName($stmt, $key, $ba[$key], -1);
}
. . .
-
PHP numbers are converted to and
from strings when they are bound. This means the length parameter
must generally be given to OCIBindByName()
when returning a numeric data value in a bind variable. The
length is the number of digits that will be returned.
-
Don't pass variables to OCIBindByName() by reference. This is obsolete PHP
syntax and can cause problems. Sometimes you see this in older
articles or documentation.
OCIBindByName($stmt, ":mybindvar", &$val, 12);
If you have set the E_STRICT error reporting level, then you will get an error if you attempt this.
Uploading LOBS
Here is an example script that uploads a
JPG image into a BLOB column is. It uses PHP5 function names:
<?php
// Sample form to upload and insert an image into an ORACLE BLOB
// column using PHP5's OCI8 API.
//
// Before running this script, execute these statements in SQL*Plus:
// drop table btab;
// create table btab (blobid number, blobdata blob);
//
// This example uploads an JPG file and inserts it into a BLOB
// column. The image is retrieved back from the column and displayed.
// Make sure there is no whitespace before "<?php" else the wrong HTTP
// header will be sent and the image won't display properly.
//
// Based on a sample originally found in
// http://www.php.net/manual/en/function.ocinewdescriptor.php
$myblobid = 1; // should really be a unique id e.g. a sequence number
define("ORA_CON_UN", "hr"); // username
define("ORA_CON_PW", "hr"); // password
define("ORA_CON_DB", "//localhost/XE"); // connection string
if (!isset($_FILES['lob_upload'])) {
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST"
enctype="multipart/form-data">
Image filename: <input type="file" name="lob_upload">
<input type="submit" value="Upload">
</form>
<?php
}
else {
$conn = oci_connect(ORA_CON_UN, ORA_CON_PW, ORA_CON_DB);
// Delete any existing BLOB so the query at the bottom
// displays the new data
$query = 'DELETE FROM BTAB WHERE BLOBID = :MYBLOBID';
$stmt = oci_parse ($conn, $query);
oci_bind_by_name($stmt, ':MYBLOBID', $myblobid);
$e = oci_execute($stmt, OCI_COMMIT_ON_SUCCESS);
if (!$e) {
die;
}
oci_free_statement($stmt);
// Insert the BLOB from PHP's tempory upload area
$lob = oci_new_descriptor($conn, OCI_D_LOB);
$stmt = oci_parse($conn, 'INSERT INTO BTAB (BLOBID, BLOBDATA) '
.'VALUES(:MYBLOBID, EMPTY_BLOB()) RETURNING BLOBDATA INTO :BLOBDATA');
oci_bind_by_name($stmt, ':MYBLOBID', $myblobid);
oci_bind_by_name($stmt, ':BLOBDATA', $lob, -1, OCI_B_BLOB);
oci_execute($stmt, OCI_DEFAULT);
// The function $lob->savefile(...) reads from the uploaded file.
// If the data was already in a PHP variable $myv, the
// $lob->save($myv) function could be used instead.
if ($lob->savefile($_FILES['lob_upload']['tmp_name'])) {
oci_commit($conn);
}
else {
echo "Couldn't upload Blob\n";
}
$lob->free();
oci_free_statement($stmt);
// Now query the uploaded BLOB and display it
$query = 'SELECT BLOBDATA FROM BTAB WHERE BLOBID = :MYBLOBID';
$stmt = oci_parse ($conn, $query);
oci_bind_by_name($stmt, ':MYBLOBID', $myblobid);
oci_execute($stmt, OCI_DEFAULT);
$arr = oci_fetch_assoc($stmt);
$result = $arr['BLOBDATA']->load();
// If any text (or whitespace!) is printed before this header is sent,
// the text won't be displayed and the image won't display properly.
// Comment out this line to see the text and debug such a problem.
header("Content-type: image/JPEG");
echo $result;
oci_free_statement($stmt);
oci_close($conn); // log off
}
?>
Watch out for size limitations either
in the HTML script:
<input type="hidden" name="MAX_FILE_SIZE" value="3000">
or in the LimitRequestBody directive
in httpd.conf, or in php.ini's upload_max_filesize directive.
Upgrading to PHP
5
-
The OCI8 extension function names were standardized
in PHP 5. Most
changes were the addition of underscores, for
example OCIBindByName() is now oci_bind_by_name(). A
couple of function names are very different e.g. OCILogoff()
is now an alias for the new oci_close(). The biggest changes were
to data fetching functions. Refer to the manual for their new syntax.
Both old and new names
can be used so your scripts do not need to be recoded. The OCI8
Documentation has entries for old and
new names. User contributed comments for the same
functionality may be under either one.
This FAQ mostly uses the old function
names so examples work with PHP 4 and PHP 5.
-
Another name that has changed in
PHP 5 on Windows is the name of the directory containing
the extension DLLs. If starting the web server gives you
the error "Unable to load dynamic library
'c:\PHP\extension\php_oci8.dll'" edit your php.ini file
and change the value of the "extension_dir" directive
from "extension" to "ext".
-
If you are upgrading to PHP 5.1.2 onwards and using the
re-factored oci8 extension for the first time, check the documentation
on the new oci8 php.ini directives. In particular check
oci.old_oci_close_semantics. In the re-factored extension the
OCILogoff()/oci_close() function will actually close a connection
unless the directive is set. Previously the call was a no-op.
Oracle error
messages in PEAR DB
The PEAR DB
interface is a database abstraction layer that uses the same
syntax for different database brands. The standard PEAR DB
error function $db->getMessage() returns a simple PEAR
error description. For example if connection fails for any
reason, the message is always:
DB Error: connect failed
You can get the exact Oracle error
number and message by using:
$db->getDebugInfo()
It includes the Oracle error and the
complete statement like:
[nativecode=ORA-01017: invalid username/password; logon denied ] ** oci8://myusername:wrongpassword@mydb
The Oracle message text can be
extracted from this string with a wrapper function. An
example is:
require_once('DB.php');
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'PrintOCIError');
// Display PEAR DB error
function PrintOCIError($e)
{
if (is_object($e)) {
$s = preg_match('/.*\[nativecode=(.*)/', $e->getDebugInfo(), $r);
$etxt = $s ? $r[1] : $e->getDebugInfo();
}
else {
$etxt = "Unknown Error";
}
echo "<p><b>Error</b>:</p>\n<pre>" .
htmlspecialchars($etxt)."</pre>\n";
}
$db = DB::connect("oci8://myusername:wrongpassword@mydb");
if (!DB::isError($db)) {
.
.
.
}
The output from PrintPEARDBError()
is:
Error:
ORA-01017: invalid username/password; logon denied
Operating system authentication
Allowing externally authenticated
database connections (where the
username is "/" and the password an empty string) over the web
would be a potential
security risk for most configurations. Luckily PHP's OCI8
extension will not allow external authentication. The call in
PHP's oci8.c to Oracle's OCISessionBegin() always sets the
credential flag to OCI_CRED_RDBMS. To support operating system
authentication the PHP source code would have to be changed
to pass Oracle the OCI_CRED_EXT flag when appropriate.
Authentication
with AS SYSDBA or AS SYSOPER
It is possible to connect AS
SYSDBA or AS SYSOPER in PHP only with the re-factored oci8
extension. The oci8.privileged_connect parameter must also first be
set On. Connection can be made with:
$c = oci_connect("/", "", null, null, OCI_SYSDBA);
I don't recommend you allow this in external
sites as it removes a layer of security. If anyone can execute
arbitrary oci_connect() commands they may be able to gain privileged
access to your database. It is most likely to be useful when PHP is used as a command-line script language.
NCHAR and NCLOB
support in PHP
There is no NCHAR or NCLOB support in
the OCI8 extension.
The current PHP implementations of
oci8.c always use SQLCS_IMPLICIT for the character set form
when it calls Oracle's OCI. The character set form would need
to be SQLCS_NCHAR to support NCHAR and NCLOB, and other data
handling changes may be needed in PHP's code.
Getting More Help
If you have questions or problems using
Oracle and PHP, post details to the PHP
Discussion Forum on OTN.
|