Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

php DAL - separate entity and database?

I've been researching and reading a lot about working with separate layers in PHP to create maintainable and readable code. However, I see a lot of code where the entity and the database access is placed in one class. For example:

class User{
     public $id;
     public $username;
     public $database;

     function add(){
           $database->query ....
     }
}

I find this rather strange because here you are mixing the User class with database elements which makes it more difficult to maintain.

I like working like this:

  • a separate database class
  • a user class
  • a userData class

This works like this:

$database = new Database();
$database->openConnection();
$dataUser = new DataUser($db);
$user = new User(1,"myname");
$dataUser->saveUser($user);

So I'm wondering, am I working the right way or is the first way a better way to create code? I find may way very easy to maintain because you have a separate entity and a separate database class to handle the database actions.

like image 619
randomizer Avatar asked Oct 04 '22 16:10

randomizer


2 Answers

What i do :

My models are not Entities linked to the database(when i'm not using doctrine) , so no "active record" methods. An object doesnt know how to fetch its dependencies ( for instance , a user may have n comments, my model doesnt know how to get comments ).

class User{
private $name;
private $password;
// getter and setters
}

i have services that hold some business logic that can fetch models from providers, a service can have many providers.

class UserService{
    function __construct(IUserProvider $userProvider){
        $this->userProvider = $userProvider
    }
    function getUsers(){
       // return an array of user objects
       return $this->userProvider->getUsers();

    }
}

finally i have a data provider that knows how to request datas from the database , a text file , a json file , a webservice :

 class UserProvider implements IUserProvider{
      function __construct(Connection $connection){
         $this->connection = $connection;
      }
      function getUsers(){
         return $this->toUsers($this->connection->fetchAssoc("Select * from users"));
      }
      function toUsers(array $datas){
          // convert user records to an array of User
          (...)
          return $users;
      }
 }

then the interface

interface IUserProvider{
     /**@return array an array of User */
     function getUsers();
}

if i need to get a user comments , then my comment service knows how fetch comments from a user id. So to get a user and its comments , i need 2 requests to the database. one from the UserProvider , the other from the CommentProvider.

so i have 3 layers :

  • my application layer ( display users , respond to requests whatever ... )
  • my service layer ( which has to work with a command line interface and is not aware of my web application , except for password encoding which is usually binded to the framework i use , and ACL stuffs maybe ...)
  • my data access layer which knows nothing about the other layers ,

the only way my layers communicate is through Models i pass from layer to layer.

And all my classes are built with a dependency injection container, so the wiring is not a problem.

Here is an exemple of an app i made,it's open source : https://github.com/Mparaiso/silex-bookmarkly

Any thoughts welcome.

like image 190
mpm Avatar answered Oct 10 '22 02:10

mpm


easy to maintain because you have a separate entity and a separate database class

It appears you're saying that you wish to move away from an Active Record approach to a Data Mapper/Entity/Repository approach. That's a good direction to move in because it employs better separation of concerns. You can build this yourself but you might want to take a look at solutions like Doctrine where it allows you to do something along the lines of:

$product = new Product();
$product->setName($newProductName);
$entityManager->persist($product);

The $product entity is just a POPO (Plain Old PHP Object) that contains the record data and is unaware of how it's persisted and, when persistence is needed, is passed into the entity manager to take care of the storing.

like image 20
webbiedave Avatar answered Oct 10 '22 03:10

webbiedave