@@ -25,47 +25,146 @@ You can download the source code packages from [GitHub Release Page](https://git
2525
2626## Creating a Database object
2727
28+ Create a configuration array and pass it to the constructor:
29+
2830```
31+ $config = array(
32+ 'host' => 'database-hostname',
33+ 'port' => 3306,
34+ 'dbname' => 'my-db-name',
35+ 'tablePrefix' => 'test_',
36+ 'user' => 'user',
37+ 'pass' => 'password',
38+ );
2939$db = \TgDatabase\Database($config);
3040```
3141
42+ Please notice that we provide a table prefix. It is a common practice to prefix all your
43+ tablenames like ` test_ ` . This way, you can keep several "namespaces" in your database.
44+ The prefix will later be added to your query statements whenever you use ` #__ ` in the
45+ table name (see examples below).
46+
47+ Instead of holding the credentials with the configuration, you could use a ` TgUtils\Auth\CredentialsProvider `
48+ that holds these data. ` Database ` will ignore credentials in the config array then.
49+
3250```
3351$db = \TgDatabase\Database($config, $credentialsProvider);
3452```
3553
3654## Querying objects
3755
3856```
39- TBD
57+ // Query a list of objects
58+ $arr = $db->queryList('SELECT * FROM #__devtest');
59+
60+ // Querying a single object
61+ $obj = $db->querySingle('SELECT * FROM #__devtest WHERE uid='.$uid);
62+ ```
63+
64+ The interface usually delivers ` stdClass ` objects by default. However, you can name
65+ your own data class so the data will be populated in such a class:
66+
67+ ```
68+ $arr = $db->queryList('SELECT * FROM #__devtest', 'MyNamespace\MyDataClass');
69+ $obj = $db->querySingle('SELECT * FROM #__devtest WHERE uid='.$uid, 'MyNamespace\MyDataClass');
4070```
4171
4272## Inserting, Updating and deleting objects
4373
74+ You can insert your own data classes or simply use ` stdClass ` objects or arrays:
75+
76+ ```
77+ // Use a standard class object
78+ $obj = new stdClass;
79+ $obj->name = 'test-name';
80+ $obj->email = 'test-email';
81+ $uid = $db->insert('#__devtest', $obj);
82+
83+ // Use your own data class
84+ $obj = new MyNamespace\MyDataClass($initialData);
85+ $uid = $db->insert('#__devtest', $obj);
86+
87+ // Use an array
88+ $arr = array(
89+ 'name' => 'test-name',
90+ 'email' => 'test-email'
91+ );
92+ $uid = $db->insert('#__devtest', $arr);
93+ ```
94+
95+ The ` Database ` will automatically escape and quote strings that appear as values in your new objects.
96+
97+ Updating your rows is accordingly easy. You will need the table name, the new values (as object or array) and a WHERE condition:
98+
99+ ```
100+ // Save all object values
101+ $obj->name = 'Some other name';
102+ $db->update('#__devtest', $obj, 'uid='.$obj->uid);
103+
104+ // Save values from array only
105+ $arr = array('name' => 'Another name');
106+ $db->update('#__devtest', $arr, 'uid='.$uid);
107+ ```
108+
109+ If you want to change a single object only, you also can use ` updateSingle() ` which can give you back the
110+ changed object (as ` stdClass ` )
111+
44112```
45- TBD
113+ // Update a single row
114+ $updated = $db->updateSingle('#__devtest', array('name' => 'test-value2'), 'uid='.$uid);
46115```
47116
48- # How to use the higher leveled Database Access Object
117+ And finally you can delete objects. You will need the table name and the WHERE condition:
49118
50- TBD
119+ ```
120+ // Delete a single row
121+ $db->delete('#__devtest', 'uid='.$uid);
122+ ```
123+
124+ # How to use a Database Access Object (DAO)
125+
126+ The low-level ` Database ` abstraction makes object-relational mappings already simple. However,
127+ it is still a lot of boilerplate to write, such as table names, WHERE clauses etc. A better way
128+ is provided by the ` DAO ` object. It simplifies the usage with databases a lot more.
51129
52130## Creating the DAO
53131
132+ Create a DAO by giving it the ` Database ` instance and the table name:
133+
54134```
55- $userDao = \TgDatabase\DAO($db, '#__users');
135+ $dao = \TgDatabase\DAO($db, '#__users');
136+ ```
137+
138+ The default constructor as above makes assumptions about your table:
139+
140+ 1 . It always returns ` stdClass ` objects.
141+ 1 . It assumes that your table has an ` int auto-increment ` primary key that is names ` uid ` .
142+
143+ However, you can tell ` DAO ` your specifics:
144+
56145```
146+ // Uses a specific class for the data
147+ $dao = \TgDatabase\DAO($db, '#__users', 'MyNamespace\User`);
148+
149+ // Uses a specific class and another primary key attribute
150+ $dao = \TgDatabase\DAO($db, '#__users', 'MyNamespace\User`, 'id');
151+ ```
152+
153+ ` DAO ` can actually handle non-numeric primary keys. The usage is not recommended though.
57154
58155## Finding objects
59156
157+ Finding objects will be much easier now:
158+
60159```
61160// Get user with specific ID
62- $user = $userDao ->get(3);
161+ $user = $dao ->get(3);
63162
64163// Find a singe user with a specific email address
65- $user = $userDao ->findSingle(array('email' => $email));
164+ $user = $dao ->findSingle(array('email' => $email));
66165
67166// Find all active admin users, ordered by name and email in ascending order
68- $users = $userDao ->find(array('group' => 'admin', 'active' => 1), array('name', 'email));
167+ $users = $dao ->find(array('group' => 'admin', 'active' => 1), array('name', 'email));
69168```
70169
71170## Creating, saving and deleting objects
@@ -78,33 +177,173 @@ $newUser->email = 'john.doe@example.com';
78177$newUser->password = '123456';
79178$newUser->group = 'webusers';
80179$newUser->active = 1;
180+ $newId = $dao->create($newUser);
81181
82- $newId = $userDao->create($newUser);
83-
84- // Updating a user
85- $user = $userDao->get($newId);
182+ // Updating an existing user
183+ $user = $dao->get($newId);
86184$user->name = 'Jane Doe';
87- $userDao ->save($user);
185+ $dao ->save($user);
88186
89187// Deleting a user
90- $userDao ->delete($user);
188+ $dao ->delete($user);
91189// or
92- $userDao->delete($user->uid);
190+ $dao->delete($user->uid);
191+ ```
192+
193+ ## WHERE clauses in DAO interface
194+
195+ The most simple form of a WHERE clause is the condition itself:
196+
197+ ```
198+ $users = $dao->find('group=\'admin\'');
199+ ```
200+
201+ But you would need to do the quoting and escaping your self. That's why you can have an array
202+ of all conditions that are concatenated with an ` AND ` :
203+
204+ ```
205+ $users = $dao->find(array('group' => 'admin', 'active' => 1));
206+ ```
207+
208+ Or, when an equals (` = ` ) operation is not what you need:
93209
210+ ```
211+ $users $dao->find(array(
212+ array('group', 'admin', '!='),
213+ array('active' , 1)
214+ ));
94215```
95216
217+ The default operator is equals (` = ` ), but you also can use ` != ` , ` <= ` , ` >= ` , ` < ` , ` > ` , ` IN ` and ` NOT IN ` . Latter two
218+ require arrays of values at the second position of the array:
219+
220+ ```
221+ $users = $dao->find(array(
222+ array('group', array('admin'), 'NOT IN'),
223+ array('active' , 1)
224+ ));
225+ ```
226+
227+ ## ORDER clauses in DAO interface
228+
229+ Wherever an ORDER clause can be given, there are two types:
230+
231+ ```
232+ // As string
233+ $users = $dao->find('', 'name');
234+ $users = $dao->find('', 'name DESC');
235+ $users = $dao->find('', 'name DESC, email ASC');
236+
237+ // As array
238+ $users = $dao->find('', array('name'));
239+ $users = $dao->find('', array('name DESC'));
240+ $users = $dao->find('', array('name DESC', 'email ASC'));
241+ ```
242+
243+ Default order sequence is ascending (` ASC ` ) if not specified.
244+
96245## Extending DAO
97246
247+ It is a good practice not to use ` DAO ` class directly but derive from it in your project.
248+ That way you can further abstract data access, e.g.
249+
98250```
99- TBD
251+ class Users extends DAO {
252+
253+ public function __construct($database) {
254+ parent::__construct($database, '#__users', 'MyNamespace\User');
255+ }
256+
257+ public function findByEmail($email) {
258+ return $this->findSingle(array('email' => $email));
259+ }
260+
261+ public function findByDepartment($department, $order = NULL) {
262+ return $this->find(array('department' => $email), $order);
263+ }
264+ }
100265```
101266
102267## Using Data Objects with DAOs
103268
269+ As above mentioned, you can use your own data classes. There are actually no
270+ restrictions other than the class needs a no-argument constructor. The main
271+ advantage is that this class can have additional methods that have some
272+ logic. You can even define additional attributes that will not be saved in
273+ the database by a DAO. These attributes start with an underscore (_ ).
274+
275+ Here is an example:
276+
277+ ```
278+ class User {
279+
280+ // will not be saved
281+ private $_derivedAttribute;
282+
283+ public function __construct() {
284+ // You can initialize here
285+ }
286+
287+ public function getDerivedAttribute() {
288+ // Have your logic for the attribute here
289+ // or do something completely different
290+
291+ // Return something
292+ return $this->_derivedAttribute;
293+ }
294+ }
295+ ```
296+
297+ # Using a DataModel
298+
299+ Finally, we bring everything together. The last thing we need is a central location
300+ for all our ` DAO ` s. Here comes the ` DataModel ` :
301+
104302```
105- TBD
303+
304+ // Setup the model
305+ $model = new \TGDatabase\DataModel($database);
306+ $model->register('users', $userDAO);
307+ $model->register('products', $productDAO);
308+
309+ // And use it:
310+ $products = $model->get('products')->find();
106311```
107312
313+ Of course, a better idea is to encapsulate this in your own ` DataModel ` subclass:
314+
315+ ```
316+ class MyDataModel extends \TGDatabase\DataModel {
317+
318+ public function __construct($database) {
319+ parent::__construct($database);
320+ }
321+
322+ protected function init($database) {
323+ // Optional step: call the parent method (it's empty, but could change)
324+ parent::init($database);
325+
326+ // No create your DAOs
327+ $this->register('users', new UserDAO($database));
328+ $this->register('products', new ProductDAO($database));
329+ }
330+ }
331+ ```
332+
333+ You only need to implement the ` init() ` method. Now your final application code looks
334+ much cleaner and can be read easily:
335+
336+ ```
337+ // Setup...
338+ $database = new Database($config);
339+ $myModel = new MyDataModel($database);
340+
341+ // ...and use
342+ $users = $myModel->get('users')->find();
343+ ```
344+
345+ Imagine, how much error-proned code you would have to write yourself!
346+
108347# Contribution
109348Report a bug, request an enhancement or pull request at the [ GitHub Issue Tracker] ( https://github.com/technicalguru/php-database/issues ) .
110349
0 commit comments