DEV Community

powerwebdev
powerwebdev

Posted on

A simple PHP DAO/Controller Framework

Disclaimer: I am no PHP expert and I'm happy about all suggestions for improvement.

Aim

I wanted a really simple and easy to use framework to quickly create a simple backend in PHP that can easily be deployed just using copy&paste to a managed webserver that runs PHP and a MySQL database (as most of the cheaper hosted services).

Therefore I created a set of base classes in PHP that automatically provide the CRUD operations using reflection. It's then easy to concentrate on a nice frontend using Angular, React, etc.

This is no OR-mapping functionality, therefore the schema on the database has to be created manually.

Entities

The entities (the data objects) are simple PHP classes. They must have an $id field and a constructor accepting all fields is needed. To be able to serialize them as JSON objects, they have to implement the JsonSerializable interface. In the jsonSerialize method, all the object properties are returned via the get_object_vars method.

class User implements JsonSerializable {
    private $id;
    private $firstName;
    private $lastName;

    function __construct($id, $firstName, $lastName) {
        $this->id = $id;
        $this->firstName = $firstName;
        ...
    }

    public function getId() { ... }
    public function setId($id) { ... }
    // all getters / setters for the other properties

    public function jsonSerialize() {
        return (object) get_object_vars($this);
    }
}
Enter fullscreen mode Exit fullscreen mode

Data Access Objects

For every entity, there is a data access object. It derives from GenericDao and creates the basic CRUD operations using reflection. The SQL queries are created dynamically and are then processed via plain PDO.

For example, to find all entities, a simple SELECT * FROM query is created and the result is automatically mapped to an entity, so that, for example, instances of the class User are returned.

Therefore a DAO class has to be created that overrides the getEntityClass method:

class UserDao extends GenericDao {
    protected function getEntityClass() {
        return 'User';
    }
}
Enter fullscreen mode Exit fullscreen mode

The GenericDao then creates the query

public function findAll() {
    $query = "SELECT * FROM ".strtolower($this->getEntityClass()).";";
    $stmt = $this->dbh->prepare($query);
    if ($stmt->execute()) {
        $result = [];
        while ($row = $stmt->fetch()) {
            array_push($result, $this->mapToEntity($row));
        }
        return $result;
    }
    return [];
}
Enter fullscreen mode Exit fullscreen mode

The other methods for create, update and delete work in a similar way. For create and update also the fields of the entity are needed. This is done using the ReflectionClass class.

$this->reflection = new ReflectionClass($this->getEntityClass());
$properties = $this->reflection->getProperties(ReflectionProperty::IS_PRIVATE);
return $properties;
Enter fullscreen mode Exit fullscreen mode

Controller

For business logic a service layer would be inserted between DAOs and controllers, but for sake of simplicity I left i for now. It may be added in the future.

For the controllers a main class exists: EntityController. This class takes an instance of a concrete DAO implementation and has one function: handleRequests.

In this method the CRUD operations are defined:

  • Request method GET and url parameter ?findAll calls dao->findAll
  • Request method GET and url parameter ?findById=1 returns the entity with id = 1 (by calling dao->findById)
  • Request method PUT and url parameter ?save calls dao->insert. The entity has to be sent in the request body as json object.
  • Request method PUT and url parameter ?update calls dao->update. Again, the entity has to be in the request body.
  • Request method DELETE and url parameter ?delete=1 calls dao->delete and deletes the entity with id 1.

Continuing the User example, the controller would look like this:

header('Content-type: application/json');
$controller = new EntityController(new UserDao());
$controller->handleRequests();
Enter fullscreen mode Exit fullscreen mode

The controller can then be called by url like this: http://www.mydomain.com/api/userController.php?findAll

Summary

Of course this is not the most secure, powerful or even efficient way to do it, but it provides you with the basic CRUD operations out of the box so that you can focus on the user interface and your business logic without having to waste time on this standard stuff.

It is still work-in-progress and any feedback is welcome. As written at the beginning, my main aim is to have a simple framework that does not need much configuration and can easily used simply by copy&paste, without having to install any additional tools.

I hope this maybe helps somebody, even though it is just for learning :-)

All the current source code is available on GitHub: https://github.com/powerwebdev/php-crud-framework

Top comments (2)

Collapse
 
polivarez profile image
Pablo Olivarez

Hi man, I think you have a bug. Line 121 dao/basicDao.php
$properties[$field->getName()] = $row[$field->getName()];
Must be
$properties[] = $row[$field];
Cheers

Collapse
 
powerwebdev profile image
powerwebdev

You are absolutely right, thank you very much for the hint!