数据库查询

Testing Is Documentation

tests/Database/SelectTest.php数据库查询 - 图1

Uses

  1. <?php
  2. use I18nMock;
  3. use Leevel\Cache\Manager;
  4. use Leevel\Collection\Collection;
  5. use Leevel\Database\Condition;
  6. use Leevel\Database\Page;
  7. use Leevel\Di\Container;
  8. use Leevel\Filesystem\Helper;
  9. use Leevel\Page\Page as BasePage;
  10. use stdClass;
  11. use Tests\Database\DatabaseTestCase as TestCase;

master 设置是否查询主服务器

  1. public function testMaster(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test`.* FROM `test`",
  7. [],
  8. true
  9. ]
  10. eot;
  11. $this->assertSame(
  12. $sql,
  13. $this->varJson(
  14. $connect
  15. ->table('test')
  16. ->master(true)
  17. ->findAll(true)
  18. )
  19. );
  20. }

asSome 设置以某种包装返会结果

fixture 定义

Tests\Database\AsSomeDemo

  1. namespace Tests\Database;
  2. class AsSomeDemo
  3. {
  4. public $name;
  5. public $content;
  6. public function __construct(array $data)
  7. {
  8. $this->name = $data['name'];
  9. $this->content = $data['content'];
  10. }
  11. }
  1. public function testAsSome(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $result = $connect
  12. ->table('guest_book')
  13. ->asSome(fn (...$args): AsSomeDemo => new AsSomeDemo(...$args))
  14. ->where('id', 1)
  15. ->setColumns('name,content')
  16. ->findOne();
  17. $json = <<<'eot'
  18. {
  19. "name": "tom",
  20. "content": "I love movie."
  21. }
  22. eot;
  23. $this->assertSame(
  24. $json,
  25. $this->varJson(
  26. (array) $result
  27. )
  28. );
  29. $this->assertInstanceof(AsSomeDemo::class, $result);
  30. $this->assertSame('tom', $result->name);
  31. $this->assertSame('I love movie.', $result->content);
  32. }

asCollection 设置是否以集合返回

  1. public function testAsCollectionAsDefaultFindAll(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $connect
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $result = $connect
  11. ->table('guest_book')
  12. ->asCollection()
  13. ->setColumns('name,content')
  14. ->findAll();
  15. $json = <<<'eot'
  16. [
  17. {
  18. "name": "tom",
  19. "content": "I love movie."
  20. },
  21. {
  22. "name": "tom",
  23. "content": "I love movie."
  24. },
  25. {
  26. "name": "tom",
  27. "content": "I love movie."
  28. },
  29. {
  30. "name": "tom",
  31. "content": "I love movie."
  32. },
  33. {
  34. "name": "tom",
  35. "content": "I love movie."
  36. },
  37. {
  38. "name": "tom",
  39. "content": "I love movie."
  40. }
  41. ]
  42. eot;
  43. $this->assertSame(
  44. $json,
  45. $this->varJson(
  46. $result->toArray()
  47. )
  48. );
  49. $this->assertInstanceof(Collection::class, $result);
  50. $this->assertCount(6, $result);
  51. $n = 0;
  52. foreach ($result as $key => $value) {
  53. $this->assertSame($key, $n);
  54. $this->assertInstanceof(stdClass::class, $value);
  55. $this->assertSame('tom', $value->name);
  56. $this->assertSame('I love movie.', $value->content);
  57. $n++;
  58. }
  59. }

asArray 设置返会结果为数组

  1. public function testAsArray(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $result = $connect
  12. ->table('guest_book')
  13. ->asArray()
  14. ->where('id', 1)
  15. ->setColumns('name,content')
  16. ->findOne();
  17. $json = <<<'eot'
  18. {
  19. "name": "tom",
  20. "content": "I love movie."
  21. }
  22. eot;
  23. $this->assertSame(
  24. $json,
  25. $this->varJson(
  26. $result
  27. )
  28. );
  29. $this->assertIsArray($result);
  30. $this->assertSame('tom', $result['name']);
  31. $this->assertSame('I love movie.', $result['content']);
  32. }

asArray 设置返会结果为数组支持闭包处理

  1. public function testAsArrayWithClosure(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $result = $connect
  12. ->table('guest_book')
  13. ->asArray(function (array $value): array {
  14. $value['hello'] = 'world';
  15. return $value;
  16. })
  17. ->where('id', 1)
  18. ->setColumns('name,content')
  19. ->findOne();
  20. $json = <<<'eot'
  21. {
  22. "name": "tom",
  23. "content": "I love movie.",
  24. "hello": "world"
  25. }
  26. eot;
  27. $this->assertSame(
  28. $json,
  29. $this->varJson(
  30. $result
  31. )
  32. );
  33. $this->assertIsArray($result);
  34. $this->assertSame('tom', $result['name']);
  35. $this->assertSame('I love movie.', $result['content']);
  36. }

value 返回一个字段的值

  1. public function testValue(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $name = $connect
  12. ->table('guest_book')
  13. ->where('id', 1)
  14. ->value('name');
  15. $content = $connect
  16. ->table('guest_book')
  17. ->where('id', 1)
  18. ->value('content');
  19. $this->assertSame('tom', $name);
  20. $this->assertSame('I love movie.', $content);
  21. }

list 返回一列数据

  1. public function testList(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $result = $connect
  12. ->table('guest_book')
  13. ->where('id', 1)
  14. ->list('name');
  15. $json = <<<'eot'
  16. [
  17. "tom"
  18. ]
  19. eot;
  20. $this->assertSame(
  21. $json,
  22. $this->varJson(
  23. $result
  24. )
  25. );
  26. }

list 返回一列数据支持 2 个字段

  1. public function testList2(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $result = $connect
  12. ->table('guest_book')
  13. ->where('id', 1)
  14. ->list('content', 'name');
  15. $json = <<<'eot'
  16. {
  17. "tom": "I love movie."
  18. }
  19. eot;
  20. $this->assertSame(
  21. $json,
  22. $this->varJson(
  23. $result
  24. )
  25. );
  26. }

list 返回一列数据支持英文逗号分隔字段

  1. public function testList3(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. $this->assertSame(
  6. 1,
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data),
  10. );
  11. $result = $connect
  12. ->table('guest_book')
  13. ->where('id', 1)
  14. ->list('content,name');
  15. $json = <<<'eot'
  16. {
  17. "tom": "I love movie."
  18. }
  19. eot;
  20. $this->assertSame(
  21. $json,
  22. $this->varJson(
  23. $result
  24. )
  25. );
  26. }

chunk 数据分块处理

  1. public function testChunk(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $connect
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $n = 1;
  11. $connect
  12. ->table('guest_book')
  13. ->chunk(2, function ($result, $page) use (&$n) {
  14. $this->assertInstanceof(stdClass::class, $result[0]);
  15. $this->assertSame($n * 2 - 1, (int) $result[0]->id);
  16. $this->assertSame('tom', $result[0]->name);
  17. $this->assertSame('I love movie.', $result[0]->content);
  18. $this->assertStringContainsString(date('Y-m'), $result[0]->create_at);
  19. $this->assertInstanceof(stdClass::class, $result[1]);
  20. $this->assertSame($n * 2, (int) $result[1]->id);
  21. $this->assertSame('tom', $result[1]->name);
  22. $this->assertSame('I love movie.', $result[1]->content);
  23. $this->assertStringContainsString(date('Y-m'), $result[1]->create_at);
  24. $this->assertCount(2, $result);
  25. $this->assertSame($n, $page);
  26. $n++;
  27. });
  28. }

chunk 数据分块处理支持返回 false 中断

  1. public function testChunkWhenReturnFalseAndBreak(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $connect
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $n = 1;
  11. $connect
  12. ->table('guest_book')
  13. ->chunk(2, function ($result, $page) use (&$n) {
  14. $this->assertInstanceof(stdClass::class, $result[0]);
  15. $this->assertSame($n * 2 - 1, (int) $result[0]->id);
  16. $this->assertSame('tom', $result[0]->name);
  17. $this->assertSame('I love movie.', $result[0]->content);
  18. $this->assertStringContainsString(date('Y-m'), $result[0]->create_at);
  19. $this->assertInstanceof(stdClass::class, $result[1]);
  20. $this->assertSame($n * 2, (int) $result[1]->id);
  21. $this->assertSame('tom', $result[1]->name);
  22. $this->assertSame('I love movie.', $result[1]->content);
  23. $this->assertStringContainsString(date('Y-m'), $result[1]->create_at);
  24. $this->assertCount(2, $result);
  25. $this->assertSame($n, $page);
  26. // It will break.
  27. if (2 === $n) {
  28. return false;
  29. }
  30. $n++;
  31. });
  32. }

each 数据分块处理依次回调

  1. public function testEach(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $connect
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $n = $p = 1;
  11. $connect
  12. ->table('guest_book')
  13. ->each(2, function ($value, $key, $page) use (&$n, &$p) {
  14. $this->assertInstanceof(stdClass::class, $value);
  15. $this->assertSame($n, (int) $value->id);
  16. $this->assertSame('tom', $value->name);
  17. $this->assertSame('I love movie.', $value->content);
  18. $this->assertStringContainsString(date('Y-m'), $value->create_at);
  19. $this->assertSame(($n + 1) % 2, $key);
  20. $this->assertSame($p, $page);
  21. if (1 === ($n + 1) % 2) {
  22. $p++;
  23. }
  24. $n++;
  25. });
  26. $this->assertSame(7, $n);
  27. }

each 数据分块处理依次回调支持返回 false 中断

  1. public function testEachBreak(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $connect
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $n = $p = 1;
  11. $connect
  12. ->table('guest_book')
  13. ->each(2, function ($value, $key, $page) use (&$n, &$p) {
  14. if (3 === $n) {
  15. return false;
  16. }
  17. $this->assertInstanceof(stdClass::class, $value);
  18. $this->assertSame($n, (int) $value->id);
  19. $this->assertSame('tom', $value->name);
  20. $this->assertSame('I love movie.', $value->content);
  21. $this->assertStringContainsString(date('Y-m'), $value->create_at);
  22. $this->assertSame(($n + 1) % 2, $key);
  23. $this->assertSame($p, $page);
  24. if (1 === ($n + 1) % 2) {
  25. $p++;
  26. }
  27. $n++;
  28. });
  29. $this->assertSame(3, $n);
  30. }

pageCount 取得分页查询记录数量

  1. public function testPageCount(): void
  2. {
  3. $connect = $this->createDatabaseConnect();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $connect
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $this->assertSame(
  11. 6,
  12. $connect
  13. ->table('guest_book')
  14. ->pageCount(),
  15. );
  16. $this->assertSame(
  17. 6,
  18. $connect
  19. ->table('guest_book')
  20. ->pageCount('*'),
  21. );
  22. $this->assertSame(
  23. 6,
  24. $connect
  25. ->table('guest_book')
  26. ->pageCount('id'),
  27. );
  28. }

page 分页查询

  1. public function testPage(): void
  2. {
  3. $this->initI18n();
  4. $connect = $this->createDatabaseConnect();
  5. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  6. for ($n = 0; $n <= 25; $n++) {
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data);
  10. }
  11. $page = $connect
  12. ->table('guest_book')
  13. ->page(1);
  14. $result = $page->toArray()['data'];
  15. $this->assertInstanceof(BasePage::class, $page);
  16. $this->assertInstanceof(Page::class, $page);
  17. $this->assertCount(10, $result);
  18. $n = 0;
  19. foreach ($result as $key => $value) {
  20. $this->assertSame($key, $n);
  21. $this->assertInstanceof(stdClass::class, $value);
  22. $this->assertSame('tom', $value->name);
  23. $this->assertSame('I love movie.', $value->content);
  24. $n++;
  25. }
  26. $data = <<<'eot'
  27. <div class="pagination"> <span class="pagination-total">共 26 条</span> <button class="btn-prev disabled">&#8249;</button> <ul class="pager"> <li class="number active"><a>1</a></li><li class="number"><a href="?page=2">2</a></li><li class="number"><a href="?page=3">3</a></li> </ul> <button class="btn-next" onclick="window.location.href='?page=2';">&#8250;</button> <span class="pagination-jump">前往<input type="number" link="?page={jump}" onkeydown="var event = event || window.event; if (event.keyCode == 13) { window.location.href = this.getAttribute('link').replace( '{jump}', this.value); }" onfocus="this.select();" min="1" value="1" number="true" class="pagination-editor">页</span> </div>
  28. eot;
  29. $this->assertSame(
  30. $data,
  31. $page->render()
  32. );
  33. $this->assertSame(
  34. $data,
  35. $page->toHtml()
  36. );
  37. $this->assertSame(
  38. $data,
  39. $page->__toString()
  40. );
  41. $this->assertSame(
  42. $data,
  43. (string) ($page)
  44. );
  45. $data = <<<'eot'
  46. {
  47. "per_page": 10,
  48. "current_page": 1,
  49. "total_page": 3,
  50. "total_record": 26,
  51. "total_macro": false,
  52. "from": 0,
  53. "to": 10
  54. }
  55. eot;
  56. $this->assertSame(
  57. $data,
  58. $this->varJson(
  59. $page->toArray()['page']
  60. )
  61. );
  62. $this->assertSame(
  63. $data,
  64. $this->varJson(
  65. $page->jsonSerialize()['page']
  66. )
  67. );
  68. $data = <<<'eot'
  69. {"per_page":10,"current_page":1,"total_page":3,"total_record":26,"total_macro":false,"from":0,"to":10}
  70. eot;
  71. $this->assertSame(
  72. $data,
  73. json_encode($page->toArray()['page'])
  74. );
  75. $this->clearI18n();
  76. }

page 分页带条件查询

  1. public function testPageWithCondition(): void
  2. {
  3. $this->initI18n();
  4. $connect = $this->createDatabaseConnect();
  5. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  6. for ($n = 0; $n <= 25; $n++) {
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data);
  10. }
  11. $page = $connect
  12. ->table('guest_book')
  13. ->where('id', '>', 23)
  14. ->where(function ($select) {
  15. $select->orWhere('content', 'like', '%l%')
  16. ->orWhere('content', 'like', '%o%')
  17. ->orWhere('content', 'like', '%m%');
  18. })
  19. ->page(1);
  20. $result = $page->toArray()['data'];
  21. $this->assertInstanceof(BasePage::class, $page);
  22. $this->assertInstanceof(Page::class, $page);
  23. $this->assertCount(3, $result);
  24. $n = 0;
  25. foreach ($result as $key => $value) {
  26. $this->assertSame($key, $n);
  27. $this->assertInstanceof(stdClass::class, $value);
  28. $this->assertSame('tom', $value->name);
  29. $this->assertSame('I love movie.', $value->content);
  30. $n++;
  31. }
  32. $data = <<<'eot'
  33. <div class="pagination"> <span class="pagination-total">共 3 条</span> <button class="btn-prev disabled">&#8249;</button> <ul class="pager"> </ul> <button class="btn-next disabled">&#8250;</button> <span class="pagination-jump">前往<input type="number" link="?page={jump}" onkeydown="var event = event || window.event; if (event.keyCode == 13) { window.location.href = this.getAttribute('link').replace( '{jump}', this.value); }" onfocus="this.select();" min="1" value="1" number="true" class="pagination-editor">页</span> </div>
  34. eot;
  35. $this->assertSame(
  36. $data,
  37. $page->render()
  38. );
  39. $this->assertSame(
  40. $data,
  41. $page->toHtml()
  42. );
  43. $this->assertSame(
  44. $data,
  45. $page->__toString()
  46. );
  47. $this->assertSame(
  48. $data,
  49. (string) ($page)
  50. );
  51. $data = <<<'eot'
  52. {
  53. "per_page": 10,
  54. "current_page": 1,
  55. "total_page": 1,
  56. "total_record": 3,
  57. "total_macro": false,
  58. "from": 0,
  59. "to": 3
  60. }
  61. eot;
  62. $this->assertSame(
  63. $data,
  64. $this->varJson(
  65. $page->toArray()['page']
  66. )
  67. );
  68. $this->assertSame(
  69. $data,
  70. $this->varJson(
  71. $page->jsonSerialize()['page']
  72. )
  73. );
  74. $data = <<<'eot'
  75. {"per_page":10,"current_page":1,"total_page":1,"total_record":3,"total_macro":false,"from":0,"to":3}
  76. eot;
  77. $this->assertSame(
  78. $data,
  79. json_encode($page->toArray()['page'])
  80. );
  81. $this->clearI18n();
  82. }

pageMacro 创建一个无限数据的分页查询

  1. public function testPageMacro(): void
  2. {
  3. $this->initI18n();
  4. $connect = $this->createDatabaseConnect();
  5. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  6. for ($n = 0; $n <= 25; $n++) {
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data);
  10. }
  11. $page = $connect
  12. ->table('guest_book')
  13. ->pageMacro(1);
  14. $result = $page->toArray()['data'];
  15. $this->assertInstanceof(BasePage::class, $page);
  16. $this->assertInstanceof(Page::class, $page);
  17. $this->assertCount(10, $result);
  18. $n = 0;
  19. foreach ($result as $key => $value) {
  20. $this->assertSame($key, $n);
  21. $this->assertInstanceof(stdClass::class, $value);
  22. $this->assertSame('tom', $value->name);
  23. $this->assertSame('I love movie.', $value->content);
  24. $n++;
  25. }
  26. $data = <<<'eot'
  27. <div class="pagination"> <button class="btn-prev disabled">&#8249;</button> <ul class="pager"> <li class="number active"><a>1</a></li><li class="number"><a href="?page=2">2</a></li><li class="number"><a href="?page=3">3</a></li><li class="number"><a href="?page=4">4</a></li><li class="number"><a href="?page=5">5</a></li><li class="number"><a href="?page=6">6</a></li> <li class="btn-quicknext" onclick="window.location.href='?page=6';" onmouseenter="this.innerHTML='&raquo;';" onmouseleave="this.innerHTML='...';">...</li> </ul> <button class="btn-next" onclick="window.location.href='?page=2';">&#8250;</button> <span class="pagination-jump">前往<input type="number" link="?page={jump}" onkeydown="var event = event || window.event; if (event.keyCode == 13) { window.location.href = this.getAttribute('link').replace( '{jump}', this.value); }" onfocus="this.select();" min="1" value="1" number="true" class="pagination-editor">页</span> </div>
  28. eot;
  29. $this->assertSame(
  30. $data,
  31. $page->render()
  32. );
  33. $this->assertSame(
  34. $data,
  35. $page->toHtml()
  36. );
  37. $this->assertSame(
  38. $data,
  39. $page->__toString()
  40. );
  41. $this->assertSame(
  42. $data,
  43. (string) ($page)
  44. );
  45. $data = <<<'eot'
  46. {
  47. "per_page": 10,
  48. "current_page": 1,
  49. "total_page": 100000000,
  50. "total_record": 999999999,
  51. "total_macro": true,
  52. "from": 0,
  53. "to": null
  54. }
  55. eot;
  56. $this->assertSame(
  57. $data,
  58. $this->varJson(
  59. $page->toArray()['page']
  60. )
  61. );
  62. $this->assertSame(
  63. $data,
  64. $this->varJson(
  65. $page->jsonSerialize()['page']
  66. )
  67. );
  68. $data = <<<'eot'
  69. {"per_page":10,"current_page":1,"total_page":100000000,"total_record":999999999,"total_macro":true,"from":0,"to":null}
  70. eot;
  71. $this->assertSame(
  72. $data,
  73. json_encode($page->toArray()['page'])
  74. );
  75. $this->clearI18n();
  76. }

pagePrevNext 创建一个只有上下页的分页查询

  1. public function testPagePrevNext(): void
  2. {
  3. $this->initI18n();
  4. $connect = $this->createDatabaseConnect();
  5. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  6. for ($n = 0; $n <= 25; $n++) {
  7. $connect
  8. ->table('guest_book')
  9. ->insert($data);
  10. }
  11. $page = $connect
  12. ->table('guest_book')
  13. ->pagePrevNext(1, 15);
  14. $result = $page->toArray()['data'];
  15. $this->assertInstanceof(BasePage::class, $page);
  16. $this->assertInstanceof(Page::class, $page);
  17. $this->assertCount(15, $result);
  18. $n = 0;
  19. foreach ($result as $key => $value) {
  20. $this->assertSame($key, $n);
  21. $this->assertInstanceof(stdClass::class, $value);
  22. $this->assertSame('tom', $value->name);
  23. $this->assertSame('I love movie.', $value->content);
  24. $n++;
  25. }
  26. $data = <<<'eot'
  27. <div class="pagination"> <button class="btn-prev disabled">&#8249;</button> <ul class="pager"> </ul> <button class="btn-next" onclick="window.location.href='?page=2';">&#8250;</button> <span class="pagination-jump">前往<input type="number" link="?page={jump}" onkeydown="var event = event || window.event; if (event.keyCode == 13) { window.location.href = this.getAttribute('link').replace( '{jump}', this.value); }" onfocus="this.select();" min="1" value="1" number="true" class="pagination-editor">页</span> </div>
  28. eot;
  29. $this->assertSame(
  30. $data,
  31. $page->render()
  32. );
  33. $this->assertSame(
  34. $data,
  35. $page->toHtml()
  36. );
  37. $this->assertSame(
  38. $data,
  39. $page->__toString()
  40. );
  41. $this->assertSame(
  42. $data,
  43. (string) ($page)
  44. );
  45. $data = <<<'eot'
  46. {
  47. "per_page": 15,
  48. "current_page": 1,
  49. "total_page": null,
  50. "total_record": null,
  51. "total_macro": false,
  52. "from": 0,
  53. "to": null
  54. }
  55. eot;
  56. $this->assertSame(
  57. $data,
  58. $this->varJson(
  59. $page->toArray()['page']
  60. )
  61. );
  62. $this->assertSame(
  63. $data,
  64. $this->varJson(
  65. $page->jsonSerialize()['page']
  66. )
  67. );
  68. $data = <<<'eot'
  69. {"per_page":15,"current_page":1,"total_page":null,"total_record":null,"total_macro":false,"from":0,"to":null}
  70. eot;
  71. $this->assertSame(
  72. $data,
  73. json_encode($page->toArray()['page'])
  74. );
  75. $this->clearI18n();
  76. }

forPage 根据分页设置条件

  1. public function testForPage(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test`.* FROM `test` LIMIT 114,6",
  7. [],
  8. false
  9. ]
  10. eot;
  11. $this->assertSame(
  12. $sql,
  13. $this->varJson(
  14. $connect
  15. ->table('test')
  16. ->forPage(20, 6)
  17. ->findAll(true)
  18. )
  19. );
  20. }

makeSql 获得查询字符串

  1. public function testMakeSql(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "SELECT `test`.* FROM `test`"
  7. ]
  8. eot;
  9. $this->assertSame(
  10. $sql,
  11. $this->varJson(
  12. [
  13. $connect
  14. ->table('test')
  15. ->makeSql(),
  16. ]
  17. )
  18. );
  19. }

makeSql 获得查询字符串支持集合为一个条件

  1. public function testMakeSqlWithLogicGroup(): void
  2. {
  3. $connect = $this->createDatabaseConnectMock();
  4. $sql = <<<'eot'
  5. [
  6. "(SELECT `test`.* FROM `test`)"
  7. ]
  8. eot;
  9. $this->assertSame(
  10. $sql,
  11. $this->varJson(
  12. [
  13. $connect
  14. ->table('test')
  15. ->makeSql(true),
  16. ]
  17. )
  18. );
  19. }

cache 设置查询缓存

cache 原型

  1. # Leevel\Database\Select::cache
  2. /**
  3. * 设置查询缓存.
  4. *
  5. * @return \Leevel\Database\Select
  6. */
  7. public function cache(string $name, ?int $expire = null, ?string $connect = null): self;
  1. public function testCache(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $this->assertInstanceof(Manager::class, $manager->getCache());
  13. $result = $manager
  14. ->table('guest_book')
  15. ->where('id', 2)
  16. ->findOne();
  17. $this->assertFileNotExists($cacheFile);
  18. $this->assertSame(2, $result->id);
  19. $this->assertSame('tom', $result->name);
  20. $this->assertSame('I love movie.', $result->content);
  21. $resultWithoutCache = $manager
  22. ->cache('testcachekey')
  23. ->table('guest_book')
  24. ->where('id', 2)
  25. ->findOne();
  26. // cached data
  27. $resultWithCache = $manager
  28. ->cache('testcachekey')
  29. ->table('guest_book')
  30. ->where('id', 2)
  31. ->findOne();
  32. $this->assertFileExists($cacheFile);
  33. $this->assertSame(2, $resultWithCache->id);
  34. $this->assertSame('tom', $resultWithCache->name);
  35. $this->assertSame('I love movie.', $resultWithCache->content);
  36. $this->assertEquals($result, $resultWithCache);
  37. $this->assertEquals($resultWithCache, $resultWithoutCache);
  38. $this->assertFalse($result === $resultWithCache);
  39. $this->assertFalse($resultWithCache === $resultWithoutCache);
  40. }

cache 设置查询缓存支持过期时间

  1. public function testCacheWithExpire(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->where('id', 2)
  15. ->findOne();
  16. $this->assertFileNotExists($cacheFile);
  17. $this->assertSame(2, $result->id);
  18. $this->assertSame('tom', $result->name);
  19. $this->assertSame('I love movie.', $result->content);
  20. $resultWithoutCache = $manager
  21. ->cache('testcachekey', 3600)
  22. ->table('guest_book')
  23. ->where('id', 2)
  24. ->findOne();
  25. // cached data
  26. $resultWithCache = $manager
  27. ->cache('testcachekey', 3600)
  28. ->table('guest_book')
  29. ->where('id', 2)
  30. ->findOne();
  31. $this->assertFileExists($cacheFile);
  32. $this->assertStringContainsString('[3600,', file_get_contents($cacheFile));
  33. $this->assertSame(2, $resultWithCache->id);
  34. $this->assertSame('tom', $resultWithCache->name);
  35. $this->assertSame('I love movie.', $resultWithCache->content);
  36. $this->assertEquals($result, $resultWithCache);
  37. $this->assertEquals($resultWithCache, $resultWithoutCache);
  38. $this->assertFalse($result === $resultWithCache);
  39. $this->assertFalse($resultWithCache === $resultWithoutCache);
  40. }

cache 设置查询缓存支持缓存连接

  1. public function testCacheWithConnect(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->where('id', 2)
  15. ->findOne();
  16. $this->assertFileNotExists($cacheFile);
  17. $this->assertSame(2, $result->id);
  18. $this->assertSame('tom', $result->name);
  19. $this->assertSame('I love movie.', $result->content);
  20. $resultWithoutCache = $manager
  21. ->cache('testcachekey', 3600, 'file')
  22. ->table('guest_book')
  23. ->where('id', 2)
  24. ->findOne();
  25. // cached data
  26. $resultWithCache = $manager
  27. ->cache('testcachekey', 3600, 'file')
  28. ->table('guest_book')
  29. ->where('id', 2)
  30. ->findOne();
  31. $this->assertFileExists($cacheFile);
  32. $this->assertStringContainsString('[3600,', file_get_contents($cacheFile));
  33. $this->assertSame(2, $resultWithCache->id);
  34. $this->assertSame('tom', $resultWithCache->name);
  35. $this->assertSame('I love movie.', $resultWithCache->content);
  36. $this->assertEquals($result, $resultWithCache);
  37. $this->assertEquals($resultWithCache, $resultWithoutCache);
  38. $this->assertFalse($result === $resultWithCache);
  39. $this->assertFalse($resultWithCache === $resultWithoutCache);
  40. }

cache 设置查询缓存支持查询多条记录

  1. public function testCacheFindAll(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->findAll();
  15. $this->assertFileNotExists($cacheFile);
  16. $this->assertCount(6, $result);
  17. $this->assertSame(1, $result[0]->id);
  18. $this->assertSame('tom', $result[0]->name);
  19. $this->assertSame('I love movie.', $result[0]->content);
  20. $resultWithoutCache = $manager
  21. ->cache('testcachekey')
  22. ->table('guest_book')
  23. ->findAll();
  24. // cached data
  25. $resultWithCache = $manager
  26. ->cache('testcachekey')
  27. ->table('guest_book')
  28. ->findAll();
  29. $this->assertFileExists($cacheFile);
  30. $this->assertCount(6, $resultWithCache);
  31. $this->assertSame(1, $resultWithCache[0]->id);
  32. $this->assertSame('tom', $resultWithCache[0]->name);
  33. $this->assertSame('I love movie.', $resultWithCache[0]->content);
  34. $this->assertEquals($result, $resultWithCache);
  35. $this->assertFalse($result === $resultWithCache);
  36. $this->assertEquals($resultWithCache, $resultWithoutCache);
  37. }

cache 设置查询缓存支持查询单条记录

  1. public function testCacheFindOne(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->where('id', 2)
  15. ->one()
  16. ->find();
  17. $this->assertFileNotExists($cacheFile);
  18. $this->assertSame(2, $result->id);
  19. $this->assertSame('tom', $result->name);
  20. $this->assertSame('I love movie.', $result->content);
  21. $resultWithoutCache = $manager
  22. ->cache('testcachekey')
  23. ->table('guest_book')
  24. ->where('id', 2)
  25. ->one()
  26. ->find();
  27. // cached data
  28. $resultWithCache = $manager
  29. ->cache('testcachekey')
  30. ->table('guest_book')
  31. ->where('id', 2)
  32. ->one()
  33. ->find();
  34. $this->assertFileExists($cacheFile);
  35. $this->assertSame(2, $resultWithCache->id);
  36. $this->assertSame('tom', $resultWithCache->name);
  37. $this->assertSame('I love movie.', $resultWithCache->content);
  38. $this->assertEquals($result, $resultWithCache);
  39. $this->assertFalse($result === $resultWithCache);
  40. $this->assertEquals($resultWithCache, $resultWithoutCache);
  41. }

cache 设置查询缓存支持查询总记录

  1. public function testCacheFindCount(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->findCount();
  15. $this->assertFileNotExists($cacheFile);
  16. $this->assertSame(6, $result);
  17. $resultWithoutCache = $manager
  18. ->cache('testcachekey')
  19. ->table('guest_book')
  20. ->findCount();
  21. // cached data
  22. $resultWithCache = $manager
  23. ->cache('testcachekey')
  24. ->table('guest_book')
  25. ->findCount();
  26. $this->assertFileExists($cacheFile);
  27. $this->assertSame(6, $resultWithCache);
  28. $this->assertEquals($result, $resultWithCache);
  29. $this->assertTrue($result === $resultWithCache);
  30. $this->assertEquals($resultWithCache, $resultWithoutCache);
  31. }

cache 设置查询缓存支持 select 查询方法

  1. public function testCacheSelect(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->select('SELECT * FROM guest_book');
  15. $this->assertFileNotExists($cacheFile);
  16. $this->assertCount(6, $result);
  17. $this->assertSame(1, $result[0]->id);
  18. $this->assertSame('tom', $result[0]->name);
  19. $this->assertSame('I love movie.', $result[0]->content);
  20. $resultWithoutCache = $manager
  21. ->cache('testcachekey')
  22. ->select('SELECT * FROM guest_book');
  23. // cached data
  24. $resultWithCache = $manager
  25. ->cache('testcachekey')
  26. ->select('SELECT * FROM guest_book');
  27. $this->assertFileExists($cacheFile);
  28. $this->assertCount(6, $resultWithCache);
  29. $this->assertSame(1, $resultWithCache[0]->id);
  30. $this->assertSame('tom', $resultWithCache[0]->name);
  31. $this->assertSame('I love movie.', $resultWithCache[0]->content);
  32. $this->assertEquals($result, $resultWithCache);
  33. $this->assertFalse($result === $resultWithCache);
  34. $this->assertEquals($resultWithCache, $resultWithoutCache);
  35. }

cache 设置查询缓存支持分页查询

分页查询会生成两个缓存 KEY,一种是缓存数据本身,一个是缓存分页统计数量。

分页统计数量缓存 KEY 需要加一个后缀与分页数据区分,KEY 后缀为 \Leevel\Database\Select::PAGE_COUNT_CACHE_SUFFIX

  1. public function testCachePage(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 25; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $cacheFilePageCount = $cacheDir.'/testcachekey/pagecount.php';
  13. $result = $manager
  14. ->table('guest_book')
  15. ->page(1);
  16. $this->assertFileNotExists($cacheFile);
  17. $this->assertFileNotExists($cacheFilePageCount);
  18. $resultWithoutCache = $manager
  19. ->cache('testcachekey')
  20. ->table('guest_book')
  21. ->page(1);
  22. // cached data
  23. $resultWithCache = $manager
  24. ->cache('testcachekey')
  25. ->table('guest_book')
  26. ->page(1);
  27. $this->assertFileExists($cacheFile);
  28. $this->assertFileExists($cacheFilePageCount);
  29. $this->assertEquals($result, $resultWithCache);
  30. $this->assertFalse($result === $resultWithCache);
  31. $this->assertEquals($resultWithCache, $resultWithoutCache);
  32. }

cache 设置查询缓存不支持 query 查询方法

query 是一个底层查询方法支持直接设置缓存,实际上其它的查询都会走这个 query 查询方法。

query 原型

  1. # Leevel\Database\Database::query
  2. /**
  3. * 查询数据记录.
  4. *
  5. * @param bool|int $master
  6. *
  7. * @return mixed
  8. */
  9. public function query(string $sql, array $bindParams = [], $master = false, ?string $cacheName = null, ?int $cacheExpire = null, ?string $cacheConnect = null);
  1. public function testCacheQuery(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 5; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->table('guest_book')
  14. ->query('SELECT * FROM guest_book');
  15. $this->assertFileNotExists($cacheFile);
  16. $this->assertCount(6, $result);
  17. $this->assertSame(1, $result[0]->id);
  18. $this->assertSame('tom', $result[0]->name);
  19. $this->assertSame('I love movie.', $result[0]->content);
  20. $resultWithoutCache = $manager
  21. ->query('SELECT * FROM guest_book', [], false, 'testcachekey');
  22. // cached data
  23. $resultWithCache = $manager
  24. ->query('SELECT * FROM guest_book', [], false, 'testcachekey');
  25. $this->assertFileExists($cacheFile);
  26. $this->assertCount(6, $resultWithCache);
  27. $this->assertSame(1, $resultWithCache[0]->id);
  28. $this->assertSame('tom', $resultWithCache[0]->name);
  29. $this->assertSame('I love movie.', $resultWithCache[0]->content);
  30. $this->assertEquals($result, $resultWithCache);
  31. $this->assertFalse($result === $resultWithCache);
  32. $this->assertEquals($resultWithCache, $resultWithoutCache);
  33. }

cache 设置查询缓存不支持 procedure 查询方法

procedure 是一个底层查询方法支持直接设置缓存。

procedure 原型

  1. # Leevel\Database\Database::procedure
  2. /**
  3. * 查询存储过程数据记录.
  4. *
  5. * @param bool|int $master
  6. */
  7. public function procedure(string $sql, array $bindParams = [], $master = false, ?string $cacheName = null, ?int $cacheExpire = null, ?string $cacheConnect = null): array;
  1. public function testCacheProcedure(): void
  2. {
  3. $manager = $this->createDatabaseManager();
  4. $data = ['name' => 'tom', 'content' => 'I love movie.'];
  5. for ($n = 0; $n <= 1; $n++) {
  6. $manager
  7. ->table('guest_book')
  8. ->insert($data);
  9. }
  10. $cacheDir = dirname(__DIR__).'/databaseCacheManager';
  11. $cacheFile = $cacheDir.'/testcachekey.php';
  12. $result = $manager
  13. ->procedure('CALL test_procedure(0)');
  14. $this->assertFileNotExists($cacheFile);
  15. $data = <<<'eot'
  16. [
  17. [
  18. {
  19. "name": "tom"
  20. },
  21. {
  22. "name": "tom"
  23. }
  24. ],
  25. [
  26. {
  27. "content": "I love movie."
  28. }
  29. ]
  30. ]
  31. eot;
  32. $this->assertSame(
  33. $data,
  34. $this->varJson(
  35. $result
  36. )
  37. );
  38. $resultWithoutCache = $manager
  39. ->procedure('CALL test_procedure(0)', [], false, 'testcachekey');
  40. $this->assertFileExists($cacheFile);
  41. // cached data
  42. $resultWithCache = $manager
  43. ->procedure('CALL test_procedure(0)', [], false, 'testcachekey');
  44. $this->assertFileExists($cacheFile);
  45. $this->assertSame(
  46. $data,
  47. $this->varJson(
  48. $resultWithCache
  49. )
  50. );
  51. $this->assertEquals($result, $resultWithCache);
  52. $this->assertFalse($result === $resultWithCache);
  53. $this->assertEquals($resultWithCache, $resultWithoutCache);
  54. }