Sie sind auf Seite 1von 18

http://devzone.zend.

com/14/php-101-part-9-sqlite-my-fire_part-1/

PHP 101 (part 9): SQLite My Fire! Part 1


November 30, -0001

Hard Choices

Making New Friends

The Bookworm Turns

Anatomy Class

Different Strokes

Adding to the Collection

PHP 101 (PART 9): SQLITE MY FIRE! PART 2

Not My Type

Starting From Scratch

A Few Extra Tools

Hard Choices
If youve been paying attention, you now know how to use PHPs MySQL API to perform queries
and process result sets. You might even have started thinking about how to re-program your site
to run off a MySQL database. All of this is a Good Thing it means youre getting comfortable
with using PHPs database support to power your applications but theres still a little further to
go.
As you saw in Part Eight, enabling MySQL support in PHP 5.0 is not as simple as it used to be.
Instead of supporting MySQL out of the box, PHP now requires you to make all kinds of decisions
about versions and libraries before allowing you to hook your scripts up to a MySQL database. If
youre lazy (and deep down, we both know you are), you might instead prefer to try a simpler
option: the SQLite database engine.
Built-in SQLite support is new to PHP 5.0, and offers users a lightweight database system that is
fast, efficient and gets the job done. Since its enabled by default in PHP 5.0, it provides a viable
alternative to MySQL; you can use it out of the box, without spending time on version checks and
library downloads; just install PHP 5 and start typing. Thats why Im devoting a whole tutorial to it
- so get out of bed, make yourself some coffee and lets get started!

Making New Friends


Before getting into the code, lets make sure that you have a clear idea of what SQLite is (and
isnt). Unlike MySQL, which operates on a client-server paradigm, SQLite is a file-based
database engine and uses file I/O (input/output) functions to store and read databases from files
on disk. Its also much, much smaller than MySQL the command-line version of SQLite weighs
in at under 200 KB and supports most of the SQL commands youre used to.
This small size shouldnt deceive you, however according to the official SQLite Web site
(http://sqlite.org/), SQLite supports databases up to 2 terabytes in size and is actually faster than
MySQL in certain situations. SQLite database files are easily portable, and SQLite databases
created on Windows work fine on *NIX platforms and vice-versa.
One of SQLites more interesting aspects is that it is completely typeless. Fields in an SQLite
database need not be associated with a specific type, and even if they are, you can still
insert values of different types into them (there is one exception to this rule, but Ill get to that
later). This is important, because it means that if youre concerned about values of the wrong type
getting into your tables, you need to write code to implement type checking in your application.
Another important difference between MySQL and SQLite lies in their licensing policies: unlike
MySQL, SQLite source code is completely public-domain, which means that you can use and
distribute it however you choose in both commercial and non-commercial products. Take a look at
http://sqlite.org/copyright.html for more on this.
In order to use SQLite and PHP together, your PHP build must include SQLite. This is enabled by
default in both the UNIX and Windows versions of PHP 5. Read more about this at
http://www.php.net/manual/en/ref.sqlite.php.
If youre a PHP 4.x user, though, dont lose heart you can still use SQLite,
by manually downloading and installing php_sqlite.dll from
http://snaps.php.net
(Windows) or the latest tarball from "http://pecl.php.net/package/SQLite"
target="_blank">http://pecl.php.net/package/SQLite
(UNIX). You dont need to download anything else; the SQLite client is its own engine.

The Bookworm Turns


As with MySQL, you use regular SQL commands to interact with an SQLite database. The exact
SQL syntax used by SQLite is listed at http://sqlite.org/lang.html, but for most operations SQL
commands are standard.
Heres an example, which sets up the table Ill be using in this tutorial:

C:\WINDOWS\Desktop\sqlite>sqlite library.db
SQLite version 2.8.15
Enter ".help" for instructions
sqlite> create table books (
...> id integer primary key,
...> title varchar(255) not null,
...> author varchar(255) not null
...>);
sqlite> insert into books (title, author) values ('The Lord Of The Rings', 'J.R.R. Tolkien');
sqlite> insert into books (title, author) values ('The Murders In The Rue Morgue', 'Edgar Allen
Poe');
sqlite> insert into books (title, author) values ('Three Men In A
Boat', 'Jerome K. Jerome');
sqlite> insert into books (title, author) values ('A Study In Scarlet',
'Arthur Conan Doyle');
sqlite> insert into books (title, author) values ('Alice In
Wonderland', 'Lewis Carroll');
sqlite> .exit

You can enter these commands either interactively or non-interactively through the SQLite
commandline program, which is available at http://sqlite.org/download.html as a precompiled
binary for Windows and Linux. SQLite 2.* is the version currently used in both branches of PHP,
with SQLite 3.* support
anticipated for PDO and later PHP 5.* releases.
Extract the downloaded files to a directory of your choice, cd into it from your shell or DOS box
and type sqlite. You should see the SQLite version information and the line:
Enter ".help" for instructions
Read http://sqlite.org/sqlite.html for more information on how to use the commandline program.

Once the data has been imported into the database file library.db, run a quick SELECT
query to check if everything is working as it should:
sqlite> select * from books;
1|The Lord Of The Rings|J.R.R. Tolkien
2|The Murders In The Rue Morgue|Edgar Allen Poe
3|Three Men In A Boat|Jerome K. Jerome
4|A Study In Scarlet|Arthur Conan Doyle
5|Alice In Wonderland|Lewis Carroll
If you saw the same output as above, youre good to go!

Anatomy Class
Now, use PHP to communicate with SQLite, generate the same result set and format it as an
HTML page. Heres the code:
<html>
<head></head>
<body>
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// generate query string
$query = "SELECT * FROM books";
// execute query
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// if rows exist
if (sqlite_num_rows($result) > 0) {
// get each row as an array
// print values
echo "<table cellpadding=10 border=1>";
while($row = sqlite_fetch_array($result)) {
echo "<tr>";
echo "<td>".$row[0]."</td>";

echo "<td>".$row[1]."</td>";
echo "<td>".$row[2]."</td>";
echo "</tr>";
}
echo "</table>";
}
// all done
// close database file
sqlite_close($handle);
?>
</body>
</html>

If all goes well, you should see something like this:

If you remember what you learned in Part Eight, the PHP script above should be easy to
decipher. In case you dont, heres a fast rundown:
1. The ball starts rolling with the sqlite_open() function, which accepts the name of the
database file as argument and attempts to open it. If this database file cannot be found, an
empty database file will be created with the supplied name (assuming the script has write
accessto the directory).
<?php
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
$handle = sqlite_open($db) or die("Could not open database");

?>

The database file library.db needs to be kept somewhere it cant be accessed through the
browser by visitors to your site. That means that you need to create it outside your
public_html, www or htdocs directory, in a directory that allows your scripts read/write
permissions. Web hosting companies generally will offer a space above your web-visible
directory where you can do this.
$_SERVER['DOCUMENT_ROOT']."/.." is the directory directly above your web-visible
directory.
If successful, the sqlite_open() function returns a handle to the file, which is stored in the
variable $handle and is used for all subsequent communication with the database.
2. The next step is to create and execute the query, with the sqlite_query() function.
<?php
$query = "SELECT * FROM books";
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
?>
This function also needs two parameters: the database handle and the query string.
Depending on whether or not the query was successful, the function returns true or false; in
the event of a failure, the sqlite_error_string() and sqlite_last_error()
functions can be used to display the error that took place.
3. If sqlite_query() is successful, the result set returned by the query is stored in the
variable $result. You can retrieve the records in the result set with
the sqlite_fetch_array() function, which fetches a single row of data as an array
called $row. Fields in that record are represented as array elements, and can be accessed
using standard index notation.
Each time you call sqlite_fetch_array(), the next record in the result set is returned.
This makes sqlite_fetch_array() very suitable for use in a while() loop, in much the
same way as mysql_fetch_row() was used earlier.
<?php
if (sqlite_num_rows($result) > 0) {
echo "<table cellpadding=10 border=1>";
while($row = sqlite_fetch_array($result)) {

echo "<tr>";
echo "<td>".$row[0]."</td>";
echo "<td>".$row[1]."</td>";
echo "<td>".$row[2]."</td>";
echo "</tr>";
}
echo "</table>";
}
?>
The number of records returned by the query can be retrieved with the
sqlite_num_rows() function. Or, if what youre really interested in is the number of fields
in the result set, use the sqlite_num_fields()function instead. Of course, these are only
applicable with queries that actually return records; it doesnt really make sense to use them
with INSERT, UPDATE or DELETE queries.
4. Once youre done, its a good idea to close the database handle and return the used memory
to the system, with a call to sqlite_close():
<?php
sqlite_close($handle);
?>
In PHP 5 you can also use the SQLite API in an object-oriented way, wherein each of the
functions above becomes a method of the SQLiteDatabase() object. Take a look at this next
listing, which is equivalent to the one above:
<html>
<head></head>
<body>
<?php
// set path of database file
$file = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// create database object
$db = new SQLiteDatabase($file) or die("Could not open database");
// generate query string
$query = "SELECT * FROM books";
// execute query
// return result object
$result = $db->query($query) or die("Error in query");

// if rows exist
if ($result->numRows() > 0) {
// get each row as an array
// print values
echo "<table cellpadding=10 border=1>";
while($row = $result->fetch()) {
echo "<tr>";
echo "<td>".$row[0]."</td>";
echo "<td>".$row[1]."</td>";
echo "<td>".$row[2]."</td>";
echo "</tr>";
}
echo "</table>";
}
// all done
// destroy database object
unset($db);
?>
</body>
</html>
Here, the new keyword is used to instantiate an object of the class SQLiteDatabase() by
passing the object constructor the name of the database file. If the database file does
not already exist, a new database file is created. The resulting object, stored in $db, then
exposes methods and properties to perform queries. Every query returns an instance of the class
SQLiteResult(), which in turn exposes methods for fetching and processing records.
If you look closely at the two scripts above, youll see the numerous similarities between the
procedural function names and the object method names. While the correspondence between the
two is not perfect, its usually close enough to make it possible to guess the one if you know the
other.

Different Strokes
As with the MySQL API, PHPs SQLite API offers you more than one way to skin a cat. For
example, you can retrieve each row as an object with the sqlite_fetch_object() method,
and access field values by using the field names as object properties. Heres an example:
<html>

<head></head>
<body>
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// generate query string
$query = "SELECT * FROM books";
// execute query
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// if rows exist
if (sqlite_num_rows($result) > 0) {
// get each row as an object
// print field values as object properties
echo "<table cellpadding=10 border=1>";
while($obj = sqlite_fetch_object($result)) {
echo "<tr>";
echo "<td>".$obj->id."</td>";
echo "<td>".$obj->title."</td>";
echo "<td>".$obj->author."</td>";
echo "</tr>";
}
echo "</table>";
}
// all done
// close database file
sqlite_close($handle);
?>
</body>
</html>
Another option is to retrieve the complete result set in one fell swoop with the
sqlite_fetch_all() function. This function retrieves the complete set of records as an array
of arrays; each element of the outer array represents a record, and is itself structured as an array
whose elements represent fields in that record.
Heres an example, which might make this clearer:

<html>
<head></head>
<body>
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// generate query string
$query = "SELECT * FROM books";
// execute query
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// get the complete result set as a series of nested arrays
$data = sqlite_fetch_all($result);
// all done
// close database file
sqlite_close($handle);
// check the array to see if it contains at least one record
if (sizeof($data) > 0) {
echo "<table cellpadding=10 border=1>";
// iterate over outer array (rows)
// print values for each element of inner array (columns)
foreach ($data as $row) {
echo "<tr>";
echo "<td>".$row[0]."</td>";
echo "<td>".$row[1]."</td>";
echo "<td>".$row[2]."</td>";
echo "</tr>";
}
echo "</table>";
}
?>
</body>
</html>
In all the previous examples, the database remained open while the result set was processed,
because records were retrieved one after another with the sqlite_fetch_array() or

sqlite_fetch_object() functions. The example above is unique in that the database can be
closed before the result set array is processed.
This is because the entire result set is retrieved at once and stored in the $data array, so there
really isnt any need to leave the database open while processing it.
If your result set contains only a single field, use the sqlite_fetch_single()function, which
retrieves the value of the first field of a row. The PHP manual puts it best when it says this is the
most optimal way to retrieve data when you are only interested in the values from a single column
of data. Take a look:
<html>
<head></head>
<body>
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// generate query string
// this query returns only a single record with a single field
$query = "SELECT author FROM books WHERE title = 'A Study In Scarlet'";
// execute query
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// if a row exists
if (sqlite_num_rows($result) > 0) {
// get the value of the first field of the first row
echo sqlite_fetch_single($result);
}
// all done
// close database file
sqlite_close($handle);
?>
</body>
</html>
You can even use the sqlite_fetch_single() function in combination with a while() loop
to iterate over a result set containing many records but a single field. Notice also my usage of
the sqlite_has_more() function, to check if the next row exists or not.

<html>
<head></head>
<body>
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// generate query string
$query = "SELECT DISTINCT author FROM books";
// execute query
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// if rows exist
if (sqlite_num_rows($result) > 0) {
echo "<table cellpadding=10 border=1>";
// check for more rows
while (sqlite_has_more($result)) {
// get first field from each row
// print values
$row = sqlite_fetch_single($result);
echo "<tr>";
echo "<td>".$row."</td>";
echo "</tr>";
}
echo "</table>";
}
// all done
// close database file
sqlite_close($handle);
?>
</body>
</html>
You can, of course, do the same thing using object notation in PHP 5. However, you need to
know that sqlite_has_more() is one function that really doesnt translate to its object method
name; in an OO script, you would need to call $result->valid();.

This script is the OO equivalent of the one above:

<html>
<head></head>
<body>
<?php
// set path of database file
$file = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// create database object
$db = new SQLiteDatabase($file) or die("Could not open database");
// generate query string
$query = "SELECT DISTINCT author FROM books";
// execute query
$result = $db->query($query) or die("Error in query");
// if rows exist
if ($result->numRows() > 0) {
echo "<table cellpadding=10 border=1>";
// check for more rows
while ($result->valid()) {
// get first field from each row
// print values
$row = $result->fetchSingle();
echo "<tr>";
echo "<td>".$row."</td>";
echo "</tr>";
}
echo "</table>";
}
// all done
// destroy database object
unset($db);
?>
</body>
</html>

PHP 101 (PART 9): SQLITE MY FIRE! PART 2


November 30, -0001

Not My Type

Starting From Scratch

A Few Extra Tools

Not My Type
Whilst on the topic of INSERT, remember my statement a couple pages back about how SQLite
is typeless and so you can insert values of any type into any field?
There is one important exception to this rule: a field marked as INTEGER PRIMARY KEY.
In SQLite, fields marked as INTEGER PRIMARY KEY do two important things: they provide a
unique numeric identifier for each record in the table, and if you insert a NULL value into them,
SQLite automatically inserts a value that is 1 greater than the largest value already present in that
field.
INTEGER PRIMARY KEY fields in SQLite thus perform the equivalent of
AUTO_INCREMENT fields in MySQL, and are a convenient way of automatically numbering your
records. Obviously, you cant insert non-numeric values into such a field, which is why I said they
were an exception to the typeless rule.
Read more about this at http://www.sqlite.org/datatypes.html.
Since the books table used in the previous example already contains such a field (the id field), its
clear that every INSERT into it with a NULL value for that field generates a new record number. If
youd like to retrieve this number, PHP has a way to do that too just use the
sqlite_last_insert_rowid() function, which returns the ID of the last inserted row (equivalent to
the mysql_insert_id() function in PHPs MySQL API).
To see this in action, update the if() loop in the middle of the previous script to include a call
to sqlite_last_insert_rowid(), as follows:
<?php
// check to see if the form was submitted with a new record
if (isset($_POST['submit'])) {
// make sure both title and author are present
if (!empty($_POST['title']) && !empty($_POST['author'])) {

// generate INSERT query


$insQuery = "INSERT INTO books (title, author) VALUES
(\"".sqlite_escape_string($_POST['title'])."\", \"".sqlite_escape_string($_POST['author'])."\")";
// execute query
$insResult = sqlite_query($handle, $insQuery) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// print success message
echo "<i>Record successfully inserted with ID ".sqlite_last_insert_rowid($handle)."!</i><p
/>";
}
else {
// missing data
// display error message
echo "<i>Incomplete form input. Record not inserted!</i><p />";
}
}
?>
If you need to, you can also find out how many rows were affected using the sqlite_changes()
function try it for yourself and see!

Starting From Scratch


Youll remember, from the beginning of this tutorial, that I suggested you initialize the library.db
database using the SQLite commandline program. Well, that isnt the only way to create a fresh
SQLite database you can use PHP itself to do this, by issuing the necessary CREATE
TABLE and INSERT commands through the sqlite_query() function. Heres how:
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library2.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// create database
sqlite_query($handle, "CREATE TABLE books (id INTEGER PRIMARY KEY, title VARCHAR(255)
NOT NULL, author VARCHAR(255) NOT NULL)") or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
// insert records
sqlite_query($handle, "INSERT INTO books (title, author) VALUES ('The Lord Of The Rings',
'J.R.R. Tolkien')") or die("Error in query: ".sqlite_error_string(sqlite_last_error($handle)));

sqlite_query($handle, "INSERT INTO books (title, author) VALUES ('The Murders In The Rue
Morgue', 'Edgar Allan Poe')") or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));
sqlite_query($handle, "INSERT INTO books (title, author) VALUES ('Three Men In A Boat',
'Jerome K. Jerome')") or die("Error in query: ".sqlite_error_string(sqlite_last_error($handle)));
sqlite_query($handle, "INSERT INTO books (title, author) VALUES ('A Study In Scarlet', 'Arthur
Conan Doyle')") or die("Error in query: ".sqlite_error_string(sqlite_last_error($handle)));
sqlite_query($handle, "INSERT INTO books (title, author) VALUES ('Alice In Wonderland', 'Lewis
Carroll')") or die("Error in query: ".sqlite_error_string(sqlite_last_error($handle)));
// print success message
echo "<i>Database successfully initialized!";
// all done
// close database file
sqlite_close($handle);
?>
Or, in PHP 5, you can use the object-oriented approach:
<?php
// set path of database file
$file = $_SERVER['DOCUMENT_ROOT']."/../library3.db";
// create database object
$db = new SQLiteDatabase($file) or die("Could not open database");
// create database
$db->query("CREATE TABLE books (id INTEGER PRIMARY KEY, title VARCHAR(255) NOT
NULL, author VARCHAR(255) NOT NULL)") or die("Error in query");
// insert records
$db->query("INSERT INTO books (title, author) VALUES ('The Lord Of The Rings', 'J.R.R.
Tolkien')") or die("Error in query");
$db->query("INSERT INTO books (title, author) VALUES ('The Murders In The Rue Morgue',
'Edgar Allan Poe')") or die("Error in query");
$db->query("INSERT INTO books (title, author) VALUES ('Three Men In A Boat', 'Jerome K.
Jerome')") or die("Error in query");
$db->query("INSERT INTO books (title, author) VALUES ('A Study In Scarlet', 'Arthur Conan
Doyle')") or die("Error in query");
$db->query("INSERT INTO books (title, author) VALUES ('Alice In Wonderland', 'Lewis Carroll')")
or die("Error in query");
// print success message
echo "<i>Database successfully initialized!";

// all done
// destroy database object
unset($db);
?>

A Few Extra Tools


Finally, the SQLite API also includes some ancillary functions, to provide you with information on
the SQLite version and encoding, and on the error code and message generated by the last
failed operation. The following example demonstrates the sqlite_libversion() and
sqlite_libencoding() functions, which return the version number and encoding of the linked
SQLite library respectively:
<?php
// version
echo "SQLite version: ".sqlite_libversion()."<br />";
// encoding
echo "SQLite encoding: ".sqlite_libencoding()."<br />";
?>
When things go wrong, reach for the sqlite_last_error()function, which returns the last
error code returned by SQLite. Of course, this error code a numeric value is not very useful in
itself; to convert it to a human-readable message, couple it with the sqlite_error_string()
function. Consider the following example, which illustrates by attempting to run a query with a
deliberate error in it:
<?php
// set path of database file
$db = $_SERVER['DOCUMENT_ROOT']."/../library.db";
// open database file
$handle = sqlite_open($db) or die("Could not open database");
// generate query string
// query contains a deliberate error
$query = "DELETE books WHERE id = 1";
// execute query
$result = sqlite_query($handle, $query) or die("Error in query:
".sqlite_error_string(sqlite_last_error($handle)));

// all done
// close database file
sqlite_close($handle);
?>
Heres what the output looks like:

Note that although they might appear similar, the sqlite_last_error() and
sqlite_error_string() functions dont work in exactly the same way as the
mysql_errno() and mysql_error() functions. The mysql_errno() and
mysql_error() functions can be used independently of each other to retrieve the last error
code and message respectively, but the sqlite_error_string() is dependent on the error
code returned by sqlite_last_error().
If your appetite has been whetted, you can read more about the things PHP can do with SQLite in
Zends PHP 5 In Depth section.
And thats about all I have for you in this tutorial. More secrets await you in Part 10 of PHP 101,
so make sure you come back for that one!

Copyright Melonfire, 2004 (http://www.melonfire.com). All rights reserved.

Das könnte Ihnen auch gefallen