Posts 4 - Create the Blog Entity
Post
Cancel

4 - Create the Blog Entity

First we’re going to be setting up the model, or Entity, we’re going to be using.

Earlier, when we imported the test data we got a glimps of what it will look like. Let us start! Open up the post.php file and copy in the following code. We’ll have a look at it after that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
namespace Blog\Entity;

//use Application\Entity\AbstractEntity;
use Doctrine\ORM\Mapping as ORM;

/**
* Class Blog
*
* @ORM\Entity
* @ORM\Table(name="posts")
*/
//class Post extends AbstractEntity
class Post
{
    /**
    * @var int
    * @ORM\Column(name="id", type="integer", nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="IDENTITY")
    */
    protected $id;

    /**
    * @var string
    * @ORM\Column(name="title", type="string", nullable=false, length=128)
    */
    protected $title;

    /**
    * @var string
    * @ORM\Column(name="slug", type="string", nullable=true, length=128)
    */
    protected $slug;

    /**
    * @var \DateTime
    * @ORM\Column(name="created", type="datetime", nullable=false)
    */
    protected $created;

    /**
    * @var string
    * @ORM\Column(name="body", type="string", nullable=false)
    */
    protected $body;

    public function __construct()
    {
        if (empty($this->created)) {
            $this->created = new \DateTime('NOW');
        }
    }

    public function generateSlug($title = null)
    {
        if (empty($title) && !empty($this->getTitle())) {
            $title = $this->getTitle();
        }

        $slug = str_replace(' ', '-', strtolower(htmlspecialchars($title)));

        $this->setSlug($slug);

        return $this->getSlug();
    }

    /**
    * @return int
    */
    public function getId()
    {
        return $this->id;
    }

    /**
    * @param int $id
    */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
    * @return string
    */
    public function getTitle()
    {
        return $this->title;
    }

    /**
    * @param string $title
    */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
    * @return string
    */
    public function getSlug()
    {
        return $this->slug;
    }

    /**
    * @param string $slug
    */
    public function setSlug($slug)
    {
        $this->slug = $slug;
    }

    /**
    * @return \DateTime
    */
    public function getCreated()
    {
        return $this->created;
    }

    /**
    * @param \DateTime $created
    */
    public function setCreated($created)
    {
        $this->created = $created;
    }

    /**
    * @return string
    */
    public function getBody()
    {
        return $this->body;
    }

    /**
    * @param string $body
    */
    public function setBody($body)
    {
        $this->body = $body;
    }
}

Make sure to especially read through the properties and their annotations at the top of the file. Notice how we use the Doctrine\ORM\Mapping namespace in these annotations. Doctrine uses these to identify what their counterparts in the database should be. Also, the class annotations tell Doctrine that this class should be treated as an Entity, whose data is stored in the posts table in the database.

Furthermore, each property has it’s own attributes, the property $id more than the others. The annotation @ORM\Id tells Doctrine that this attribute is a Primary Key, or an identifier value. @ORM\GeneratedValue(strategy=”IDENTITY”) tells Doctrine that it should automatically create a new identifier value for this property when a new one is created. It gets the ID to use for a new property from the database.

With the $created property, notice how it is set to be a datetime object in its type annotation and that the PHP annotation for @var sets it to \DateTime. The Doctrine annotation tells it that it should expect the value of the entity property $created to be a PHP DateTime object.

Next up to take a look at is the public function generateSlug($title = null). We’re creating that here for 2 reasons. The most important being that we will have the function available to us any time that we’re going to be using the Post entity. The second reason is built upon the first, we do not want to recreate this functionality every time we use the Post entity. This would cause code multiplication and increase later maintenance. Also, it wouldn’t be DRY (Don’t Repeat Yourself).

Lastly, notice how we set the $created property in the __construct() function of this entity. We do this so that we have a pre-created DateTime object to work with when we create a new object. Don’t worry about setting the correct date and time when you’re going to use an existing Post; Doctrine takes care of setting the correct data of your object after asking for an object.

If you’re already familiar with the usage of Doctrine you might know that an Entity comes with some functions available, however, it lacks a few that I find handy. Especially during debugging. But, to have to copy those everytime I create an entity isn’t DRY. So, let’s create an AbstractEntity for ourselves and then let the Post entity extend this so we always have this.

Please create the file /module/Application/src/Application/Entity/AbstractEntity.php and copy in the following code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
namespace Application\Entity;

abstract class AbstractEntity
{
    /**
    * Gets an array copy
    */
    public function getArrayCopy()
    {
        $values = get_object_vars($this);
        foreach ($values as $property => $value) {
        // Skip relations
            if (is_object($value)) {
                unset($values[$property]);
            }
        }

        return $values;
    }

    /**
    * Maps the specified data to the properties of this object
    *
    * @param array $data
    */
    public function exchangeArray($data)
    {
        foreach ($data as $property => $value) {
            if (isset($this->$property)) {
                $method = 'set' . ucfirst($property);
                $this->$method($value);
            }
        }
    }

    /**
    * Gets associations
    */
    public function getAssociations()
    {
        $values = get_object_vars($this);
        foreach ($values as $property => $value) {
            // Skip scalar values
            if (!is_object($value)) {
                unset($values[$property]);
            }
        }

        return $values;
    }
}

These functions aren’t anything special and their names are quite self-explanatory. The last function, getAssociations() might deserve to be noted of however that it gets entities associated to the entity object your applying it on. When you’re in a further stage, long after this Blog tutorial, you might find this useful to debug data in associated entities.

Now that we’ve got an AbstractEntity object it would be good to modify our Post entity so that it extends this one. Modify the below lines below to match in the Post entity file Post.php.

1
2
3
4
5
6
7
namespace Blog\Entity;

use Application\Entity\AbstractEntity; //Insert this one
use Doctrine\ORM\Mapping as ORM;
//Doctrine annotation

class Post extends AbstractEntity

By just including the namespace and setting the class Post extends AbstractEntity you’ve made sure that the more abstract functionality will be available to for Post entities as well.

At this time please refresh your web-browsers page. It should still show the Skeleton Application homepage. If it doesn’t please check what you’ve done with the code above or the code you might’ve downloaded to see if it matches.

This post is licensed under CC BY 4.0 by the author.