Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Database\Eloquent\Relations;
4
 
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\Relations\Concerns\ComparesRelatedModels;
9
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
10
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
11
 
12
class BelongsTo extends Relation
13
{
14
    use ComparesRelatedModels,
15
        InteractsWithDictionary,
16
        SupportsDefaultModels;
17
 
18
    /**
19
     * The child model instance of the relation.
20
     *
21
     * @var \Illuminate\Database\Eloquent\Model
22
     */
23
    protected $child;
24
 
25
    /**
26
     * The foreign key of the parent model.
27
     *
28
     * @var string
29
     */
30
    protected $foreignKey;
31
 
32
    /**
33
     * The associated key on the parent model.
34
     *
35
     * @var string
36
     */
37
    protected $ownerKey;
38
 
39
    /**
40
     * The name of the relationship.
41
     *
42
     * @var string
43
     */
44
    protected $relationName;
45
 
46
    /**
47
     * Create a new belongs to relationship instance.
48
     *
49
     * @param  \Illuminate\Database\Eloquent\Builder  $query
50
     * @param  \Illuminate\Database\Eloquent\Model  $child
51
     * @param  string  $foreignKey
52
     * @param  string  $ownerKey
53
     * @param  string  $relationName
54
     * @return void
55
     */
56
    public function __construct(Builder $query, Model $child, $foreignKey, $ownerKey, $relationName)
57
    {
58
        $this->ownerKey = $ownerKey;
59
        $this->relationName = $relationName;
60
        $this->foreignKey = $foreignKey;
61
 
62
        // In the underlying base relationship class, this variable is referred to as
63
        // the "parent" since most relationships are not inversed. But, since this
64
        // one is we will create a "child" variable for much better readability.
65
        $this->child = $child;
66
 
67
        parent::__construct($query, $child);
68
    }
69
 
70
    /**
71
     * Get the results of the relationship.
72
     *
73
     * @return mixed
74
     */
75
    public function getResults()
76
    {
77
        if (is_null($this->child->{$this->foreignKey})) {
78
            return $this->getDefaultFor($this->parent);
79
        }
80
 
81
        return $this->query->first() ?: $this->getDefaultFor($this->parent);
82
    }
83
 
84
    /**
85
     * Set the base constraints on the relation query.
86
     *
87
     * @return void
88
     */
89
    public function addConstraints()
90
    {
91
        if (static::$constraints) {
92
            // For belongs to relationships, which are essentially the inverse of has one
93
            // or has many relationships, we need to actually query on the primary key
94
            // of the related models matching on the foreign key that's on a parent.
95
            $table = $this->related->getTable();
96
 
97
            $this->query->where($table.'.'.$this->ownerKey, '=', $this->child->{$this->foreignKey});
98
        }
99
    }
100
 
101
    /**
102
     * Set the constraints for an eager load of the relation.
103
     *
104
     * @param  array  $models
105
     * @return void
106
     */
107
    public function addEagerConstraints(array $models)
108
    {
109
        // We'll grab the primary key name of the related models since it could be set to
110
        // a non-standard name and not "id". We will then construct the constraint for
111
        // our eagerly loading query so it returns the proper models from execution.
112
        $key = $this->related->getTable().'.'.$this->ownerKey;
113
 
114
        $whereIn = $this->whereInMethod($this->related, $this->ownerKey);
115
 
116
        $this->query->{$whereIn}($key, $this->getEagerModelKeys($models));
117
    }
118
 
119
    /**
120
     * Gather the keys from an array of related models.
121
     *
122
     * @param  array  $models
123
     * @return array
124
     */
125
    protected function getEagerModelKeys(array $models)
126
    {
127
        $keys = [];
128
 
129
        // First we need to gather all of the keys from the parent models so we know what
130
        // to query for via the eager loading query. We will add them to an array then
131
        // execute a "where in" statement to gather up all of those related records.
132
        foreach ($models as $model) {
133
            if (! is_null($value = $model->{$this->foreignKey})) {
134
                $keys[] = $value;
135
            }
136
        }
137
 
138
        sort($keys);
139
 
140
        return array_values(array_unique($keys));
141
    }
142
 
143
    /**
144
     * Initialize the relation on a set of models.
145
     *
146
     * @param  array  $models
147
     * @param  string  $relation
148
     * @return array
149
     */
150
    public function initRelation(array $models, $relation)
151
    {
152
        foreach ($models as $model) {
153
            $model->setRelation($relation, $this->getDefaultFor($model));
154
        }
155
 
156
        return $models;
157
    }
158
 
159
    /**
160
     * Match the eagerly loaded results to their parents.
161
     *
162
     * @param  array  $models
163
     * @param  \Illuminate\Database\Eloquent\Collection  $results
164
     * @param  string  $relation
165
     * @return array
166
     */
167
    public function match(array $models, Collection $results, $relation)
168
    {
169
        $foreign = $this->foreignKey;
170
 
171
        $owner = $this->ownerKey;
172
 
173
        // First we will get to build a dictionary of the child models by their primary
174
        // key of the relationship, then we can easily match the children back onto
175
        // the parents using that dictionary and the primary key of the children.
176
        $dictionary = [];
177
 
178
        foreach ($results as $result) {
179
            $attribute = $this->getDictionaryKey($result->getAttribute($owner));
180
 
181
            $dictionary[$attribute] = $result;
182
        }
183
 
184
        // Once we have the dictionary constructed, we can loop through all the parents
185
        // and match back onto their children using these keys of the dictionary and
186
        // the primary key of the children to map them onto the correct instances.
187
        foreach ($models as $model) {
188
            $attribute = $this->getDictionaryKey($model->{$foreign});
189
 
190
            if (isset($dictionary[$attribute])) {
191
                $model->setRelation($relation, $dictionary[$attribute]);
192
            }
193
        }
194
 
195
        return $models;
196
    }
197
 
198
    /**
199
     * Associate the model instance to the given parent.
200
     *
201
     * @param  \Illuminate\Database\Eloquent\Model|int|string|null  $model
202
     * @return \Illuminate\Database\Eloquent\Model
203
     */
204
    public function associate($model)
205
    {
206
        $ownerKey = $model instanceof Model ? $model->getAttribute($this->ownerKey) : $model;
207
 
208
        $this->child->setAttribute($this->foreignKey, $ownerKey);
209
 
210
        if ($model instanceof Model) {
211
            $this->child->setRelation($this->relationName, $model);
212
        } else {
213
            $this->child->unsetRelation($this->relationName);
214
        }
215
 
216
        return $this->child;
217
    }
218
 
219
    /**
220
     * Dissociate previously associated model from the given parent.
221
     *
222
     * @return \Illuminate\Database\Eloquent\Model
223
     */
224
    public function dissociate()
225
    {
226
        $this->child->setAttribute($this->foreignKey, null);
227
 
228
        return $this->child->setRelation($this->relationName, null);
229
    }
230
 
231
    /**
232
     * Alias of "dissociate" method.
233
     *
234
     * @return \Illuminate\Database\Eloquent\Model
235
     */
236
    public function disassociate()
237
    {
238
        return $this->dissociate();
239
    }
240
 
241
    /**
242
     * Add the constraints for a relationship query.
243
     *
244
     * @param  \Illuminate\Database\Eloquent\Builder  $query
245
     * @param  \Illuminate\Database\Eloquent\Builder  $parentQuery
246
     * @param  array|mixed  $columns
247
     * @return \Illuminate\Database\Eloquent\Builder
248
     */
249
    public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
250
    {
251
        if ($parentQuery->getQuery()->from == $query->getQuery()->from) {
252
            return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
253
        }
254
 
255
        return $query->select($columns)->whereColumn(
256
            $this->getQualifiedForeignKeyName(), '=', $query->qualifyColumn($this->ownerKey)
257
        );
258
    }
259
 
260
    /**
261
     * Add the constraints for a relationship query on the same table.
262
     *
263
     * @param  \Illuminate\Database\Eloquent\Builder  $query
264
     * @param  \Illuminate\Database\Eloquent\Builder  $parentQuery
265
     * @param  array|mixed  $columns
266
     * @return \Illuminate\Database\Eloquent\Builder
267
     */
268
    public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
269
    {
270
        $query->select($columns)->from(
271
            $query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash()
272
        );
273
 
274
        $query->getModel()->setTable($hash);
275
 
276
        return $query->whereColumn(
277
            $hash.'.'.$this->ownerKey, '=', $this->getQualifiedForeignKeyName()
278
        );
279
    }
280
 
281
    /**
282
     * Determine if the related model has an auto-incrementing ID.
283
     *
284
     * @return bool
285
     */
286
    protected function relationHasIncrementingId()
287
    {
288
        return $this->related->getIncrementing() &&
289
            in_array($this->related->getKeyType(), ['int', 'integer']);
290
    }
291
 
292
    /**
293
     * Make a new related instance for the given model.
294
     *
295
     * @param  \Illuminate\Database\Eloquent\Model  $parent
296
     * @return \Illuminate\Database\Eloquent\Model
297
     */
298
    protected function newRelatedInstanceFor(Model $parent)
299
    {
300
        return $this->related->newInstance();
301
    }
302
 
303
    /**
304
     * Get the child of the relationship.
305
     *
306
     * @return \Illuminate\Database\Eloquent\Model
307
     */
308
    public function getChild()
309
    {
310
        return $this->child;
311
    }
312
 
313
    /**
314
     * Get the foreign key of the relationship.
315
     *
316
     * @return string
317
     */
318
    public function getForeignKeyName()
319
    {
320
        return $this->foreignKey;
321
    }
322
 
323
    /**
324
     * Get the fully qualified foreign key of the relationship.
325
     *
326
     * @return string
327
     */
328
    public function getQualifiedForeignKeyName()
329
    {
330
        return $this->child->qualifyColumn($this->foreignKey);
331
    }
332
 
333
    /**
334
     * Get the key value of the child's foreign key.
335
     *
336
     * @return mixed
337
     */
338
    public function getParentKey()
339
    {
340
        return $this->child->{$this->foreignKey};
341
    }
342
 
343
    /**
344
     * Get the associated key of the relationship.
345
     *
346
     * @return string
347
     */
348
    public function getOwnerKeyName()
349
    {
350
        return $this->ownerKey;
351
    }
352
 
353
    /**
354
     * Get the fully qualified associated key of the relationship.
355
     *
356
     * @return string
357
     */
358
    public function getQualifiedOwnerKeyName()
359
    {
360
        return $this->related->qualifyColumn($this->ownerKey);
361
    }
362
 
363
    /**
364
     * Get the value of the model's associated key.
365
     *
366
     * @param  \Illuminate\Database\Eloquent\Model  $model
367
     * @return mixed
368
     */
369
    protected function getRelatedKeyFrom(Model $model)
370
    {
371
        return $model->{$this->ownerKey};
372
    }
373
 
374
    /**
375
     * Get the name of the relationship.
376
     *
377
     * @return string
378
     */
379
    public function getRelationName()
380
    {
381
        return $this->relationName;
382
    }
383
}