-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQueryBuilderFetcher.php
More file actions
117 lines (85 loc) · 2.78 KB
/
Copy pathQueryBuilderFetcher.php
File metadata and controls
117 lines (85 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
namespace ADT\BulkFetcher;
use Doctrine\ORM\QueryBuilder;
/**
* Vyřešení zpomalení v MySQL kvůli vysokým offsetům podle https://stackoverflow.com/a/16935313/4837606
*/
class QueryBuilderFetcher extends AbstractFetcher {
/** @var QueryBuilder */
protected $qb;
/** @var array */
protected $lastRowData = NULL;
/** @var string */
protected $entityIdentifierColumn = NULL;
/** @var array */
protected $queryHints = [];
public function setHint($name, $value)
{
$this->queryHints[$name] = $value;
return $this;
}
/**
* QueryBuilderFetcher constructor.
* @param QueryBuilder $qb
* @param int $batch
* @param string $entityIdentifierColumn
*/
public function __construct(QueryBuilder $qb, $batch = 100, $entityIdentifierColumn = 'e.id') {
parent::__construct($batch);
$this->qb = $qb;
$this->entityIdentifierColumn = $entityIdentifierColumn;
$this->lastRowData = [
$this->entityIdentifierColumn => 0,
];
$this->qb->andWhere("{$this->entityIdentifierColumn} > :".static::param($this->entityIdentifierColumn));
$this->qb->orderBy("{$this->entityIdentifierColumn}", 'ASC');
}
protected function loadNewData() {
foreach ($this->lastRowData as $columnName => $value) {
$this->qb->setParameter(static::param($columnName), $value);
}
$query = $this->qb
->getQuery();
foreach ($this->queryHints as $name => $value) {
$query->setHint($name, $value);
}
$data = $query
->setFirstResult(0)
->setMaxResults($this->limit)
->getResult();
if (!count($data)) {
return $data;
}
$lastRow = $data[count($data)-1];
if (!is_object($lastRow)) {
// Doctrine vrací objekt na indexu 0
$lastRow = $lastRow[0]; // TODO: možnost nastavit si callback, který vrátí atribut (viz dále)
}
foreach (array_keys($this->lastRowData) as $columnName) {
// TODO: možnost nastavit si callback, který vrátí atribut, protože to nemusí být pole objektů
$rootEntityAlias = substr($this->entityIdentifierColumn, 0, strpos($this->entityIdentifierColumn, '.')); // "e.id" -> "e"
$propertyName = str_replace(
'.',
'->',
strpos($columnName, $rootEntityAlias.'.') === 0
? substr($columnName, strpos($columnName, '.') + 1) // "e.column1" -> "column1"
: $columnName
);
$this->lastRowData[$columnName] = self::accessNestedObjectPropertyByString($propertyName, $lastRow);
}
return $data;
}
protected static function param($param)
{
// TODO: možnost nastavit si název parametru, aby náhodou nekolidoval
return 'QueryBuilderFetcher_' . str_replace('.', '__', $param);
}
public static function accessNestedObjectPropertyByString($property, $object)
{
$steps = explode("->", $property);
foreach ($steps as $step) {
$object = $object->{'get' . ucfirst($step)}();
}
return $object;
}
}