nested 嵌套预加载关联

Testing Is Documentation

tests/Database/Ddd/Relation/NestedTest.phpnested 嵌套预加载关联 - 图1

预加载关联可以减少查询,并且支持嵌套,通过 . 分隔嵌套关联。

Uses

  1. <?php
  2. use Leevel\Collection\Collection;
  3. use Tests\Database\DatabaseTestCase as TestCase;
  4. use Tests\Database\Ddd\Entity\Relation\Post;
  5. use Tests\Database\Ddd\Entity\Relation\Role;
  6. use Tests\Database\Ddd\Entity\Relation\User;
  7. use Tests\Database\Ddd\Entity\Relation\UserRole;

基本使用方法

fixture 定义

Tests\Database\Ddd\Entity\Relation\Post

  1. namespace Tests\Database\Ddd\Entity\Relation;
  2. use Leevel\Database\Ddd\Entity;
  3. use Leevel\Database\Ddd\GetterSetter;
  4. use Leevel\Database\Ddd\Relation\Relation;
  5. class Post extends Entity
  6. {
  7. use GetterSetter;
  8. const TABLE = 'post';
  9. const ID = 'id';
  10. const AUTO = 'id';
  11. const STRUCT = [
  12. 'id' => [
  13. self::READONLY => true,
  14. ],
  15. 'title' => [],
  16. 'user_id' => [],
  17. 'summary' => [],
  18. 'create_at' => [],
  19. 'delete_at' => [
  20. self::CREATE_FILL => 0,
  21. ],
  22. 'user' => [
  23. self::BELONGS_TO => User::class,
  24. self::SOURCE_KEY => 'user_id',
  25. self::TARGET_KEY => 'id',
  26. ],
  27. 'comment' => [
  28. self::HAS_MANY => Comment::class,
  29. self::SOURCE_KEY => 'id',
  30. self::TARGET_KEY => 'post_id',
  31. self::RELATION_SCOPE => 'comment',
  32. ],
  33. 'post_content' => [
  34. self::HAS_ONE => PostContent::class,
  35. self::SOURCE_KEY => 'id',
  36. self::TARGET_KEY => 'post_id',
  37. ],
  38. 'user_not_defined_source_key' => [
  39. self::BELONGS_TO => User::class,
  40. self::TARGET_KEY => 'id',
  41. ],
  42. 'user_not_defined_target_key' => [
  43. self::BELONGS_TO => User::class,
  44. self::SOURCE_KEY => 'id',
  45. ],
  46. 'comment_not_defined_source_key' => [
  47. self::HAS_MANY => Comment::class,
  48. self::TARGET_KEY => 'post_id',
  49. self::RELATION_SCOPE => 'comment',
  50. ],
  51. 'comment_not_defined_target_key' => [
  52. self::HAS_MANY => Comment::class,
  53. self::SOURCE_KEY => 'id',
  54. self::RELATION_SCOPE => 'comment',
  55. ],
  56. 'post_content_not_defined_source_key' => [
  57. self::HAS_ONE => PostContent::class,
  58. self::TARGET_KEY => 'post_id',
  59. ],
  60. 'post_content_not_defined_target_key' => [
  61. self::HAS_ONE => PostContent::class,
  62. self::SOURCE_KEY => 'id',
  63. ],
  64. ];
  65. const DELETE_AT = 'delete_at';
  66. protected function relationScopeComment(Relation $relation): void
  67. {
  68. $relation->where('id', '>', 4);
  69. }
  70. }

Tests\Database\Ddd\Entity\Relation\UserRole

  1. namespace Tests\Database\Ddd\Entity\Relation;
  2. use Leevel\Database\Ddd\Entity;
  3. use Leevel\Database\Ddd\GetterSetter;
  4. class UserRole extends Entity
  5. {
  6. use GetterSetter;
  7. const TABLE = 'user_role';
  8. const ID = 'id';
  9. const AUTO = 'id';
  10. const STRUCT = [
  11. 'id' => [],
  12. 'user_id' => [],
  13. 'role_id' => [],
  14. 'create_at' => [],
  15. ];
  16. }

Tests\Database\Ddd\Entity\Relation\Role

  1. namespace Tests\Database\Ddd\Entity\Relation;
  2. use Leevel\Database\Ddd\Entity;
  3. use Leevel\Database\Ddd\GetterSetter;
  4. class Role extends Entity
  5. {
  6. use GetterSetter;
  7. const TABLE = 'role';
  8. const ID = 'id';
  9. const AUTO = 'id';
  10. const STRUCT = [
  11. 'id' => [],
  12. 'name' => [],
  13. 'create_at' => [],
  14. ];
  15. }
  1. public function testBase(): void
  2. {
  3. $posts = Post::select()->limit(5)->findAll();
  4. $this->assertInstanceof(Collection::class, $posts);
  5. $this->assertCount(0, $posts);
  6. $connect = $this->createDatabaseConnect();
  7. for ($i = 0; $i <= 5; $i++) {
  8. $this->assertSame(
  9. $i + 1,
  10. $connect
  11. ->table('post')
  12. ->insert([
  13. 'title' => 'hello world',
  14. 'user_id' => 1,
  15. 'summary' => 'Say hello to the world.',
  16. 'delete_at' => 0,
  17. ])
  18. );
  19. }
  20. $this->assertSame(
  21. 1,
  22. $connect
  23. ->table('user')
  24. ->insert([
  25. 'name' => 'niu',
  26. ])
  27. );
  28. $this->assertSame(
  29. 1,
  30. $connect
  31. ->table('role')
  32. ->insert([
  33. 'name' => '管理员',
  34. ])
  35. );
  36. $this->assertSame(
  37. 2,
  38. $connect
  39. ->table('role')
  40. ->insert([
  41. 'name' => '版主',
  42. ])
  43. );
  44. $this->assertSame(
  45. 3,
  46. $connect
  47. ->table('role')
  48. ->insert([
  49. 'name' => '会员',
  50. ])
  51. );
  52. $this->assertSame(
  53. 1,
  54. $connect
  55. ->table('user_role')
  56. ->insert([
  57. 'user_id' => 1,
  58. 'role_id' => 1,
  59. ])
  60. );
  61. $this->assertSame(
  62. 2,
  63. $connect
  64. ->table('user_role')
  65. ->insert([
  66. 'user_id' => 1,
  67. 'role_id' => 3,
  68. ])
  69. );
  70. $posts = Post::eager(['user.role'])
  71. ->limit(5)
  72. ->findAll();
  73. $this->assertInstanceof(Collection::class, $posts);
  74. $this->assertCount(5, $posts);
  75. $post = Post::select()->where('id', 1)->findOne();
  76. $this->assertSame(1, $post->id);
  77. $this->assertSame(1, $post['id']);
  78. $this->assertSame(1, $post->getId());
  79. $this->assertSame(1, $post->user_id);
  80. $this->assertSame(1, $post->userId);
  81. $this->assertSame(1, $post['user_id']);
  82. $this->assertSame(1, $post->getUserId());
  83. $this->assertSame('hello world', $post->title);
  84. $this->assertSame('hello world', $post['title']);
  85. $this->assertSame('hello world', $post->getTitle());
  86. $this->assertSame('Say hello to the world.', $post->summary);
  87. $this->assertSame('Say hello to the world.', $post['summary']);
  88. $this->assertSame('Say hello to the world.', $post->getSummary());
  89. $user = $post->user;
  90. $this->assertInstanceof(User::class, $user);
  91. $this->assertSame(1, $user->id);
  92. $this->assertSame(1, $user['id']);
  93. $this->assertSame(1, $user->getId());
  94. $this->assertSame('niu', $user->name);
  95. $this->assertSame('niu', $user['name']);
  96. $this->assertSame('niu', $user->getName());
  97. $role = $user->role;
  98. $this->assertInstanceof(Collection::class, $role);
  99. $user1 = $role[0];
  100. $this->assertInstanceof(Role::class, $user1);
  101. $this->assertSame(1, $user1->id);
  102. $this->assertSame(1, $user1['id']);
  103. $this->assertSame(1, $user1->getId());
  104. $this->assertSame('管理员', $user1->name);
  105. $this->assertSame('管理员', $user1['name']);
  106. $this->assertSame('管理员', $user1->getName());
  107. $user2 = $role[1];
  108. $this->assertInstanceof(Role::class, $user2);
  109. $this->assertSame(3, $user2->id);
  110. $this->assertSame(3, $user2['id']);
  111. $this->assertSame(3, $user2->getId());
  112. $this->assertSame('会员', $user2->name);
  113. $this->assertSame('会员', $user2['name']);
  114. $this->assertSame('会员', $user2->getName());
  115. $this->assertCount(2, $role);
  116. $this->assertSame(1, $role[0]['id']);
  117. $this->assertSame('管理员', $role[0]['name']);
  118. $this->assertSame(3, $role[1]['id']);
  119. $this->assertSame('会员', $role[1]['name']);
  120. $middle = $role[0]->middle();
  121. $this->assertInstanceof(UserRole::class, $middle);
  122. $this->assertSame(1, $middle->userId);
  123. $this->assertSame(1, $middle->roleId);
  124. $middle = $role[1]->middle();
  125. $this->assertInstanceof(UserRole::class, $middle);
  126. $this->assertSame(1, $middle->userId);
  127. $this->assertSame(3, $middle->roleId);
  128. }