sFire PHP Framework

MySQLi Entity

In Domain Driven Design, an Entity is an object that is not defined by its attributes, but rather by a thread of continuity and its identity. So for example, a customer is an entity because you can change the customers email address without changing the identity of the customer. This is because the customer has an id so even when you change the customers attributes, it is still the same customer. An entity can be a user, an order, a product, a blog post, really anything with an identity.

sFire lets you create and store entities to the database and even creates entities automatically from records from a database table.

In this section we will handle:

  • Creating entities
  • Dynamic entities
  • Hard coded entities
  • Load data using DBtables
  • Load data from Array
  • Overwrite default table name
  • Save entity data to database
  • Delete entity from database
  • Refresh entity
  • Export entities to Arrays, Objects and Json strings
  • Events
  • Converting dates to DateTime objects automatically

Creating entities

For example purposes, we create a customer entity. Create a file called "EntityCustomer.php" in "modules/{YOUR-MODULE-NAME}/models/entity/".

There are two ways of defining the entity. Dynamically or hard coded entities which are described below.

Dynamic entities

Dynamic entities have the advantage that you don't need to write all the getters and setters for all different properties/columns. You can set new data by using the fromArray, then you can use the getters and setters to set and retrieve individual properties/columns.

Blueprint / Example

In the example below we created a dynamic customer entity.

namespace App\models\entity;

use sFire\DB\Driver\MySQLi\Entity;

class EntityCustomer extends Entity {

    public function __construct() {
        $this -> setIdentifier(['id']);
    }
}
Set and retrieve data dynamically

You can use the fromArray method to fill the data from an existing Array.

use App\models\entity\EntityCustomer;

$customer = new EntityCustomer();
$customer -> fromArray(['id' => '1', 'name' => 'John Smith']);

Now you can set new data or retrieve the data by using setters and getters.

$name = $customer -> getName();
echo $name; //Outputs "John Smith"

$customer -> setName('William Jones');
$name = $customer -> getName();
echo $name; //Outputs "William Jones"

Note: You can only set or get properties that have been set with the fromArray method. The reason behind this, is that if you only use a setter and getter and want to save the entity to a database, sFire won't know what the database columns are named. Maybe you use underscores or camelcase column names.

Hard coded entities

Hard coded entities have the advantage that you can create an entity from scratch and use the setters to set all the data to save it to the database without using the fromArray method to set all the data. Another advantage is that you know beforehand which properties an entity has. You can also use the "get_class_methods" from PHP to return all methods of an entity.

Blueprint / Example

In the example below, a customer has an "id" and a "name", so our entity would look like:

namespace App\models\entity;

use sFire\DB\Driver\MySQLi\Entity;

class EntityCustomer extends Entity {

    protected $id;
    protected $name;

    public function __construct() {
        $this -> setIdentifier(['id']);
    }

    public function getId() {
        return $this -> id;
    }

    public function setId($id) {
        $this -> id = $id;
    }

    public function getName() {
        return $this -> name;
    }

    public function setName($name) {
        $this -> name = $name;
    }
}

Note: Properties should always be a protected property and should be named after the columns of the database table/scheme it represents.

Note: Methods will be converted to camelcase. For example, if you have a property/column named "customer_id", the getter and setter methods would be "getCustomerId" and "setCustomerId".

Set and retrieve data dynamically

You can directly use the setters and getters of the entity to retrieve and store data.

use App\models\entity\EntityCustomer;

$customer = new EntityCustomer();
$customer -> setId(1);
$customer -> setName('John Smith');

$id = $customer -> getId();
echo $id; //Outputs "1"

Load data using DBtables

Creating entities from a DBTable is easy. Use the select method to query the database and the result set will create entities by default.

class DBTableCustomer extends TableGateway {

    public function getCustomers() {

        $customers = $this -> select('SELECT id, name FROM customer');

        foreach($customers as $customer) {
            echo $customer -> getName(); //Will output similar to "John Smith"
        }
    }
}

Note: If you alter an entity and try to save it to a database, sFire uses by default the database adapter that was used to retrieve the entity.

Load data from Array

You can also create entities from an existing Array.

$customer = new EntityCustomer();
$customer -> fromArray(['id' => 1, 'name' => 'John Smith']);

echo $customer -> getName(); //Outputs "John Smith"

Note: The fromArray method will use the hard coded setters from the entity if exists. Otherwise it will create the getters and setters dynamically.

Note: It is possible to use hard coded and dynamically methods at the same time.

Overwrite default table name

sFire will snakecase the table name. The table name is extracted from the name of the entity. So "EntityCustomerRelations" will be converted to "customer_relations" as table name. To overwrite this, you can use the setTable method in the constructor.

public function __construct() {

    $this -> setIdentifier(['id']);
    $this -> setTable('customerRelations'); //Use this table name for deleting and saving entities
}

Save entity data to database

To save the data from an entity to a database table, you should first set a database adapter.

In the DBTable you can use the getAdapter method to set the adapter. In the example below, we create a new customer and save all the data to the database using the save method.

class DBTableCustomer extends TableGateway {

    public function create() {

        $customer = new EntityCustomer();
        $customer -> setAdapter($this -> getAdapter()); //Set the correct adapter
        $customer -> setName('John Smith');

        $customer -> save(); //Save the data to database

        echo $customer -> getId(); //Output similar to "25"
    }
}

When the customer already exists, it will update the data in the database. Otherwise it will insert a new record. When inserting a new record, the last inserted id will be used in the first identifier method. For example, if you have set two identifiers (with the setIdentifier method) named "id" and "customer_id", the first identifier will be used to fill data with the last inserted id automatically.

The save method will return a Boolean true on success or false on failure.

You may use the setExclude method, to exclude properties/columns on saving. This can prevent for example error messages using generated columns in MySQL. This method accepts an Array with column names.

class EntityEmployee extends Entity {

    public function __construct() {
        $this -> setIdentifier(['id']);
        $this -> setExclude(['fullname']);
    }
}

Refresh entity

After, for example, saving an entity into the database, there are times when you have to rebuild the stored entity in order to return the updated data. When you save an entity and it does not match the latest values from the database (such as column values entered by the database like date and timestamps), you can use the refresh method.

This method retrieves the new values so that they can be used via the entity methods.

class DBTableCustomer extends TableGateway {

     public function create() {
        
         $customer = new EntityCustomer();
         $customer -> setAdapter ($this -> getAdapter ()); // Set the correct adapter
         $customer -> setName ('John Smith');
        
         $customer -> save(); // Save the data to database
         $customer -> refresh();
         $customer -> getCreatedAt();
     }
}

Without calling the refresh method, the getCreatedAt method will not be available or equals to NULL.

Delete entity from database

It is also possible to delete the entity from the database using the delete method.

$customer = new EntityCustomer();
$customer -> setAdapter($this -> getAdapter()); //Set the correct adapter
$customer -> setId(1);
$customer -> delete(); //Deleting the row from the customer table which has a column id that matches 1

The delete method will return a Boolean true on success or false on failure.

This will only work if the identifier have been set with the setIdentifier method:

class EntityEmployee extends Entity {

    public function __construct() {
        $this -> setIdentifier(['id']);
    }
}

Export entities

You can export the data from an entity while using the toArray, toObject or toJson methods.

To array

Exports data to an Array.

$customer = new EntityCustomer();
$customer -> setId(1);
$data = $customer -> toArray();

print_r($data); 

//Output:
Array
(
    [id] => 1
)
To object

Exports data to an Object.

$customer = new EntityCustomer();
$customer -> setId(1);
$data = $customer -> toObject();

print_r($data); 

//Output
stdClass Object
(
    [id] => 1
)
To JSON string

Exports data to a JSON string.

$customer = new EntityCustomer();
$customer -> setId(1);
$data = $customer -> toJson();

echo $data; //Outputs "{"id":1}"

Events

sFire will trigger multiple events that you can listen to. The beforeSave, afterSave, beforeDelete, afterDelete, beforeLoad and afterLoad are methods which you can use in your entity class.

Example

In the entity below, we have all the event methods that will be triggered on loading, saving and deleting an entity.

class EntityCustomer extends Entity {

    public function __construct() {
        $this -> setIdentifier(['id']);
    }

    private function beforeLoad() {
        echo 'Entity is loading!';
    }

    private function afterLoad() {
        echo 'Entity is loaded!';
    }

    private function beforeSave() {
        echo 'Entity is saving!';
    }

    private function afterSave() {
        echo 'Entity is saved!';
    }

    private function beforeDelete() {
        echo 'Entity will be deleted!';
    }

    private function afterDelete() {
        echo 'Entity is deleted!';
    }
}

Converting dates to DateTime objects automatically

Often you want to format a date that is returned by a database. Many will use the standard date functions from in the query to convert a date. Working with multiple time zones where you have to make a difference between a 12 or 24 hour clock, can be tricky using standard SQL. Instead, sFire lets you convert datatypes automatically to DateTime objects. This way, you can format the dates at PHP level.

To enable this feature, you can use the setDateFormat method in the entity constructor:

public function __construct() {

    $this -> setIdentifier(['id']); //Always set the identifier
    $this -> setDateFormat('Y-m-d H:i:s'); //Set a single date format
    $this -> setDateFormat(['Y-m-d', 'Y-m-d H:i:s']); //Set multiple date formats
}

This method accepts a String or an Array with Strings which represent a date format following the rules of formatting dates in PHP. Every time a value matches a date format that has been set with this method, the value will be converted to a sFire DateTime object which extends the functionality of the DateTime object of PHP.

DBTable

Now you can format your date from within a DBTable:

$customers = $this -> select('SELECT activated_at FROM customer');

foreach($customers as $customer) {
    echo $customer -> getActivatedAt() -> format('m-d-Y'); //Output similar to "11-09-2019"
}
Hard coded entity

You can also use the convertToDate method to convert values to DateTime objects.

class EntityCustomer extends Entity {

    protected $activated_at;

    public function __construct() {
        $this -> setIdentifier(['id']);
    }

    public function setActivatedAt($date) {
        $this -> activated_at = $this -> convertToDate($date);
    }

    public function getActivatedAt() {
        return $this -> activated_at;
    }
}

$customer = new EntityCustomer();
$customer -> setActivatedAt('2019-11-09');

$date = $customer -> getActivatedAt() -> format('m-d-Y');
echo $date; //Ouputs "11-09-2019"

The convertToDate method will return a sFire\DateTime\DateTime object if it matches a date format previous set with the setDateFormat method. Otherwise it will return the given value.