PHP 8.4.2 Released!

oci_connect

(PHP 5, PHP 7, PHP 8, PECL OCI8 >= 1.1.0)

oci_connectConnect to an Oracle database

Descrição

oci_connect(
    string $username,
    string $password,
    ?string $connection_string = null,
    string $encoding = "",
    int $session_mode = OCI_DEFAULT
): resource|false

Returns a connection identifier needed for most other OCI8 operations.

For performance, most applications should use persistent connections with oci_pconnect() instead of oci_connect(). See Connection Handling for general information on connection management and connection pooling.

The second and subsequent calls to oci_connect() with the same parameters will return the connection handle returned from the first call. This means that transactions in one handle are also in the other handles, because they use the same underlying database connection. If two handles need to be transactionally isolated from each other, use oci_new_connect() instead.

Parâmetros

username

The Oracle user name.

password

The password for username.

connection_string

Contém a instância do Oracle à qual se conectar. Pode ser uma » string Easy Connect ou um Connect Name do arquivo tnsnames.ora ou o nome de uma instância local do Oracle.

Se não especificado ou null, o PHP usará variáveis de ambiente como TWO_TASK (no Linux) ou LOCAL (no Windows) e ORACLE_SID para determinar a instância do Oracle à qual se conectar.

Para usar o método de nomenclatura Easy Connect, o PHP precisa ter sido compilado com as bibliotecas Oracle Client 10g ou superiores. A string Easy Connect para o Oracle 10g tem o formato: [//]nome_do_servidor[:porta][/nome_do_servico]. A partir do Oracle 11g a sintaxe é: [//]nome_do_servidor[:porta][/nome_do_servico][:tipo_de_servidor][/nome_da_instancia]. Outras opções foram introduzidas com o Oracle 19c, incluindo as configurações de timeout e keep-alive. Consulte a documentação do Oracle. Os nomes dos serviços podem ser encontrados executando o utilitário Oracle lsnrctl status na máquina do servidor de banco de dados.

O arquivo tnsnames.ora pode estar no caminho de pesquisa Oracle Net, que inclui /seu/caminho/para/instantclient/network/admin, $ORACLE_HOME/network/admin e /etc. Como alternativa, defina TNS_ADMIN para que $TNS_ADMIN/tnsnames.ora possa ser lido. Certifique-se de que o servidor web tem acesso de leitura ao arquivo.

encoding

Determina o conjunto de caracteres usado pelas bibliotecas Oracle Client. O conjunto de caracteres não precisa corresponder ao conjunto de caracteres usado pelo banco de dados. Se não corresponderem, o Oracle fará o possível para converter os dados de e para o conjunto de caracteres do banco de dados. Dependendo dos conjuntos de caracteres, isso pode não fornecer resultados utilizáveis. A conversão também adiciona alguma sobrecarga de tempo.

Se não for especificado, as bibliotecas Oracle Client determinam um conjunto de caracteres a partir da variável de ambiente NLS_LANG.

Passar este parâmetro pode reduzir o tempo necessário para conectar.

session_mode

Este parâmetro está disponível a partir do PHP 5 (PECL OCI8 1.1) e aceita os seguintes valores: OCI_DEFAULT, OCI_SYSOPER e OCI_SYSDBA. Se OCI_SYSOPER ou OCI_SYSDBA forem especificadas, esta função tentará estabelecer uma conexão privilegiada usando credenciais externas. Conexões privilegiadas estão desabilitadas por padrão. Para habilitá-las é preciso configurar oci8.privileged_connect para On.

O PHP 5.3 (PECL OCI8 1.3.4) introduziu o valor de modo OCI_CRED_EXT. Ele informa ao Oracle para usar autenticação External ou OS, que deve ser configurada no banco de dados. A flag OCI_CRED_EXT só pode ser usada com o usuário "/" e uma senha vazia. oci8.privileged_connect pode ser On ou Off.

OCI_CRED_EXT pode ser combinado com os modos OCI_SYSOPER ou OCI_SYSDBA.

OCI_CRED_EXT não é suportado no Windows por razões de segurança.

Valor Retornado

Returns a connection identifier or false on error.

Registro de Alterações

Versão Descrição
8.0.0, PECL OCI8 3.0.0 connection_string is now nullable.

Exemplos

Exemplo #1 Basic oci_connect() using Easy Connect syntax

<?php

// Connects to the XE service (i.e. database) on the "localhost" machine
$conn = oci_connect('hr', 'welcome', 'localhost/XE');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT * FROM employees');
oci_execute($stid);

echo
"<table border='1'>\n";
while (
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
echo
"<tr>\n";
foreach (
$row as $item) {
echo
" <td>" . ($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;") . "</td>\n";
}
echo
"</tr>\n";
}
echo
"</table>\n";

?>

Exemplo #2 Basic oci_connect() using a Network Connect name

<?php

// Connects to the MYDB database described in tnsnames.ora file,
// One example tnsnames.ora entry for MYDB could be:
// MYDB =
// (DESCRIPTION =
// (ADDRESS = (PROTOCOL = TCP)(HOST = mymachine.oracle.com)(PORT = 1521))
// (CONNECT_DATA =
// (SERVER = DEDICATED)
// (SERVICE_NAME = XE)
// )
// )

$conn = oci_connect('hr', 'welcome', 'MYDB');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT * FROM employees');
oci_execute($stid);

echo
"<table border='1'>\n";
while (
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
echo
"<tr>\n";
foreach (
$row as $item) {
echo
" <td>" . ($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;") . "</td>\n";
}
echo
"</tr>\n";
}
echo
"</table>\n";

?>

Exemplo #3 oci_connect() with an explicit character set

<?php

$conn
= oci_connect('hr', 'welcome', 'localhost/XE', 'AL32UTF8');
if (!
$conn) {
$e = oci_error();
trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR);
}

$stid = oci_parse($conn, 'SELECT * FROM employees');
oci_execute($stid);

echo
"<table border='1'>\n";
while (
$row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) {
echo
"<tr>\n";
foreach (
$row as $item) {
echo
" <td>" . ($item !== null ? htmlentities($item, ENT_QUOTES) : "&nbsp;") . "</td>\n";
}
echo
"</tr>\n";
}
echo
"</table>\n";

?>

Exemplo #4 Using multiple calls to oci_connect()

<?php

$c1
= oci_connect("hr", "welcome", 'localhost/XE');
$c2 = oci_connect("hr", "welcome", 'localhost/XE');

// Both $c1 and $c2 show the same PHP resource id meaning they use the
// same underlying database connection
echo "c1 is $c1<br>\n";
echo
"c2 is $c2<br>\n";

function
create_table($conn)
{
$stmt = oci_parse($conn, "create table hallo (test varchar2(64))");
oci_execute($stmt);
echo
"Created table<br>\n";
}

function
drop_table($conn)
{
$stmt = oci_parse($conn, "drop table hallo");
oci_execute($stmt);
echo
"Dropped table<br>\n";
}

function
insert_data($connname, $conn)
{
$stmt = oci_parse($conn, "insert into hallo
values(to_char(sysdate,'DD-MON-YY HH24:MI:SS'))"
);
oci_execute($stmt, OCI_DEFAULT);
echo
"$connname inserted row without committing<br>\n";
}

function
rollback($connname, $conn)
{
oci_rollback($conn);
echo
"$connname rollback<br>\n";
}

function
select_data($connname, $conn)
{
$stmt = oci_parse($conn, "select * from hallo");
oci_execute($stmt, OCI_DEFAULT);
echo
"$connname ----selecting<br>\n";
while (
oci_fetch($stmt)) {
echo
" " . oci_result($stmt, "TEST") . "<br>\n";
}
echo
"$connname ----done<br>\n";
}

create_table($c1);

insert_data('c1', $c1); // Insert a row using c1
sleep(2); // sleep to show a different timestamp for the 2nd row
insert_data('c2', $c2); // Insert a row using c2

select_data('c1', $c1); // Results of both inserts are returned
select_data('c2', $c2); // Results of both inserts are returned

rollback('c1', $c1); // Rollback using c1

select_data('c1', $c1); // Both inserts have been rolled back
select_data('c2', $c2);

drop_table($c1);

// Closing one of the connections makes the PHP variable unusable, but
// the other could be used
oci_close($c1);
echo
"c1 is $c1<br>\n";
echo
"c2 is $c2<br>\n";


// Output is:
// c1 is Resource id #5
// c2 is Resource id #5
// Created table
// c1 inserted row without committing
// c2 inserted row without committing
// c1 ----selecting
// 09-DEC-09 12:14:43
// 09-DEC-09 12:14:45
// c1 ----done
// c2 ----selecting
// 09-DEC-09 12:14:43
// 09-DEC-09 12:14:45
// c2 ----done
// c1 rollback
// c1 ----selecting
// c1 ----done
// c2 ----selecting
// c2 ----done
// Dropped table
// c1 is
// c2 is Resource id #5

?>

Notas

Nota:

An incorrectly installed or configured OCI8 extension will often manifest itself as a connection problem or error. See Installing/Configuring for troubleshooting information.

Veja Também

adicione uma nota

Notas Enviadas por Usuários (em inglês) 9 notes

up
10
M0no at ethonfusino dot com
22 years ago
If your oracle database is on a remote system within your local network and you don't want to worry about the tnsnames file you can try this.

$db = "(DESCRIPTION=(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.XX.XXX)(PORT = 1521)))(CONNECT_DATA=(SID=XXXX)))";

$c1 = ocilogon("name","password",$db);

Hope this helps someone.
up
4
Leandro da Cunha Campos
15 years ago
ONE ALTERNATIVE OF CONNECT IN ORACLE RAC "Real Application Clusters"

<?php
$dbstr
="(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST =ip1)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = banco)
(INSTANCE_NAME = banco1)))"
;

$dbstr1 ="(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST =ip2)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = banco)
(INSTANCE_NAME = banco2)))"
;

if(!@(
$conn = oci_connect('user','password',$dbstr1)))
{
$conn = oci_connect('user','password',$dbstr) or die (ocierror()); }
?>
up
3
sixd at php dot net
16 years ago
If you want to specify a connection timeout in case there is network problem, you can edit the client side (e.g. PHP side) sqlnet.ora file and set SQLNET.OUTBOUND_CONNECT_TIMEOUT. This sets the upper time limit for establishing a connection right through to the DB, including the time for attempts to connect to other services. It is available from Oracle 10.2.0.3 onwards.

In Oracle 11.1, a slightly lighter-weight solution TCP.CONNECT_TIMEOUT was introduced. It also is a sqlnet.ora parameter. It bounds just the TCP connection establishment time, which is mostly where connection problem are seen.

The client sqlnet.ora file should be put in the same directory as the tnsnames.ora file.
up
2
sebastien.barbieri _at_ gmail dot com
18 years ago
When you are using Oracle 9.2+ I would say that you MUST use the CHARSET parameter.

Of course, you will not notice it until there is accented character... so just specify it and you will avoid a big headache.

So for example here is our Oracle internal conf:
select * from nls_database_parameters;

PARAMETER VALUE
------------------------------ ----------------------------------------

NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_ISO_CURRENCY AMERICA
NLS_CHARACTERSET WE8ISO8859P15


And there our oci_connect call:

$dbch=ocilogon($user,$pass,$connectString,"WE8ISO8859P15");

Without that, you will get question mark (inversed), squares… instead of most accented character.

Don’t forget to use that for writing as well as for reading.
up
1
blake dot lewis at gmail dot com
11 years ago
Using ldap for Oracle name resolution:

The web server will need the environmental variable TNS_ADMIN='Directory of tnsname.ora' unless the default location is used. I use '/etc/tns_admin'. Confirm using the phpinfo().

There are three files needed in the TNS_ADMIN location: tnsnames.ora, sqlnet.ora and ldap.ora. If you are only using ldap, tnsnames.ora is not needed.

To sqlnet.ora add:
NAMES.DIRECTORY_PATH=(TNSNAMES,LDAP)

To ldap.ora add:
DIRECTORY_SERVERS=(ldap_server_fqdn:port)
DEFAULT_ADMIN_CONTEXT=""
DIRECTORY_SERVER_TYPE=OID

For a quick and dirty ldap tnsnames server use tnsManager by Dave Berry. Oracle OID or Openldap can used, but are complicated to setup. tnsManager is a no brainer. The quick part: give it a tnsnames.ora file and start it up. The dirty parts: I can't get Toad and SQLDeveloper to work with it, it ignores the domain and it is no longer being maintained.

The order of values in NAMES.DIRECTORY_PATH in sqlnet.ora determines which look up 'adapter' is used, in this case it is tnsnames.ora file and then ldap. I use ldap for general consumption and tnsnames.ora file to override ldap or entries that are not for general consumption.

If you have the full Oracle client you have tnsping. 'tnsping ORACLE_SID' will tell you what adapter you are using: 'Used LDAP adapter to resolve the alias'.

<?php
echo system("/PATH/tnsping ".$ORACLE_SID." 2>&1")."<br />";
echo
'TNS_ADMIN='.getenv('TNS_ADMIN');
?>

ISSUE:
If connecting with only ORACLE_SID and not ORACLE_SID.DB_DOMAIN, the value of NAMES.DEFAULT_DOMAIN from sqlnet.ora is appended, then for some reason PHP tries the HOSTNAME adapter, and if the database name resolves in DNS, it will fail connecting using the database name as the hostname, because neither SID nor SERVICE_NAME are defined.
If using tnsManager append '.ANY_DOMAIN' to $ORACLE_SID to hack around the issue above.

I have tested with:
11.1.0.7 full client and PHP 5.1.6
11.2.0.2 full client and PHP 5.4.11

I have heard that LDAP lookup does not work with older instantclients.
up
1
drew dot carmichael at gmail dot com
15 years ago
When using the OCI_CRED_EXT in php
if the ENV $ORACLE_SID is set the DB does not need to be specified explicitly and the connection will fail unless you provide a NULL DB value when creating the connection.

The $ORACLE_SID trumps the TNS name look up for the connection. So even a manual connection string in the DB parameter will fail.

So when the $ORACLE_SID Env is set a NULL passed instead of the DB name connects successfully.

Hope this saves some hair pulling when moving to %.3 and OS Authentications
up
1
Jonathon Robinson
14 years ago
Regarding the following statement in the documentation:
"The second and subsequent calls to oci_connect() with the same parameters will return the connection handle returned from the first call."

There's one caveat here. Subsequent calls to oci_connect() will only return the same connection handle as the first call as long as a reference is held to the original handle.

For example, the following code will generate *one* connection handle:

<?php
$dbh
= oci_connect($username, $password, $conn_info);
// Do stuff
$dbh = oci_connect$username, $password, $conn_info);
// Do more stuff

The follow code will generate *two* connection handles:
getData();
// Do stuff
getData();
// Do more stuff

getData() {
$dbh = oci_connect($username, $password, $conn_info);
// Do stuff
}
?>

This is the result of PHP garbage collecting the handle at the end of the method scope.

If you want to isolate your DB layer through function calls but still want to leverage the fact that oci_connect can return the same handle, just keep a reference to the handle like so:

<?php
getData
($username, $password, $conn_info) {
$dbh = oci_connect($username, $password, $conn_info);
$key = hash('md5', "$username|$password|$conn_info");
$GLOBALS[$key] = $dbh;
// Do stuff
}
?>

I originally logged this as a bug but apparently this is the expected behaviour, likely because oci_close($dbh) just calls unset($dbh).
up
-4
ben at onshop dot co dot uk
19 years ago
There is a useful solution to the problem of securing connection information in the PHP Cookbook (O'Reilly) by David Sklar and Adam Trachtenberg. They propose using 'SetEnv' in the Apache configuration and then accessing the values from within a script using $_SERVER.

Unfortunately using the 'SetEnv' solution exposes your connection information to all users of that virtual host. If they run phpinfo.php or display $_SERVER, I found that they will see the password from any file under the root of that virtual host.

To restrict exposure to a particular directory or specific file:

1. First put an 'Include' to the secret file in httpd.conf. For example:

Include "/web/private/secret.txt"

2. In the password file, use the 'SetEnvIf' directive to enable the Environment variables by directory only or within a specific file. For example:

- For all files in the directory:

SetEnvIf Request_URI "/path/to/my/directory" ORACLE_PASS=5gHj790j

- For a specific file in the directory

SetEnvIf Request_URI "/path/to/my/directory/connection.oracle.php" ORACLE_PASS=5gHj790j
up
-5
blake dot lewis at gmail dot com
11 years ago
Using ldap for Oracle name resolution:

The web server needs the environmental variable TNS_ADMIN='Directory of tnsname.ora'. I use '/etc/tns_admin'. Confirm using the phpinfo() function.

There are three files needed in the TNS_ADMIN location: tnsnames.ora, sqlnet.ora and ldap.ora. If you are only using ldap, tnsnames.ora is not needed.

To sqlnet.ora add:
NAMES.DIRECTORY_PATH=(TNSNAMES,LDAP)

To ldap.ora add:
DIRECTORY_SERVERS=(ldap_fqdn_hostname:1575)
DEFAULT_ADMIN_CONTEXT=""
DIRECTORY_SERVER_TYPE=OID

For a quick and dirty ldap tnsnames server use tnsManager by Dave Berry. Oracle OID or Openldap can used, but are complicated to setup. tnsManager is a no brainer. The default port is 1575.

The order of values in NAMES.DIRECTORY_PATH from sqlnet.ora determines which look up 'adapter' is used first, in this case it is tnsnames.ora file and then ldap. I use ldap for general consumption and tnsnames.ora file to override ldap or entries that are not for general consumption.

If you have the full Oracle client you have tnsping. 'tnsping ORACLE_SID' will tell you what adapter you are using: 'Used LDAP adapter to resolve the alias'.

<?php
echo system("/PATH/tnsping ".$ORACLE_SID." 2>&1")."<br />";
echo
'TNS_ADMIN='.getenv('TNS_ADMIN');
?>

ISSUE:
For some reason PHP tries the HOSTNAME adapter first, and if the database name resolves in DNS, it will try connecting using the database name as the hostname with no SID or SERVICE_NAME defined. All other Oracle clients I have used will not try the HOSTNAME adapter unless it is listed in NAMES.DIRECTORY_PATH.
I have heard that LDAP look up does not work with older instantclients.
To Top