Você está na página 1de 13

04.

07
Cutting-Edge Technologies for Web Professionals
The Oracle PHP Connection
How to Get Well Connected and
What the Future Holds Once You Are
PHP Databases Special
MaxDB on the Web with PHP
An Introduction to the MaxDB PHP Interface
Slony Replication by Example
Building the Slony Cluster
Ruling the Turf with PHP and IBM Databases
Capitalize on the Best of Both Worlds
2
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7


Table of Contents
www.php-mag.net
06 Whats New in the PHP Community
23 Slony Replication by Example
Building the Slony Cluster
The ability of providing copies among instances of the
database engine is known as replication. This article talks
about Slony, which is the most popular form of master-
slave replication used on PostgreSQL today.
by Robert Bernier
05 The Oracle PHP Connection
How to Get Well Connected and What
the Future Holds Once You Are
In this article we take a look the connection methods
used for PHP and Oracle database using the PHP OCI8
extension. Specifcally we cover non-persistent and
persistent connections while offering some suggestions
for choosing the right approach. In addition we will cover
some upcoming features in the next major release of the
Oracle database to signifcantly improve scalability of
PHP applications.
by Richard Rendell
PHP Databases Special
3
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7


April 2007 Issue
16 MaxDB on the Web with PHP
An Introduction to the MaxDB
PHP Interface
The article presents an introduction to working with
the PHP interface from MaxDB. It is intended for PHP
users and developers already familiar with the use of PHP
extensions and, perhaps, with MaxDB itself. This article
tells you what you need to install MaxDB PHP, how
you can use its features and how you can convert your
MySQL applications to MaxDB PHP.
by Thomas Simenec
37 Ruling the Turf with PHP
and IBM Databases
Capitalize on the Best of Both Worlds
With the release of ibm_db2, PDO_IBM, and PDO_
INFORMIX extensions, IBM has provided a simple
to use, high performing, and very stable database
connectivity layer to the PHP community. The article
attempts to highlight the IBM value proposition and
provides a perspective straight from the gatekeepers
of these offerings to enable development of robust,
enterprise class web applications using PHP and IBM
databases.
by Srini Bhagavan, Kellen Bombardier
Want to Sponsor/Exhibit?
Email: info@jaxindia.com
Phone: +91 80 411 24 392/3
R
THIS YEARS MUST ATTEND FOR IT PROFESSIONALS
Three Conferences In One Package. Cutting-edge Sessions Delivered by
Community and Industry Luminaries.
Venue :
Date :
National Science Symposium Centre, IISc, Bangalore, India
28-31 May 2007
O7
OlSCOVEH TME POWEH OF TMHEE-lM-OME
www.jexindie.ccm
Presents
Media Sponsors
YOUR RIGHT TO INFORMATION TECHNOLOGY
Platinum Sponsor Gold Sponsor
The Oracle PHP Connection PHP Databases Special
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
5
P
HP applications of all types and sizes are being built
using the Oracle database. Using the free Oracle Express
Edition (XE) and the equally free SQL Developer or
JDeveloper, getting up and going with Oracle has never been
more accessible--or cheaper! Whether you are building a
prototype, or a business critical PHP application the initial
step to using all that database technology is to connect to
it. The choice of connection method and how you manage
database connections in the PHP application can have a
dramatic effect on performance. So here we will explore
the ways in which you can connect to an Oracle database
from your PHP application, including the types of Oracle
connections, environment variables and semantics of each
connection method. Finally we will take a look at scalability
of PHP applications and the Oracle connection pooling
approach specifcally developed to increase performance of
multi-process clients such as PHP.
Overview
When I initially got involved in our PHP efforts one of the
most interesting aspects was discovering what customers
were actually doing with PHP and Oracle. Customers were
showing us their wow factor with Oracle and PHP long
before well, those other wow guys. Heres just some of
The Oracle PHP Connection
By Richard Rendell
In this article we take a look the connection methods
used for PHP and Oracle database using the PHP OCI8
extension. Specifcally we cover non-persistent and
persistent connections while offering some suggestions
for choosing the right approach. In addition we will cover
some upcoming features in the next major release of the
Oracle database to signifcantly improve scalability of PHP
applications.
How to Get Well Connected and What
the Future Holds Once You Are
the categories and types of PHP applications our customers
are building using the Oracle database:
Enterprise portals
Content and Records Management
Trading and web commerce
Multimedia
Spatial
OLAP and Business Intelligence
Life Sciences
Pharmaceuticals
Education
Data warehousing and mining
Some of these applications contain over a million lines of
PHP code and at least as many users. Also, several open source
projects have chosen to add Oracle as a supported database. Most
recently the folks at Drupal were kind enough to write about
their experiences doing exactly that in the Oradrup project [1].

Since this article is on PHP connections to


Oracle databases, an exposure to PHP and
the PHP OCI8 extension is desirable.
PHP Databases Special The Oracle PHP Connection

6
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
.......Common to all these PHP applications is the need to connect
to the Oracle database in a high-performance and scalable way.
Many of these applications are business critical and need to
service thousands of users in a very short time period so the
question of scalability is never too far away. In certain cases
the scalability of PHP and Oracle could use some improvement
and we have responded to those customers with some new
functionality around connection pooling scheduled for the next
major database release. More on that later. For now, lets begin
by looking at the connection methods and explaining what we
have today before introducing the new stuff.
Types of Oracle Connection
There are basically three ways to connect to an Oracle
database from a PHP application; all routines are contained in
the PHP OCI8 extension:
A standard connection
Unique connections
Persistent connections
Lets take a look at them.
Standard Connections
For basic connection to Oracle use PHPs oci_connect()
function. You can call oci_connect() more than once in a script.
If you do this and use the same username and database name,
then you get a pointer to the original connection.
$c = oci_connect($username, $password, $dbname);

Multiple Unique Connections


To get a totally independent connection use oci_new_
connect() function. Each connection is separate from any other.
This lets you have more than one database session open at the
same time. This can be useful when you want to do database
operations independently from each other.
$c = oci_new_connect($username, $password, $dbname);
Persistent Connections
Persistent connections can be made with oci_pconnect()
function. Persistent connections are not automatically closed
at the end of a PHP script and remain open for reuse in other
scripts. This makes them fast. Limits on the number of persistent
connections can be set, and connections can be automatically
expired to free up resources. The parameters for tuning persistent
connections are discussed later.
$c = oci_pconnect($username, $password, $dbname);
Oracle Database Name Connection Strings
The $dbname connection string in the earlier examples
is the name of the database that you want to attach to.
It can be local or remote. Having an invalid connection
string can lead to the Oracle error: ORA-12514 TNS:
listener does not currently know of service requested in
connect descriptor.
The database name can be defned in one of the following
ways:
Oracle is proposing enhancements to
the open source PHP OCI8 extension
so that PHP can leverage the pooling
functionality. The OCI8 extension would
be modied to use the DRCP by getting
connections from the pool and releasing
the connection at the end of the script or
when the connection is not in use by the
application.
The Oracle PHP Connection PHP Databases Special
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
7
An Easy Connect string
A full connection string
A database alias
Easy Connect string
The Easy Connect method isas its name suggesteasy,
especially when compared to the other methods. If you are
running Oracle XE on the same machine as the PHP-enabled
web server, you could connect to the HR schema with:
$c=oci_connect(hr,hr_password, //localhost/XE);
The Easy Connect string is a JDBC-like syntax: [//]hostname[:
port][/service_name]
The port defaults to Oracles standard port, 1521. The
service_name defaults to the same name as the host computer.
The // prefx is part of the syntax and is not a PHP line
comment.
You can use this syntax to connect to Oracle8i, Oracle9i
and Oracle10g databases as long as PHP is linked with Oracle
10g libraries. Zend Core for Oracle uses the appropriate Oracle
libraries. More information on the Easy Connect syntax can be
found at:
http://download-west.oracle.com/docs/cd/B19306_01/
network.102/b14212/naming.htm.

Full Database Connection String


The second method of defning a database name is using a
full Oracle Net connection string, that gives total fexibility over
the connection. See Listing. 1
When in doubt, you can copy the connection string used by
other Oracle tools and users if you have access to them. The
syntax can be more complex than the example in Listing 1,
depending on the database and Oracle Net features used. For
example, by using the full syntax, you can enable Oracle Net
features like load balancing and tweak packet sizes. The Easy
Connect syntax doesnt allow this fexibility.
Database Alias
The third option is to store the full connection string in a fle
called tnsnames.ora and refer to it in PHP using an alias. See
Listing 2.
In PHP you would use the alias MYA to connect to the
database:
$c = oci_connect($username, $password, MYA);
PHP needs to be able to fnd the tnsnames.ora fle to resolve
the MYA alias. The directory paths that Oracle searches for
tnsnames.ora depend on your operating system. The search path
always includes the directory specifed by the TNS_ADMIN
environment variable and a default location.
In a standard install the default tnsnames.ora is in:
$ORACLE_HOME/network/admin/tnsnames.ora
In Oracle XE for example, $ORACLE_HOME is in:
/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
.....If you have compiled PHP yourself and are running it
with the Oracle libraries in a standard install, then you would
typically have ORACLE_HOME set and the default tnsnames.ora
# tnsnames.ora
MYA = (DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)
(HOST = myhost.mydomain)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = MYDB.MYDOMAIN)))
Listing 2: Entry in tnsnames.ora le
$db = (DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)
(HOST = myhost.mydomain)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = MYDB.MYDOMAIN)));
$c = oci_connect($username, $password, $db);
Listing 1: Full Oracle Net connection string
Note: Do not set environment variables in
a PHP script with putenv(). It causes hard to
track errors as the behavior is not consistent
for all OCI8 functions.
PHP Databases Special The Oracle PHP Connection

8
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
fle will automatically be found without needing to set TNS_
ADMIN.
In Zend Core for Oracle, the ORACLE_HOME variable
is generally not set when Apache starts, so the default fle will
not be found. Instead, set the TNS_ADMIN variable.
Oracle Environment Variables for
Connections
If you need to change Oracle environment settings like the
language and territory conventions, or are confguring and
building PHP yourself, you will need to set some environment
variables in the shell that starts the web server. The OCI8
extension always needs to fnd Oracle libraries and message
fles. Not fnding the fles can lead to errors like Error while
trying to retrieve text for error ORA-12154. This message
means that an error ORA-12154 occurred (which is one
problem, in this case a connection problem). It also means that
OCI8 couldnt even fnd Oracles message fles to get the text
describing the error (a second problem). The solution for both
problems is often the same--to set the environment correctly.
Another potential source of problems is having multiple
installations of Oracle. Finding mismatched versions of
Oracle libraries and fles can lead to PHP returning the
Oracle error ORA-12705: Cannot access NLS data fles
or invalid environment specifed. The bottom line is that
your environment should be set correctly and consistently.
Environment variables must be set in the shell that starts
Apache so when the OCI8 extension is frst loaded it has access
to the correct values.
To connect to a remote database, or when PHP is linking
with ORACLE_HOME binaries, you may need some or all of the
following environment variables to be set:
ORACLE_HOME
ORACLE_SID
LD_LIBRARY_PATH
NLS_LANG
TNS_ADMIN
The NLS_LANG and TNS_ADMIN variables are most likely to
be required for Zend Core for Oracle. Zend Core for Oracle
modifes apachectl and adds LD_LIBRARY_PATH. (This may not be
required in a future version of Zend Core for Oracle if Oracle
links the Instant Client differently). This allows the Zend Core
for Oracle GUI Console to be reused to start Apache.
If you are using a tnsnames.ora fle and specify network aliases
for the connection string with Zend Core for Oracle, you may
need to do something similar with TNS_ADMIN so the Zend
Core for Oracle Console can restart Apache correctly. If you
start Apache manually, set the environment in a calling script
(see Listing 3).
This example assumes /usr/local/apache/conf/tnsnames.ora exists.
TNS_ADMIN points to the directory containing the tnsnames.
ora fle. You may come across connections that do not specify a
connection string:
$c = oci_connect($username, $password);
This works when ORACLE_SID is set to a local database on
the host running PHP. If you confgure PHP yourself and have
problems, check the output from the phpinfo() function. Look at
the Environment section and make sure the Oracle variables are
set to the values you expect.
Closing Oracle Connections
At the end of each script, connections opened with oci_
connect() or oci_new_connect() are automatically closed. You can
also explicitly close them at any time by calling:
oci_close($c);

Any uncommitted data is rolled back. If a long running
script only spends a small amount of time interacting with the
database, you may want to close connections to free resources
for other users.

#!/bin/sh
TNS_ADMIN=/usr/local/apache/conf
export TNS_ADMIN
echo Starting Apache
#export > /tmp/envvars
/usr/local/apache/bin/apachectl start
Listing 3: start_apache.sh
The Oracle PHP Connection PHP Databases Special
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
9


















Connections opened with oci_pconnect() will not be closed by
oci_close(). This is similar to the way persistent resources work in
other PHP extensions. Idle persistent connections can be set to
expire.
The oci_close() function was a no-op prior to the re-
factoring of OCI8. That is, it had no functional code, and did
not actually close a connection. You could not explicitly close
connections even if you wanted to! This has now changed, but
you can revert to the old behavior if necessary with this php.
ini setting:
oci8.old_oci_close_semantics = 1
Semantically, oci_close() works by reference counting.
Only when all references to the PHP connection are
finished will the database connection actually be closed. In
this example $c1 and $c2 are the one database connection
(because oci_connect returns the same connection resource
when called more than once in a script), but only at the
end of script is the database connection really closed. See
Listing 4.
In Listing 4, the second query fails, but the third succeeds.
Although the reference counting algorithm keeps the database
connection physically open, the connection resource in $c1 is
not usable after oci_close ($c1) is executed.
Connection Management in
Scalable Systems
Oracle achieves its well-known scalability in part through a
multi-threaded architecture. PHP instead has a multi-process
architecture. This difference means care is required when
designing scalable applications.
Using persistent connections is common for web sites that
have high numbers of connections being established. Reusing
a previously opened connection is signifcantly faster than
opening a fresh one. Large sites should benchmark persistent
PHP connections and Oracle Shared Servers also known as
Multi Threaded Servers (MTS). Shared Servers reduce the
numbers of processes needed to handle database requests.
Make sure that you understand the lifetime of your
applications connections. Reuse connections where possible,
but dont be afraid to create new connections and close them
as needed. Each connection will take some Oracle memory, so
overall load can be reduced if idle connections are closed with
Apache process timeouts or with the php.ini parameters to
expire persistent connections.
For sites with hundreds of connections a second, tune the
cache size of an internal sequence generator, sys.audses$. A
starting point is to change it to perhaps 10000:
SQL> alter sequence sys.audses$ cache 10000;
This is also recommended if you are using Oracle RAC
(Real Application Clusters).
With Oracle RAC you can adjust the algorithm that decides
which Oracle node handles each new connection. Set the listener.
ora parameter
PREFER_LEAST_LOADED_NODE_<listener_name> to OFF to use
session based load balancing.
This is documented in Note 220970.1 on Oracles Metalink
support site.
Session-based load balancing takes into account the number
of sessions connected to each node and then distributes new
connections to balance the number of sessions across the
different nodes. This can help when there is a connection storm
<?php
function do_query($c, $query)
{
$s = oci_parse($c, $query);
oci_execute($s);
oci_fetch_all($s, $res);
echo <pre>;
var_dump($res);
echo </pre>;
}
$c1 = oci_connect(hr, hr, //localhost/XE);
$c2 = oci_connect(hr, hr, //localhost/XE);
do_query($c1, select user from dual);
oci_close($c1);
do_query($c1, select user from dual); // fails
do_query($c2, select user from dual); // succeeds
oci_close($c2);
?>
Listing 4: close.php
PHP Databases Special The Oracle PHP Connection

10
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
and the normal allocation metrics do not get a chance to get
updated fast enough. For both RAC and non-RAC database,
the DBMS_SERVICE package lets you specify workload
management goals. This is a detailed topic; refer to Oracles
manuals for more information. Finally, make sure that your
applications are as effcient as possible, which should minimize
the length of time connections are held.
Now that pretty much covers the best practices with
current technology, but to scale performance beyond what we
have today for multi-process clients like PHP, Oracle is adding
a server side connection pool, which will manage a pool of
active connections ready to go.
Pooling Software Objects
In general pooling objects is an optimization that is widely
adopted in many scenarios. Pooling an object makes sense if
the object is:
Required for a relatively short duration
Expensive to create every time it is required
Expensive to tear down when not required
Expensive to maintain all the time (even when not required)
because it consumes resources
Pooling such objects enables the user that needs the object
to quickly access it from the pool and release it back when the
object is not required, thereby enabling other users to reuse
the pooled object. This typically improves system performance
dramatically.
Pooling Database Connections
Database connections generally satisfy all of the earlier
mentioned criteria. Database connection establishment
involves creation of the network connection, spawning an
associated operating system process/thread, performing the
requisite authentication, creation of the session involving
session private contexts for SQL statement, and so on. Tearing
down database connections is also expensive. And needless to
state that unnecessarily maintaining them when not required
just eats up precious resources on the database server. That
explains why database connection pooling greatly helps high
traffc web applications where connections are needed for
short durations. Most multithreaded systems that talk to a
database offer some form of database connection pooling.

Currently PHP Apache processes, being single threaded,


are unable to pool opened database connections, each process
uses its own connection. PHP users are left with two options
either repeatedly create and tear down the connection or keep
the connection around. The former option is typically called
non-persistent connections and the latter is called persistent
connections. Neither of these options really achieves pooling.
Oracle Database Resident
Connection Pooling
The next major release of Oracle will have support for
Database Resident Connection Pooling (DRCP) that performs
pooling on the database side. We announced this feature at
Oracle OpenWorld in 2006. This allows process-oriented
architectures such as PHP to take advantage of database
Richard Rendell is Senior Director of Product
Development in the Linux Engineering division and
is responsible for PHP activities at Oracle. Richard
has worked at Oracle for over 17 years occupying a
range of positions in software development, business
development, product management, consulting and
education. Richard established Oracles Australian
Product Development Center in 1992 initially taking
responsibility for SQL*Plus which is now among
several products developed at the Australian Center.
With a focus on open source for the last 6 years his
teams have delivered the JDeveloper PHP extension
and co-led the Zend Core for Oracle project with Andi
Gutmans at Zend.
The Oracle PHP Connection PHP Databases Special
I n t e r n a t i o n a l P H P M a g a z i n e 0 4 . 2 0 0 7
11
connection pooling in the absence of a middle tier connection
pooling process. Since DRCP is server side functionality, it can
be leveraged across middle tier processes and middle tier boxes
by all clients that want pooling of database connections. That
will allow very high traffc web sites to scale better and the cool
thing about the Oracle DRCP feature is that it is not just limited
to PHPany database client could use it.
DBA View of DRCP
The DRCP is optionally enabled by the DBA on the database
side. The DRCP is confgured by specifying the minimum and
maximum number of connections allowed. The DBA can also
confgure inactivity timeout settings and specify the number of
cursors to be cached per connection. All of this is achieved by
calls to a new PL/SQL connection pool package. Starting the
pool brings up the minimum number of pooled connections and
DRCP dynamically sizes the number of connections in response
to load. There will be some DBA views available for monitoring
DRCP activity and performance as well.
Client Side View of DRCP
On the client side, the client needs to specify :POOLED
in the Easy Connect string that directs the client to the pool
instead of getting a dedicated server connection:
hostname:port/service:POOLED
For users who use TNS style connect strings, there is an
equivalent option:
(SERVER=POOLED)
All clients connecting as a certain user; for example, SCOTT
can then share other SCOTT connections from the pool.
At the Oracle C interface level, there is an additional
parameter called connection_class that allows for further sub-
pools within a users pool. This allows for separation of distinct
applications that may connect as the same user to the database.
The connection_class can be specifed programmatically in the
OCI connect calls.
PHP User View of DRCP
Oracle is proposing enhancements to the open source
PHP OCI8 extension so that PHP can leverage the pooling
functionality. The OCI8 extension would be modifed to use the
DRCP by getting connections from the pool and releasing the
connection at the end of the script or when the connection is
not in use by the application. For example the oci_pconnect()
call will get the connection from the DRCP and an explicit or
implicit indication that the connection is not in use will release
the connection back to the pool.
The proposal includes an additional php.ini setting that
allows for identifcation of all Apache servers that run the same
application:
oci8.connection_class=NAME
This allows Apache instances to share connections from
the same sub-pool on the database side, thereby achieving
pooling across middle tier instances. The aim is to provide the
connection pooling advantages with minimal confguration on
the PHP side.
More Information
For more information on the proposed oci8 changes, or if
anyone is interested in contributing to the oci8 enhancements
or specifcation, please contact either myself at richard.rendell@
oracle.com or Christopher Jones at christopher.jones@oracle.
com.
Conclusion
Connecting to the Oracle database and maintaining high-
performance connections is critical to high traffc web sites and
business critical PHP applications. Through feedback from our
customers and developers Oracle is creating a highly scalable
architecture for multi-process clients such as PHP. We sincerely
appreciate the efforts of all who have helped defne and
refne this functionality. I would especially like to thank Luxi
Chidambaran and the Oracle OCI development team for their
long-standing support of PHP and development of the DRCP
architecture. Look for further announcements at the next major
release of the database.
Resources & References
[1] http://www.oracle.com/technology/pub/articles/pedros-drupal.html
Oracle Technology Network: http://www.oracle.com/technology
[2] Oracle 10g Release 2 Documentation: http://www.oracle.com/technology/
documentation/database10gr2.html
[3] Oracle PHP Developer Center: http://www.oracle.com/technology/tech/
php/index.html
$POGFSFODFGPSUIF/FYU(FOFSBUJPO8
FC
Webinale 07
The Next Generation Web is about getting
associated with openness, trust, authenticity
and collaboration. Interactivity, new
possibilities to connect, social software,
usability, and community networking are fast
catching up with users. This new buzz is
generating fresh and exciting projects. The
latest buzzword is Web 2.0, and the event
for anyone seeking to stay on top of this
buzz is Webinale 2.0!
Are you in a dilemma finding solutions to
your questions? Where do I find specific
perspectives sans the hype? What are the
possible methodologies and how can I
implement them in my projects? Who can
show me how to use the opportunities and
solve the problems? What does the future of
the World Wide Web (WWW) looks like?
Which parts of this Buzz are just gadgets
that cannot persist in every day reality?
Webinale 07 is transferring the knowledge
for the Next Generation Web! Find your
answers here! Become part of the
movement and gather all the information
you need to become successful on the Web
2.0 platform.
Focus Areas

Webinale 07 provides concrete perspectives on:


AJAX in Act
Web Security
Web Business
Web Know-how
Enterprise Business
webinale 07 will disseminate business and technical
know-how related to Web development, Design,
Optimization, and Web Security, besides informative
sessions on how to efficiently market Web sites.
webinale 07 offers a number of parallel sessions for
you to choose from. It also provides ample
opportunities for exchange of ideas, networking and
staying abreast with the latest trends on the Web!
The topics in webinale 07 are
relevant to:

Developers
Designers
Project Managers
Online Marketing Strategists
webinale 07 is positioned as a platform that will enable
the Next Generation Web for you. Top-notch speakers
who will not only demonstrate the best Practices, but
also guide you along the way will deliver cutting-edge
sessions. Information that you gather at webinale 07
will be most relevant for your day-to-day projects.
Interested in Advertising, Exhibiting or Sponsoring?
Please visit

webinale-asia.com
Singapore,
webinale-asia.com
23-24 April 2007
FOUR SERVICES.ONE SOURCE.
'OLD3PONSOR
ou can also visit http://www.impigertech.com/
wizard/.
WHERE DO YOU WANT TO
MEET YOUR CUSTOMER?
S&S Media
CHAMPIONING CROSS MEDIA COMMUNICATIONS
S&S MEDIA PTE LTD
l33 NLw 8P|DGL POAD #08-l0 CH|NATOwN PO|NT
S|NGAPOPL 0594l3
TEL: +65 6435 0260 (MA|N L|NL) FAX: +65 6887 3842
E-MAIL: advertisesda-asia.com
WebSite:www.softwaresupportmedia.sg
Software & Support Verlag GmbH
Geleitsstrae l4
60599 Prankfurt am Main, Germany
Phone: +49 (0) 69 63 00 89 0 Fax: +49 (0) 69 63 00 89 89
E-mail: sda-asiasoftware-support.biz
Website:www.software-support.biz
S&S Media
MLNAPA KAD|N |NDONLS|A,
1AKAPTA l2950, |NDONLS|A
Phone: +62 2l 5263083 Fax: +62 2l 5299 4599
E-mail: contactusmedia-ti.co.id
WebSite:www.media-ti.co.id
S&S Media
#l5/6, | PLOOP, PP|MPOSL POAD,
8ANGALOPL - 560 025
Off: +9l 80 4ll24392/3 Pax: +9l 80 4ll2439l
E-mail: editorssda-india.com
WebSite:www.softwaresupportmedia.in
FOUR SERVICES. ONE SOURCE.
S&S
Media
Print
(Magazine)
Custom
Events
Branded
Conference
Online

Você também pode gostar