Skip to content

Commit f0612ef

Browse files
authored
Merge pull request #11 from Weebly/relationship-actual-fix
Relationship actual fix
2 parents 2781aa0 + e4c60bd commit f0612ef

File tree

4 files changed

+183
-13
lines changed

4 files changed

+183
-13
lines changed

.circleci/config.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ jobs:
33
build:
44
docker:
55
- image: circleci/php:7.1.8-browsers
6+
- image: circleci/mysql:5.7
7+
environment:
8+
- MYSQL_USER=mutate
9+
- MYSQL_PASSWORD=secret
10+
- MYSQL_DATABASE=circle-test
611
working_directory: ~/laravel-mutate
712
steps:
813
- checkout
9-
- run: sudo apt install -y libsqlite3-dev
14+
- run: sudo docker-php-ext-install pdo_mysql
1015
- run: sudo composer self-update
1116
- restore_cache:
1217
keys:
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
namespace Weebly\Mutate\Database\Eloquent\Relations;
4+
5+
use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany;
6+
7+
class BelongsToMany extends EloquentBelongsToMany
8+
{
9+
/**
10+
* If parent model uses mutator for its key, serialize the attribute.
11+
*
12+
* @return mixed
13+
*/
14+
protected function getParentKeyValue()
15+
{
16+
$value = $this->parent->{$this->parentKey};
17+
18+
if ($this->parent->hasMutator($this->parentKey)) {
19+
$value = $this->parent->serializeAttribute($this->parentKey, $value);
20+
}
21+
22+
return $value;
23+
}
24+
25+
/**
26+
* Set the where clause for the relation query.
27+
*
28+
* @return $this
29+
*/
30+
protected function addWhereConstraints()
31+
{
32+
$this->query->where(
33+
$this->getQualifiedForeignPivotKeyName(), '=', $this->getParentKeyValue()
34+
);
35+
36+
return $this;
37+
}
38+
39+
/**
40+
* Create a new pivot attachment record.
41+
*
42+
* @param int $id
43+
* @param bool $timed
44+
* @return array
45+
*/
46+
protected function baseAttachRecord($id, $timed)
47+
{
48+
$record[$this->relatedPivotKey] = $id;
49+
50+
$record[$this->foreignPivotKey] = $this->getParentKeyValue();
51+
52+
// If the record needs to have creation and update timestamps, we will make
53+
// them by calling the parent model's "freshTimestamp" method which will
54+
// provide us with a fresh timestamp in this model's preferred format.
55+
if ($timed) {
56+
$record = $this->addTimestampsToAttachment($record);
57+
}
58+
59+
return $record;
60+
}
61+
62+
/**
63+
* Create a new query builder for the pivot table.
64+
*
65+
* @return \Illuminate\Database\Query\Builder
66+
*/
67+
protected function newPivotQuery()
68+
{
69+
$query = $this->newPivotStatement();
70+
71+
foreach ($this->pivotWheres as $arguments) {
72+
call_user_func_array([$query, 'where'], $arguments);
73+
}
74+
75+
foreach ($this->pivotWhereIns as $arguments) {
76+
call_user_func_array([$query, 'whereIn'], $arguments);
77+
}
78+
79+
return $query->where($this->foreignPivotKey, $this->getParentKeyValue());
80+
}
81+
82+
/**
83+
* Get all of the IDs from the given mixed value.
84+
*
85+
* @param mixed $value
86+
* @return array
87+
*/
88+
protected function parseIds($value)
89+
{
90+
if ($value instanceof Model) {
91+
$values = [$value->getKey()];
92+
}
93+
94+
if ($value instanceof Collection) {
95+
$values = $value->modelKeys();
96+
}
97+
98+
if ($value instanceof BaseCollection) {
99+
$values = $value->toArray();
100+
}
101+
102+
if (isset($values) === false) {
103+
$values = (array) $value;
104+
}
105+
106+
if ($this->related->hasMutator($this->related->getKeyName())) {
107+
$related = $this->related;
108+
$values = array_map(function ($attribute) use ($related) {
109+
return $related->serializeAttribute($related->getKeyName(), $attribute);
110+
}, $values);
111+
}
112+
113+
return $values;
114+
}
115+
}

src/Database/Model.php

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,12 @@
44

55
use Weebly\Mutate\Database\Traits\HasMutators;
66
use Illuminate\Database\Eloquent\Model as Eloquent;
7+
use Weebly\Mutate\Database\Eloquent\Relations\BelongsToMany;
78

89
abstract class Model extends Eloquent
910
{
1011
use HasMutators;
1112

12-
/**
13-
* {@inheritdoc}
14-
*/
15-
public function getKey()
16-
{
17-
return $this->getAttributeFromArray($this->getKeyName());
18-
}
19-
2013
/**
2114
* @param string $key
2215
* @return \Illuminate\Foundation\Application|mixed
@@ -61,6 +54,51 @@ public function attributesToArray()
6154
return $attributes;
6255
}
6356

57+
/**
58+
* Define a many-to-many relationship.
59+
*
60+
* @param string $related
61+
* @param string $table
62+
* @param string $foreignPivotKey
63+
* @param string $relatedPivotKey
64+
* @param string $parentKey
65+
* @param string $relatedKey
66+
* @param string $relation
67+
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
68+
*/
69+
public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
70+
$parentKey = null, $relatedKey = null, $relation = null)
71+
{
72+
// If no relationship name was passed, we will pull backtraces to get the
73+
// name of the calling function. We will use that function name as the
74+
// title of this relation since that is a great convention to apply.
75+
if (is_null($relation)) {
76+
$relation = $this->guessBelongsToManyRelation();
77+
}
78+
79+
// First, we'll need to determine the foreign key and "other key" for the
80+
// relationship. Once we have determined the keys we'll make the query
81+
// instances as well as the relationship instances we need for this.
82+
$instance = $this->newRelatedInstance($related);
83+
84+
$foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();
85+
86+
$relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();
87+
88+
// If no table name was provided, we can guess it by concatenating the two
89+
// models using underscores in alphabetical order. The two model names
90+
// are transformed to snake case from their default CamelCase also.
91+
if (is_null($table)) {
92+
$table = $this->joiningTable($related);
93+
}
94+
95+
return new BelongsToMany(
96+
$instance->newQuery(), $this, $table, $foreignPivotKey,
97+
$relatedPivotKey, $parentKey ?: $this->getKeyName(),
98+
$relatedKey ?: $instance->getKeyName(), $relation
99+
);
100+
}
101+
64102
/**
65103
* {@inheritdoc}
66104
*/

tests/Integration/PivotMutatorTest.php renamed to tests/Integration/BelongsToManyMutatedTest.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
/**
1313
* @group integration
1414
*/
15-
class PivotMutatorTest extends TestCase
15+
class BelongsToManyMutatedTest extends TestCase
1616
{
1717
/**
1818
* @param \Illuminate\Foundation\Application $app
@@ -24,9 +24,18 @@ protected function getEnvironmentSetUp($app)
2424
$app['config']->set('app.debug', 'true');
2525
$app['config']->set('database.default', 'testbench');
2626
$app['config']->set('database.connections.testbench', [
27-
'driver' => 'sqlite',
28-
'database' => ':memory:',
27+
'driver' => 'mysql',
28+
'host' => env('DB_HOST', '127.0.0.1'),
29+
'port' => env('DB_PORT', '3306'),
30+
'database' => env('DB_DATABASE', 'circle-test'),
31+
'username' => env('DB_USERNAME', 'mutate'),
32+
'password' => env('DB_PASSWORD', 'secret'),
33+
'unix_socket' => env('DB_SOCKET', ''),
34+
'charset' => 'utf8mb4',
35+
'collation' => 'utf8mb4_unicode_ci',
2936
'prefix' => '',
37+
'strict' => true,
38+
'engine' => null,
3039
]);
3140

3241
$app->singleton('mutator', function (Application $app) {
@@ -42,6 +51,9 @@ protected function getEnvironmentSetUp($app)
4251
public function setUp()
4352
{
4453
parent::setUp();
54+
DB::connection()->getPdo()->exec('DROP TABLE IF EXISTS test_model_a');
55+
DB::connection()->getPdo()->exec('DROP TABLE IF EXISTS test_model_b');
56+
DB::connection()->getPdo()->exec('DROP TABLE IF EXISTS pivot_table');
4557

4658
Schema::create('test_model_a', function ($table) {
4759
$table->string('name');
@@ -67,7 +79,7 @@ public function testPivotRecordsGetCreated()
6779
$modelA = (new TestModelA())->create(['id' => $idA, 'name' => 'A table']);
6880
$modelB = (new TestModelB())->create(['id' => $idB, 'name' => 'B table']);
6981

70-
$modelA->testModelBs()->attach($modelB, ['extra' => 'Something Extra']);
82+
$modelA->testModelBs()->attach($idB, ['extra' => 'Something Extra']);
7183

7284
$this->assertEquals(1, $modelA->testModelBs()->count());
7385
}

0 commit comments

Comments
 (0)