Read meAbout DAOs

Quick start guide

In this quick start guide, we will see how you can use TDBM to query, read and write data to your database We will assume that you succesfully installed TDBM using Mouf, and therefore, that TDBM is connected to your database and that the TDBM DAOs have been generated. You can learn more about DAO generation in the Generating DAOs guide.

Our playground data model

For this tutorial, let's assume a very classic database schema for handling users.
We have users. Users can be part of several groups, and obviously, a group can contain several users.
A group has a name.
A user has a name and is part of a country.

database schema

Connecting to the database

When you install TDBM in Mouf, you will be asked the connection to your database. This connection will be represented by a "dbConnection" instance. This instance represents a pointer to your database and can be used to execute SQL queries. But we won't be using the "dbConnection" instance. Indeed, the whole point of TDBM is to avoid writing SQL.

Upon installation, TDBM will propose you to generate the DAOs (Data Access Objects). DAOs are classes that will help you access the objects in your database. There is one DAO per table in your database. Each DAO will return "beans". Each row in your database will be represented by one instance of a bean.

Usage sample

Let's now review a few samples:

Creating a new row in the "users" table:

// Let's get the DAO
$userDao = Mouf::getUserDao();

// Create a new bean
$userBean = $userDao->getNewUser();

// Fill the columns of the bean using the setters
$userBean->setName("myName");
$userBean->setPassword(sha1("myPassword"));
$userBean->setMail("myMail");
// Any date should be passed as a PHP timestamp
$userBean->setCreateDate(time());

In the first line, Mouf::getUserDao() will return the DAO object. Since we have a "users" table, TDBM generated a "UserDao" class, and a "userDao" instance of that class. We will be using this instance to create/update/delete/search any user.

You can also notice that the "save()" method is not called. Yet, the bean will be automatically saved by TDBM before the script ends. TDBM will choose the best moment to perform the save. You can explicitly call the save method using:

$userDao->saveUser(time());

Retrieving a user bean by its primary key:

// Let's get the DAO
$userDao = Mouf::getUserDao();

// Let's get the bean
$userBean = $userDao->getUserById(42);

// Let's display the name
echo $userBean->getName();

TDBM will automatically detect the primary key of your table (of course, your table must have a primary key). There is no name convention to respect, your primary key column can be named anything ('id', 'userid', 'isuser', ...)

To use this method, the primary key must be on a single column. If your primary key is on several columns, you can still use the search method (see below)

Querying the database

Now, what about getting the list of all users and displaying their name?
Ok, that's easy, just use the getUserList() method!

// Let's get the DAO
$userDao = Mouf::getUserDao();

// Let's get the list of users
$userList = $userDao->getUserList();

// Let's display the names
foreach ($userList as $userBean) {
    /* @var $userBean UserBean */
    echo $userBean->getName()."
"; }

In our exemple, we would see John Doe
Jean Dupont
Robert Marley
Bill Shakespeare

The getXXXList method will return the list of beans. Of course, most of the time, you don't want all the rows in a database. You want to perform a query with filters.

Querying the database with filters

Now, what if I want to get something more difficult, like the list of users with name starting with a 'J'?
To do this, I need to call the getUserListByFilter method and pass the filter in parameter.

At this point, it might be a good idea to have a look at the code TDBM did generate. For the "User" table, TDBM generated 4 classes:

  • UserDaoBase: the base class that contains methods to access the "users" table. It is generated by TDBM. You should never modify this class.
  • UserDao: this class extends UserDaoBase. If you have some custom requests, you should perform them in this class. You can edit it as TDBM will never overwrite it.
  • UserBaseBean: the bean mapping the columns of the "users" table. This class contains getters and setters for each and every column of the "users" table. It is generated by TDBM and you should never modify this class.
  • UserBean: this class extends UserBaseBean. If you have some custom getters and setters, you should implement them in this class. You can edit it as TDBM will never overwrite it.

In our example, we are trying to perform a new query to retrieve any name starting with a J. This is a new kind of query. Since any request should be part of a DAO, we will add this request to the UserDao.

Therefore, our code will be:

class UserDao extends UserDaoBase {

    /**
     * Returns the list of users starting with $firstLetter
     *
     * @param string $firstLetter
     * @return array<UserBean>
     */
    public function getUsersByLetter($firstLetter) {
        // The getUserListByFilter can be used to retrieve a list of UserBean
        // It takes in parameter a filter
        return $this->getUserListByFilter(new TDBM_LikeFilter("users", "name", $firstLetter."%"));
    }
}

And you can simply use it like this:

$userDao = Mouf::getUserDao();

$users = $userDao->getUsersByLetter("J");
foreach ($users as $userBean)
{
    /* @var $userBean UserBean */
    echo $userBean->getName().'<br/>';
}

You can learn much more about filters in the "avanced section" of this documentation.

So far, so good, we have had enough play with the Users table. But the users table is not alone and it would be good to get some more information.

Navigating the object model

So what if I want to get the name of the country in which the first user is located?

// Let's get the DAO
$userDao = Mouf::getUserDao();

// Let's get the user bean
$userBean = $userDao->getUserById(42);

// Let's get the country bean
$countryBean = $userBean->getCountryBean();

// Let's display the country name
echo $countryBean->getName();

Notice how you can jump from the userBean to the countryBean using the getCountryBean method. The user table is linked to the country table, so it has a getCountryBean method!
How is this possible?
I want some data from the country table. So I want to get the countries associated to user 42. In the data model, there is a constraint between column country_id of the users table and the column country_id of the country table. Behind the scene, TDBM finds this relationship. This is a "1*" relationship, so there is only one country per user. Therefore, the country object will be directly returned.

Ok. What, now, if I want to find a user from a country.

That's easy too.

class UserDao extends UserDaoBase {
    /**
     * Returns the list of users whose country name is "$countryName"
     *
     * @param string $countryName
     * @return array<UserBean>
     */
    public function getUsersByCountryName($countryName) {
        // Behold the magic!
        return $this->getUserListByFilter(new EqualFilter("country", "name", $countryName));
    }
}

Here, we called the getUserListByFilter method passing a filter on the country table.
TDBM is smart enough to automatically detect the link between the users and the country table. You just need to tell TDBM what filter you want on any column in any table in your database model and TDBM will find the right qury for you.

Most of the time, of course, you will not pass the name of the country but the ID of the country. Actually, using TDBM you can just pass the object. Have a look!

class UserDao extends UserDaoBase {
    /**
     * Returns the list of users whose country is "$countryBean"
     *
     * @param CountryBean $countryBean
     * @return array<UserBean>
     */
    public function getUsersByCountry(CountryBean $countryBean) {
        // You can pass a CountryBean instance directly to the getUserListByFilter method!
        return $this->getUserListByFilter($countryBean);
    }
}

You would use this method like this:

// Let's get the DAO
$countryDao = Mouf::getCountryDao();
$userDao = Mouf::getUserDao();

// Let's get the country bean
$countryBean = $countryDao->getCountryById(12);

// Let's get the users from this country
$userList = $userBean->getUsersByCountry($countryBean);

// Let's display the list of users in this country
foreach ($userList as $userBean)
{
    /* @var $userBean UserBean */
    echo $userBean->getName().'<br/>';
}

So now, what if I want to find out what groups robert marley belongs to.
We saw how to access a "1" and "1" relationship, therefore, we could do it by getting "robert marley" from users, then accessing the "pivot_users_groups" objects, then accessing the "groups" objects associated to that group. But this would be definitely tedious, and the use of a pivot table to generate "**" relationships is definitely common.
Hopefully, TDBM can help here too:

// Since we are accessing groups, we will modify the GroupDao class
class GroupDao extends GroupDaoBase {
    /**
     * Returns the list of groups associated to a user
     *
     * @param UserBean $userBean
     * @return array<UserBean>
     */
    public function getGroupsForUser(UserBean $userBean) {
        // Behold the magic!
        return $this->getCountryListByFilter($userBean);
    }
}

Powerful, isn't it? TDBM automatically detected the pivot table and performed the SQL double join to retrieve the groups our user belongs too.

Actually, TDBM is much more powerful. It can perform any kind of joins between 2 tables as long as they can be related by a constraint. Let's admit that I want to find the countries of all the writers in database. Well, I can do it in one single line of code:

return $this->getCountryListByFilter(new EqualFilter("groups", "name", "writers"));

Let's now learn how to regenerate DAOs when your data model changes.

Read meAbout DAOs

Found a typo? Something is wrong in this documentation? Just fork and edit it!