1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace duxet\Rethinkdb\Eloquent; |
4
|
|
|
|
5
|
|
|
use DateTime; |
6
|
|
|
use duxet\Rethinkdb\Eloquent\Relations\BelongsTo; |
7
|
|
|
use duxet\Rethinkdb\Query\Builder as QueryBuilder; |
8
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany; |
9
|
|
|
use Illuminate\Database\Eloquent\Relations\HasOne; |
10
|
|
|
|
11
|
|
|
class Model extends \Illuminate\Database\Eloquent\Model |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* Get the format for database stored dates. |
15
|
|
|
* |
16
|
|
|
* @return string |
17
|
|
|
*/ |
18
|
|
|
protected function getDateFormat() |
19
|
|
|
{ |
20
|
|
|
return 'Y-m-d H:i:s'; |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Get the table qualified key name. |
25
|
|
|
* |
26
|
|
|
* @return string |
27
|
|
|
*/ |
28
|
|
|
public function getQualifiedKeyName() |
29
|
|
|
{ |
30
|
|
|
return $this->getKeyName(); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Ensure Timestamps are returned in DateTime. |
35
|
|
|
* |
36
|
|
|
* @param \DateTime $value |
37
|
|
|
* |
38
|
|
|
* @return \DateTime |
39
|
|
|
*/ |
40
|
|
|
protected function asDateTime($value) |
41
|
|
|
{ |
42
|
|
|
if ($value instanceof DateTime) { |
43
|
|
|
return $value; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
return new DateTime($value); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Retain DateTime format for storage. |
51
|
|
|
* |
52
|
|
|
* @param \DateTime $value |
53
|
|
|
* |
54
|
|
|
* @return string |
55
|
|
|
*/ |
56
|
|
|
public function fromDateTime($value) |
57
|
|
|
{ |
58
|
|
|
return $this->asDateTime($value); |
|
|
|
|
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Get a fresh timestamp for the model. |
63
|
|
|
* |
64
|
|
|
* @return \DateTime |
65
|
|
|
*/ |
66
|
|
|
public function freshTimestamp() |
67
|
|
|
{ |
68
|
|
|
return new DateTime(); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Get a new query builder instance for the connection. |
73
|
|
|
* |
74
|
|
|
* @return Builder |
75
|
|
|
*/ |
76
|
|
|
protected function newBaseQueryBuilder() |
77
|
|
|
{ |
78
|
|
|
$connection = $this->getConnection(); |
79
|
|
|
// Check the connection type |
80
|
|
|
if ($connection instanceof \duxet\Rethinkdb\Connection) { |
81
|
|
|
return new QueryBuilder($connection); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
return parent::newBaseQueryBuilder(); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Create a new Eloquent query builder for the model. |
89
|
|
|
* |
90
|
|
|
* @param \duxet\Rethinkdb\Query\Builder $query |
91
|
|
|
* |
92
|
|
|
* @return \duxet\Rethinkdb\Eloquent\Builder|static |
93
|
|
|
*/ |
94
|
|
|
public function newEloquentBuilder($query) |
95
|
|
|
{ |
96
|
|
|
return new Builder($query); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* Define an inverse one-to-one or many relationship. |
101
|
|
|
* |
102
|
|
|
* @param string $related |
103
|
|
|
* @param string $foreignKey |
104
|
|
|
* @param string $otherKey |
105
|
|
|
* @param string $relation |
106
|
|
|
* |
107
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo |
108
|
|
|
*/ |
109
|
|
|
public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null) |
110
|
|
|
{ |
111
|
|
|
// If no relation name was given, we will use this debug backtrace to extract |
112
|
|
|
// the calling method's name and use that as the relationship name as most |
113
|
|
|
// of the time this will be what we desire to use for the relationships. |
114
|
|
|
if (is_null($relation)) { |
115
|
|
|
list(, $caller) = debug_backtrace(false, 2); |
116
|
|
|
$relation = $caller['function']; |
117
|
|
|
} |
118
|
|
|
// If no foreign key was supplied, we can use a backtrace to guess the proper |
119
|
|
|
// foreign key name by using the name of the relationship function, which |
120
|
|
|
// when combined with an "_id" should conventionally match the columns. |
121
|
|
|
if (is_null($foreignKey)) { |
122
|
|
|
$foreignKey = snake_case($relation).'_id'; |
123
|
|
|
} |
124
|
|
|
$instance = new $related(); |
125
|
|
|
// Once we have the foreign key names, we'll just create a new Eloquent query |
126
|
|
|
// for the related models and returns the relationship instance which will |
127
|
|
|
// actually be responsible for retrieving and hydrating every relations. |
128
|
|
|
$query = $instance->newQuery(); |
129
|
|
|
$otherKey = $otherKey ?: $instance->getKeyName(); |
130
|
|
|
|
131
|
|
|
return new BelongsTo($query, $this, $foreignKey, $otherKey, $relation); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Define a one-to-one relationship. |
136
|
|
|
* |
137
|
|
|
* @param string $related |
138
|
|
|
* @param string $foreignKey |
139
|
|
|
* @param string $localKey |
140
|
|
|
* |
141
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne |
142
|
|
|
*/ |
143
|
|
View Code Duplication |
public function hasOne($related, $foreignKey = null, $localKey = null) |
|
|
|
|
144
|
|
|
{ |
145
|
|
|
$foreignKey = $foreignKey ?: $this->getForeignKey(); |
146
|
|
|
$instance = new $related(); |
147
|
|
|
$localKey = $localKey ?: $this->getKeyName(); |
148
|
|
|
|
149
|
|
|
return new HasOne($instance->newQuery(), $this, $foreignKey, $localKey); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Define a one-to-many relationship. |
154
|
|
|
* |
155
|
|
|
* @param string $related |
156
|
|
|
* @param string $foreignKey |
157
|
|
|
* @param string $localKey |
158
|
|
|
* |
159
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany |
160
|
|
|
*/ |
161
|
|
View Code Duplication |
public function hasMany($related, $foreignKey = null, $localKey = null) |
|
|
|
|
162
|
|
|
{ |
163
|
|
|
$foreignKey = $foreignKey ?: $this->getForeignKey(); |
164
|
|
|
$instance = new $related(); |
165
|
|
|
$localKey = $localKey ?: $this->getKeyName(); |
166
|
|
|
|
167
|
|
|
return new HasMany($instance->newQuery(), $this, $foreignKey, $localKey); |
168
|
|
|
} |
169
|
|
|
} |
170
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.