TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 07-24-2008, 02:44 PM   #1 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default [Tutorial] How to organize your classes | Part 1

How to organize your classes
Part 1: Database class + config files


Section 1: Intro

Hello and welcome to this guide! This will be a guide with 2 or possibly 3 parts.
It will learn you how to organize your class files in a nice way, and how to write a good database class that gets your job done.
Ofcourse this is only how I do it, and there are a thousand other ways, but I think you'll get a better understanding and possibly get some ideas from reading this guide.

So, first we'll take a look at the structure and organizing of the files.

For this to be easier to explain(and for you to understand), I will just pretend that we have a projectfolder called "test", located in our root directory.

And since I do this on localhost, the folder I place my hosted files, is called "www". So what does this conclude?
We have:

Code:
www
- test
Everyone with me so far?


Right, so let's start the actual tutorial :P
We want to have an includes folder, where we will have everything that we want to include.

Code:
www
- test
- - includes
In the includes folder, we will have our config file for example(that's atleast what I will explain to you today) and a classes file which I also will go through today.
Some folders that you want to have inside includes, is for example gfx, js, templates, classes, plugins

Code:
www
- test
- - includes
- - - gfx
- - - js
- - - templates
- - - classes
- - - plugins
The folder we will concentrate on today, is the classes folder.

Section 2: The database class and the database interface

Right. Alot of people use database to store things. Not only is it faster than if you would store it with.. say a .txt file, but it's also alot safer, but the main
thing is that it's EASY to manipulate the data. This means that you could write neat admin panels to control your site layout, templates and lots and lots more!!

But in order to get a nice way of handling the database, you need a proper database class, that will provide a set of functions for you to use inside your classes.

This database class, will actually consist of 3 files.
iDB.php - This is our interface for the class.
DBmysql.php - This is the actual class for the database, in this case a mysql-database which I called mysql.php(convinient xD?) with the prefix of DB(DBmysql).
DB.php - This is our.. DB factory, which makes it easier to include the database file.

So let's start by taking a look at our interface!

An interface is merely a blueprint on how the class should look, what functions it have to contain. This is neccessary, because when you guys figure out
that you don't want to use a mysql database, but an oracle database, and you write your own db class(DBoracle.php), you will then see if your class follows the blueprint.

The interface is define with
PHP Code:
    interface iDB {
        
    } 
Pretty simple.
So what functions should the database have?
Well, first of all, we need a function that will set the values of the hostname, username, userpass and dbname. We would also need a function that connects.. etc etc.
I'm sure you can figure out by yourself all the functions that a database class should have.

This is my interface anyhow:
PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/

    
interface iDB {
        
        public function 
setHandler($host$user$pass$data);
        public function 
connect();
        public function 
select();
        public function 
disconnect();
        public function 
query($query);
        public function 
fetch_one($sql);
        public function 
fetch_all($sql);
        public function 
fetch_object_one($sql);
        public function 
fetch_object_all($sql);
        public function 
setTable($field$value);
        public function 
setCol($field$value);
        
    } 
2 very important functions are the setTable and setCol. I will explain later in the tutorial what they do, just keep them there!

So the next file, is ofcourse the database class itself.
As I mentioned before, this is just the mysql since it's most used.

PHP Code:
    class DBmysql implements iDB {
        
        private 
$host;
        private 
$user;
        private 
$pass;
        private 
$data;
        public 
$table = array();
        public 
$col = array();
        
        
        public function 
setHandler($host$user$pass$data) {
            
            
        }
        
        public function 
connect() {
            
            
        }
        
        public function 
select() {
            
            
        }
        
        public function 
disconnect() {
            
            
        }
        
        public function 
query($query) {
            
            
        }
        
        public function 
fetch_one($sql) {
            
            
        }
        
        public function 
fetch_all($sql) {
            
            
        }
        
        public function 
fetch_object_one($sql) {
            
            
        }
        
        public function 
fetch_object_all($sql) {
            
            
        }
            
        public function 
secure($string) {
            
                        
        }
        
        public function 
setTable($field$value) {
            
            
        }
        
        public function 
setCol($field$value) {
            
            
        }
        
        
    } 
As you see, we IMPLEMENT the interface. So if you guys decide to create another dbtype class, you have to implement the interface.
And ofcourse, we have to have all the functions that we defined in the interface.

PHP Code:
        public function setHandler($host$user$pass$data) {
            
            
$this->host $host;
            
$this->user $user;
            
$this->pass $pass;
            
$this->data $data;
            
            return 
$this;
            
        } 
I think this is pretty self-explenatory.
The end:
PHP Code:
return $this
..makes it possible to CHAIN the functions later when we call them and that just looks so awesome.

PHP Code:
        public function connect() {
            
            @
mysql_connect($this->host$this->user$this->pass) or die("Could not connect to the database.<br /> " .mysql_error());
            
            return 
$this;
            
        } 
I think this is pretty straight forward aswell. We return $this here aswell.

PHP Code:
        public function select() {
            
            @
mysql_select_db($this->data) or die("Could not select database.");
            
            return 
$this;
            
        } 
I'm not gonna say anything..

PHP Code:
        public function disconnect() {
            
            @
mysql_close() or die("Could not close database connection. Perhaps because the connection isn't opened.");
            
        } 
PHP Code:
        public function query($query) {
            
            
$result mysql_query($query);
            
            return 
$result;
            
        } 
Here's some new stuff, but still really basic. If you're even reading this guide, about classes and interfaces, you should definitely know how to make a mysql query!!

PHP Code:
        public function fetch_one($sql) {
            
            
$array mysql_fetch_array($sqlMYSQL_ASSOC);
            
            return 
$array;
            
        } 
PHP Code:
        public function fetch_all($sql) {
            
            
$array mysql_fetch_array($sql);
            
            return 
$array;
            
        } 
PHP Code:
        public function fetch_object_one($sql) {
            
            
$array mysql_fetch_object($sqlMYSQL_ASSOC);
            
            return 
$array;
            
        } 
PHP Code:
        public function fetch_object_all($sql) {
            
            
$array mysql_fetch_object($sql);
            
            return 
$array;
            
        } 
Fetches arrays and objects..


PHP Code:
        public function secure($string) {
            
            
$secure mysql_real_escape_string($string);
            
            return 
$secure;
                        
        } 
Secures a string from possible mysql injections.

PHP Code:
        public function setTable($field$value) {
            
            
$this->table[$field] = $value;
            
        }
        
        public function 
setCol($field$value) {
            
            
$this->col[$field] = $value;
            
        } 
These are our 2 magic functions :D
The explenation comes later.. ;)

The whole class:
PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/

    
class DBmysql implements iDB {
        
        private 
$host;
        private 
$user;
        private 
$pass;
        private 
$data;
        public 
$table = array();
        public 
$col = array();
        
        
        public function 
setHandler($host$user$pass$data) {
            
            
$this->host $host;
            
$this->user $user;
            
$this->pass $pass;
            
$this->data $data;
            
            return 
$this;
            
        }
        
        public function 
connect() {
            
            @
mysql_connect($this->host$this->user$this->pass) or die("Could not connect to the database.<br />" .mysql_error());
            
            return 
$this;
            
        }
        
        public function 
select() {
            
            @
mysql_select_db($this->data) or die("Could not select database.<br />" .mysql_error());
            
            return 
$this;
            
        }
        
        public function 
disconnect() {
            
            @
mysql_close() or die("Could not close database connection. Perhaps because the connect isn't opened.<br />" .mysql_error());
            
        }
        
        public function 
query($query) {
            
            
$result mysql_query($query) or die("Could not perform query.<br />" .mysql_error());
            
            return 
$result;
            
        }
        
        public function 
fetch_one($sql) {
            
            
$array mysql_fetch_array($sqlMYSQL_ASSOC);
            
            return 
$array;
            
        }
        
        public function 
fetch_all($sql) {
            
            
$array mysql_fetch_array($sql);
            
            return 
$array;
            
        }
        
        public function 
fetch_object_one($sql) {
            
            
$array mysql_fetch_object($sqlMYSQL_ASSOC);
            
            return 
$array;
            
        }
        
        public function 
fetch_object_all($sql) {
            
            
$array mysql_fetch_object($sql);
            
            return 
$array;
            
        }
            
        public function 
secure($string) {
            
            
$escapedstring mysql_real_escape_string($string);
            
            return 
$secure;
                        
        }
        
        public function 
setTable($field$value) {
            
            
$this->table[$field] = $value;
            
        }
        
        public function 
setCol($field$value) {
            
            
$this->col[$field] = $value;
            
        }
        
        
    } 
Did you notice btw, that the table variable, and the col variable are public??
This makes it really sweet for you when you write your plugins later :)

Section 3: The database factory

So onto the DB factory!
This is the.. ultimate thing. It makes it so easy to include the classes it's unbelievable.. :P

We name the file DB.php and the first thing we have in it is an autoload function..

PHP Code:
    function __autoload($classname) {
        
        include_once(
$classname '.php');
        
    } 
This makes it so that whenever you call ..
PHP Code:
$object = new DBmysql(); 
.. it autoincludes DBmysql file so you can create the object. You don't have to include the file in the beginning or anything! Magic! :D

Secondly, we will have the factory class:

PHP Code:
    class DB {
        
        public static 
$DB;

        public static function 
getInstance($type) {
        
            if(!
is_object(self::$DB)) {
                
                
$type strtolower($type);
                
$type 'DB'.$type;
                    
                
self::$DB = new $type();
                
            }
            
           return 
self::$DB;
    
        }

    } 
So what the **** is this?
Static??!?!

Yah! It's something awesome, and sweet, and.. completely madness :D
Static means that you can use it, without instance the DB class.

Instead of writing:
PHP Code:
$db = new DB();
echo 
$db->DB
You can just do this:
PHP Code:
echo DB::$DB
Not that you would want to echo the DB object(it's a variable, but contains an object if you called the getInstance function) but still you get the point.

So what does this getInstance do?
Well, first we check if the variable $DB is an object already, and if it's not, we do the things inside the bracket.
Also note, that when dealing with static variables or functions, we have to use self:: instead of $this.

Actually, I think this function is pretty easy to understand.
What happens is that you include DB.php
Then:
PHP Code:
$database DB::getInstance('mysql'); 
.. and it tries to include DBmysql.php, create an instance of it, and return the object.
Now don't tell me that this ain't neat? :D

NOTE: iDB.php, DB.php and DBmysql.php should be placed in the classes folder!

Section 4: The config and classes files

So the configuration file will ofcourse contain alot more when you have your plugins written, but right now we'll just include the basic stuff.
This is my configuration file:

PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/

    
$tanaxia['config']['database']['host'] = 'localhost';    // Database host
    
$tanaxia['config']['database']['user'] = 'root';        // Database user
    
$tanaxia['config']['database']['pass'] = '';            // Database pass
    
$tanaxia['config']['database']['data'] = 'testing'// Database name
    
$tanaxia['config']['database']['type'] = 'mysql';        // Database type
    
    
session_start();
    include(
'classes.php'); 
Yeh, erh.. I got kinda long variables+arrays there, but that's just so I could easially see what it is.
It's the $tanaxia variable(in this case for me it means that it's belonging to the core), and it's the ['config'] array, which means for me that it's
a setting for the core. The next array ['database'], means that it's a database setting, and then the next is defining what setting.

I then start the session, and include classes.php


Onto the classes file; this is what makes or breaks the script. Here we start all the classes, AND we use the setCol and setTable functions of the database class.
This is the classes file:
PHP Code:
/**
||||||||||||||||||||||||||||||||||||||||||
|||| @author Tanax
|||| @copyright 2008
||||||||||||||||||||||||||||||||||||||||||
**/

    
include('classes/DB.php');
    
    
$tanaxia['database'] = DB::getInstance($tanaxia['config']['database']['type']);    
    
$tanaxia['database']->setHandler(
                
                        
$tanaxia['config']['database']['host'],
                        
$tanaxia['config']['database']['user'],
                        
$tanaxia['config']['database']['pass'],
                        
$tanaxia['config']['database']['data']
                        
                        )
                        ->
connect()
                        ->
select();
                        

        
    
//$tanaxia['database']->setTable('news', 'news');
    //$tanaxia['database']->setCol('news_id', 'news_id');
    //$tanaxia['database']->setCol('news_publish', 'news_publish'); 
So, we include our DB factory.
Then we create the database, based on the type settings in our config file.

After that we set the handler with all the data provided from the config file, and then directly we chain the next function(remember the chain I talked about?) and connect to
the host, and then select the database.

That's really everything we've done now.

The things that are commented describes how to use the setTable.

The good things with that, is that later when you use the db object in the plugins(for example news plugin), you want to insert values into different columns in the database.
An example would be this:

PHP Code:
    class news {
        
        private 
$db;
        private 
$newsid;
        
        public function 
__construct($db) {
            
            
$this->db $db;
            
        }
        
        public function 
getNewsbyID($id) {
                
            if(!
is_numeric($id)) {
                    
                return 
false;
                    
            }
                
            else {
                    
                
$sql sprintf("    SELECT
                                        *
                                    FROM
                                        `%s`
                                    WHERE
                                        `%s` = '%s'
                                    AND
                                        `%s` != 0
                                    LIMIT 1"
,
                                        
                                    
$this->db->table['news'],
                                    
$this->db->col['news_id'],
                                    
$id,
                                    
$this->db->col['news_publish']);
                                        
                
$query $this->db->query($sql);
                    
                if(!
$query) {
                        
                    return 
false;
                        
                }
                    
                else {
                        
                    unset(
$this->newsid);
                    
$this->newsid $this->db->fetch_one($query);
                    return 
$this->newsid;
                        
                }
                    
            }
            
        }
        
        
    } 
As you see, we call the table news. But what if you decide to rename the table in your database and you've hardprinted `news` into the query?
Then you need to enter your class and change EVERYTHING to match the new name. And that kinda stinks.

So let's say you change the news table name to "articles".

Then you just enter your classes.php file, and change this line:
PHP Code:
$tanaxia['database']->setTable('news''news'); 
to this:
PHP Code:
$tanaxia['database']->setTable('news''articles'); 
Now, even if we in the class call the table "news", it will assosciate with "articles", so it's really easy and manageable.

NOTE: Both config.php and classes.php goes into your includes folder!

So the structure we have, looks like this right now:
Code:
www
- test
- - includes
- - - config.php
- - - classes.php
- - - classes
- - - - DB.php
- - - - iDB.php
- - - - DBmysql.php
This is everything right now! Part 2 will be about plugins :D
__________________
Tanax is offline  
Reply With Quote
The Following User Says Thank You to Tanax For This Useful Post:
hello-world (02-27-2009)
Old 07-27-2008, 10:59 PM   #2 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Anyone? >.<
__________________
Tanax is offline  
Reply With Quote
The Following User Says Thank You to Tanax For This Useful Post:
Ross (07-28-2008)
Old 07-28-2008, 11:23 AM   #3 (permalink)
The Contributor
 
Ross's Avatar
 
Join Date: Jan 2008
Location: England, UK
Posts: 83
Thanks: 3
Ross is on a distinguished road
Default

Interesting tutorial, personally I use the phpdoc comments at the start of a file e.g.

PHP Code:
/**
 * Sample file
 * @package Sample
 * @version 1.0
 * @author Ross Masters <ross@php.net> (yeah, right)
 */ 
Interfaces are useful if there is scope to write a future addition to your abstract - in this case a PostgreSQL plugin for the database system - and don't see why more people don't use them.

I'll be interested to see your plugins tutorial as I'm struggling myself with a similar project.
Ross is offline  
Reply With Quote
Old 07-28-2008, 03:23 PM   #4 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Quote:
Originally Posted by redSHIFT View Post
Interesting tutorial, personally I use the phpdoc comments at the start of a file e.g.

PHP Code:
/**
 * Sample file
 * @package Sample
 * @version 1.0
 * @author Ross Masters <ross@php.net> (yeah, right)
 */ 
Interfaces are useful if there is scope to write a future addition to your abstract - in this case a PostgreSQL plugin for the database system - and don't see why more people don't use them.

I'll be interested to see your plugins tutorial as I'm struggling myself with a similar project.
Hehe yea, well.. it wasn't really a tutorial about how to write comments though, but okey

Indeed, if they want to write an oracle db, or mysqli or w.e..
Thanks I'll write it whenever I see more interest xD
__________________
Tanax is offline  
Reply With Quote
Old 07-28-2008, 09:07 PM   #5 (permalink)
Moderateur
RegEx Guru PHP Guru Top Contributor Advanced Programmer 
 
Salathe's Avatar
 
Join Date: Apr 2007
Posts: 1,393
Thanks: 5
Salathe is on a distinguished road
Default

I've not read thoroughly through the entire article (time is money) but I do however have a few comments to offer up. Firstly, the filesystem structure itself; why is there a folder named includes when some things in there aren't simple PHP files to be included into others (e.g. the js folder)? A more suitable name would suffice, or indeed a complete separation of groups of files serving different purposes (javascript, css might be better suited outwith the PHP files' folders).

A next point, and one I won't labour too much, is the way you have written the various DB-related classes. To me at least, whether you did this knowingly or not, it all seems very MySQL-centric in how things are done. You could certainly do with working with a wider group of databases and seeing which common methods are really needed, and those which are more tailored to working with MySQL in particular.

Next, your autoloading and factory method. Why have both? Why separate the two? It's not my point to provide answers right now but it's something to consider. I will, however, note that you can only define a single __autoload function. It might (read: will) be easier to use the SPL library (e.g. spl_autoload_register) to keep the DB autoloading separate from any other autoloading which might be needed elsewhere in your project.

For the configuration file, I'd like to see things simplified much more. Have separate config files for different jobs. For example, one for the MySQL database settings, another for SQLite database settings, yet another for caching settings (if that were to be part of your application), etc. Keep the variable names within those files simple (just plain $config works fine) and make use of the include-scope when loading/using the configurations (if that's over your head, I'll explain at a later date).

Anyhow, there are some comments to tide you over until I can really sink my teeth into this come september! :)
Salathe is offline  
Reply With Quote
Old 07-29-2008, 12:10 PM   #6 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Quote:
Originally Posted by Salathe View Post
I've not read thoroughly through the entire article (time is money) but I do however have a few comments to offer up. Firstly, the filesystem structure itself; why is there a folder named includes when some things in there aren't simple PHP files to be included into others (e.g. the js folder)? A more suitable name would suffice, or indeed a complete separation of groups of files serving different purposes (javascript, css might be better suited outwith the PHP files' folders).
Because then in your templates when you "include" a css file, you use:
Code:
<link charset="utf-8" title="no title" media="screen" type="text/css" href="includes/gfx/layout.css" rel="stylesheet">
or

Code:
<script charset="utf-8" type="text/javascript" src="includes/js/mootools.js"></script>
So you can say that you include the file to be used, and thus it should be placed in includes..

Quote:
Originally Posted by Salathe View Post
A next point, and one I won't labour too much, is the way you have written the various DB-related classes. To me at least, whether you did this knowingly or not, it all seems very MySQL-centric in how things are done. You could certainly do with working with a wider group of databases and seeing which common methods are really needed, and those which are more tailored to working with MySQL in particular.
Yep. And that's because of the simple reason, that I use MySQL and not anything else. And this is why I've made the factory cause people can then write their own database classes to support THEIR database-type.

Quote:
Originally Posted by Salathe View Post
Next, your autoloading and factory method. Why have both? Why separate the two? It's not my point to provide answers right now but it's something to consider. I will, however, note that you can only define a single __autoload function. It might (read: will) be easier to use the SPL library (e.g. spl_autoload_register) to keep the DB autoloading separate from any other autoloading which might be needed elsewhere in your project.
I've used this method for ages, and I use it for almost every single system I code as a core. The thing is, you SHOULD NEVER create an instance of an object OUTSIDE of classes.php. That's the purpose of classes.php, to instanciate all the classes. Config includes classes.php, so you only have to include the config file and you'll have access to every class.
And within classes.php, you always include DB.php, thus I've placed it there. However, I could place the autoload function in classes.php instead if you like that, but it doesn't really matter the way I see it if it's in DB.php or in classes.php.

But I'll take a look at spl autoload!

[quote=Salathe;17443]
For the configuration file, I'd like to see things simplified much more. Have separate config files for different jobs. For example, one for the MySQL database settings, another for SQLite database settings, yet another for caching settings (if that were to be part of your application), etc. Keep the variable names within those files simple (just plain $config works fine) and make use of the include-scope when loading/using the configurations (if that's over your head, I'll explain at a later date).
[quote]

This is all a matter of preferences ofcourse. But you are all free to create your own variable names for your configuration file. I'm just mearly showing that you should have a variable for the dbhost, one for dbuser, etc.

The thing about several configuration files, will actually make it harder, at least to me. Why not keep it all placed in one file, which will make it alot easier to find and read the config. Instead of having to go through 10 configuration files just to find the setting that you're looking for if you're not sure where the setting is.

And about the seperate DBsettings. You should only have 1 database, so thus you can easially change that by changing the variable that contains the value for "dbtype" from "mysql" to "whateveryouwant".

Quote:
Originally Posted by Salathe View Post
Anyhow, there are some comments to tide you over until I can really sink my teeth into this come september! :)
Thanks for comments
__________________
Tanax is offline  
Reply With Quote
Old 09-28-2008, 12:27 AM   #7 (permalink)
The Visitor
 
Join Date: Sep 2008
Posts: 3
Thanks: 0
kazaan is on a distinguished road
Default

I'm very grateful for this tutorial. It helps me very much.
kazaan is offline  
Reply With Quote
Old 09-29-2008, 08:59 AM   #8 (permalink)
Jim
The Addict
 
Jim's Avatar
 
Join Date: Nov 2007
Location: the Netherlands
Posts: 281
Thanks: 2
Jim is on a distinguished road
Default

I've just written a MySQL class too few days ago. It actually resembles your class quite much. I'll post it later this week :)

Nice tut btw ;)
__________________
Nunchaku! Who doesn't like martial arts? =)
Send a message via MSN to Jim Send a message via Skype™ to Jim
Jim is offline  
Reply With Quote
Old 02-27-2009, 08:22 PM   #9 (permalink)
The Contributor
 
hello-world's Avatar
 
Join Date: Feb 2009
Posts: 73
Thanks: 30
hello-world is on a distinguished road
Default

Thanks for goood tutorial. This might also an old tut of you.
But it was help and the comments Salathe as well.
hello-world is offline  
Reply With Quote
Old 02-27-2009, 09:39 PM   #10 (permalink)
The Prestige
Upcoming Programmer Inquisitive 
 
Tanax's Avatar
 
Join Date: Sep 2007
Location: Sweden, Stockholm
Posts: 1,080
Thanks: 115
Tanax is on a distinguished road
Default

Hehe wow, people start commenting all the old tutorials I've posted xD
But I'm glad you liked it, and that it was helpful
__________________
Tanax is offline  
Reply With Quote
Old 03-01-2009, 10:08 PM   #11 (permalink)
The Contributor
 
hello-world's Avatar
 
Join Date: Feb 2009
Posts: 73
Thanks: 30
hello-world is on a distinguished road
Default

I searched the Part II. I think it does not exist. I hope you get time to finish the second part too.
hello-world is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 10:00 AM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design