PHP has a set of functions for each kind of database. We have
PostgreSQL on Osiris, so use the functions whose names start with pg_
.
If you should change databases, to MySQL, say, you would have to
replace all pg_
with mysql_
.
You connect to a database (on Osiris), do any number of 'queries',
look at the results of select queries, and close the connection (or
else it is closed at the end of the script.) For a quick start, see commented
example
$conn=pg_connect ('dbname=timetable') or die ('Connect failed ');In the first case, a local connection is made with the permissions of the user 'apache', since "user authentication" is in effect on Osiris. This means that you must grant the necessary permissions to 'apache'. These should be the minimum necessary for your scripts, I avoid DELETE permissions, for example. This is the safest way to connect.
$conn=pg_connect ('dbname=jsmith user=jsmith password=fishStory');
$conn=pg_connect ('host=localhost dbname=jsmith user=jsmith password=fishStory');
GRANT SELECT, INSERT ON students, sports TO apache;
The second case is, again a local connection, this time using jsmith's permissions. Presumably jsmith is the owner of the database. The third case is the same, except that a TCP connection is made. Host could have been given as Osiris, or even cs-linux (a different host).
There are some drawbacks to connecting as the database owner:
In all the functions, the connection object is the first argument, but it is optional since typically you only make one connection in a script. For simplicity I will omit the connection, which we assume is (the last one to be) made.
A query can either modify the database (INSERT, UPDATE, DELETE) or
return results (SELECT). These 2 sorts return somewhat different result
objects.
$query = "SELECT given, family FROM students"
$result = pg_query($query) or die("query failed".pg_last_error());
We can then get the names of students from $result, see below
When the query depends upon form data, we cannot write it in
advance. Examples are search criteria for SELECT, and data to be
INSERTed or used for UPDATE.
A lot of things could go wrong, because we don't know what the users
might input, character data must be delimited by single-quotes (') in
SQL statements, so apostrophes (') must be "escaped" or doubled in the
constructed statement. Do not use
pg_query for variable data. The name O'Hara will fail, and O'; drop table students --
will kill
you! This is a cracker trick called "SQL injection". Cartoon at http://xkcd.com/327/
Instead, we write the query with placeholders of the form $1, $2, etc.
and then pass the variable data as an array, as follows.
$query2 = 'INSERT into students (given, family, linux) values ($1, $2, $3)';
$resultinsert = pg_query_params($query2, array($g, $f, $linux))
or die("query failed".pg_last_error());
$query1 ='SELECT * FROM courses where prof=$1'; // will come from form
$result1 = pg_query_params($query, array($profname));
The function pg_query_params escapes the data (doubling any
single-quotes), encloses each item in single quotes (ex: 'O''Hara') and
puts the result in the query at each placeholder. Note: There must be exactly as many
elements in the array as there are placeholders.
pg_prepare('instu',$query2);... and we could have more pg_execute() statements for the same named query
$resultinsert = pg_execute('instu', array($g, $f, $linux))
or die("query failed".pg_last_error());
The result of a modify could be FALSE, if the statement failed. This could happen if it violated some constraint, such as primary key or character data too long. If it succeeds, the only information we might need is how many rows were inserted (0 or 1) updated or deleted (0, 1, or more). For a modify query, use
print pg_affected_rows ($resultinsert) . " rows inserted for $linux<br>\n";
$nrows = pg_num_rows($result);and we probably want to fetch all the rows, one after another. The "fetch" functions normally return successive rows, each one as an array of fields, and FALSE when all have been fetched.
print "There are $nrows students";
This example prints the field names followed by their values, one
field per line. (A fancier
example could print the result table as an HTML table.) The use
of htmlentities is optional, it prevents misunderstandings about
encoding of special characters.
while ( $line = pg_fetch_assoc($result1) ) // all rows
foreach ($line as $key => $value) // all columns
print "$key = ".htmlentities($value, ENT_COMPAT, 'UTF-8')."<br>\n";
pg_free_result($result1); /* Free resultset */
Another example, also loops through the rows, and for each row print
the columns on one line and then a <br> tag:
while ($row = pg_fetch_row($result) )
{ foreach ($row as $item)
print $item;
print "<br>\n"; // a new line (break) in html
}
Of course, you would discover that all the items will be scrunched
up together, so at least you want to add some spaces between them, or
else add the appropriate tags to define an html table. You could add
column headings to a table, this php code does not get the column names.
Result sets may be large, and should be freed when no longer needed,
if one is not at the end of the script. In addition, it is a good idea
to close the connection. Remember $conn? It has been implicit all along.
pg_close($conn);