Completed
Push — master ( 77a63f...cef321 )
by Restu
11:38
created

Database::like()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 3
c 1
b 0
f 1
nc 1
nop 3
dl 0
loc 5
rs 9.4285
1
<?php
2
namespace JayaCode\Framework\Core\Database;
3
4
use JayaCode\Framework\Core\Database\Connector\Connector;
5
use JayaCode\Framework\Core\Database\Connector\ConnectorMySql;
6
use JayaCode\Framework\Core\Database\Query\Grammar\Grammar;
7
use JayaCode\Framework\Core\Database\Query\Grammar\GrammarMySql;
8
use JayaCode\Framework\Core\Database\Query\Query;
9
use PDO;
10
11
/**
12
 * Class Database
13
 * @package JayaCode\Framework\Core\Database
14
 */
15
class Database
16
{
17
    /**
18
     * @var Connector
19
     */
20
    protected $connector;
21
22
    /**
23
     * @var \PDO
24
     */
25
    protected $pdo;
26
27
    /**
28
     * @var \PDOStatement
29
     */
30
    protected $statement;
31
32
    /**
33
     * @var Query
34
     */
35
    protected $query;
36
37
    /**
38
     * @var Grammar
39
     */
40
    protected $grammar;
41
42
    /**
43
     * @var array
44
     */
45
    protected $driver = [
46
        "mysql" => [
47
            "connector" => ConnectorMySql::class,
48
            "grammar" => GrammarMySql::class,
49
        ]
50
    ];
51
52
    /**
53
     * @var array
54
     */
55
    protected $config = [
56
        "driver" => "mysql",
57
58
        "host" => "",
59
        "username" => "",
60
        "password" => "",
61
62
        "dbname" => "",
63
        "options" => [
64
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
65
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
66
        ]
67
    ];
68
69
    /**
70
     * @var string
71
     */
72
    protected $model = null;
73
74
    /**
75
     * @param $config
76
     */
77
    public function __construct($config)
78
    {
79
        $options = isset($config["options"])?
80
            arr_merge_all($this->config["options"], $config["options"])
81
            :$this->config["options"];
82
83
        $this->config = arr_merge_all($this->config, $config);
84
85
        $this->config['options'] = $options;
86
        $this->initialize();
87
88
        $this->createConnection();
89
    }
90
91
    /**
92
     * @param $config
93
     * @return static
94
     */
95
    public static function create($config)
96
    {
97
        return new static($config);
98
    }
99
100
    /**
101
     *
102
     */
103
    protected function initialize()
104
    {
105
        $connectorClass = $this->driver[$this->config["driver"]]["connector"];
106
        $this->connector = new $connectorClass();
107
108
        $grammarClass = $this->driver[$this->config["driver"]]["grammar"];
109
        $this->grammar = new $grammarClass();
110
111
        $this->query = new Query();
112
    }
113
114
    /**
115
     * @return PDO
116
     */
117
    public function createConnection()
118
    {
119
        $this->pdo = $this->connector->connect($this->config);
120
        return $this->pdo;
121
    }
122
123
    /**
124
     * @param $query
125
     * @param null $params
126
     * @return $this
127
     */
128
    public function sql($query, $params = null)
129
    {
130
        $this->query = $this->query->sql($query, $params);
131
        return $this;
132
    }
133
134
    /**
135
     * @param $table
136
     * @return $this
137
     */
138
    public function table($table)
139
    {
140
        $this->query->setTable($table);
141
        return $this;
142
    }
143
144
    /**
145
     * @param null $columns
146
     * @return $this
147
     */
148
    public function select($columns = null)
149
    {
150
        $this->query->select($columns);
151
        return $this;
152
    }
153
154
    /**
155
     * @param array $columnsVal
156
     * @param bool $runExecute
157
     * @return $this | bool
158
     */
159
    public function insert(array $columnsVal, $runExecute = false)
160
    {
161
        $this->query->insert($columnsVal);
162
163
        if ($runExecute) {
164
            $status = $this->execute();
165
            $this->clear();
166
167
            return $status;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $status; (boolean) is incompatible with the return type documented by JayaCode\Framework\Core\Database\Database::insert of type JayaCode\Framework\Core\Database\Database.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
168
        }
169
170
        return $this;
171
    }
172
173
    /**
174
     * @param array $columnsVal
175
     * @param null $primaryKey
176
     * @return $this|bool
177
     */
178
    public function update(array $columnsVal, $primaryKey = null)
179
    {
180
        if ($primaryKey) {
181
            $keyVal = $columnsVal[$primaryKey];
182
            $columnsVal = arr_exclude($columnsVal, [$primaryKey]);
183
184
            $this->query->update($columnsVal)->where($primaryKey, $keyVal);
185
186
            $status = $this->execute();
187
            $this->clear();
188
189
            return $status;
190
        }
191
192
        $this->query->update($columnsVal);
193
194
        return $this;
195
    }
196
197
    /**
198
     * @param $query
199
     * @param string $type
200
     * @return Query
201
     */
202
    public function whereQ($query, $type = "AND")
203
    {
204
        $this->query->whereQ($query, $type);
205
        return $this;
206
    }
207
208
    /**
209
     * @param $column
210
     * @param $value
211
     * @param string $operator
212
     * @param string $type
213
     * @return $this
214
     */
215
    public function where($column, $value, $operator = "=", $type = "AND")
216
    {
217
        $this->query->where($column, $value, $operator, $type);
218
        return $this;
219
    }
220
221
    /**
222
     * @param $column
223
     * @param $value
224
     * @param string $operator
225
     * @return $this
226
     */
227
    public function andWhere($column, $value, $operator = "=")
228
    {
229
        $this->query->andWhere($column, $value, $operator);
230
        return $this;
231
    }
232
233
    /**
234
     * @param $column
235
     * @param $value
236
     * @param string $operator
237
     * @return $this
238
     */
239
    public function orWhere($column, $value, $operator = "=")
240
    {
241
        $this->query->orWhere($column, $value, $operator);
242
        return $this;
243
    }
244
245
    /**
246
     * @param $column
247
     * @param $value
248
     * @param string $type
249
     * @return $this
250
     */
251
    public function like($column, $value, $type = "AND")
252
    {
253
        $this->query->like($column, $value, $type);
254
        return $this;
255
    }
256
257
    /**
258
     * @param $column
259
     * @param $value
260
     * @return $this
261
     */
262
    public function andLike($column, $value)
263
    {
264
        $this->query->andLike($column, $value);
265
        return $this;
266
    }
267
268
    /**
269
     * @param $column
270
     * @param $value
271
     * @return $this
272
     */
273
    public function orLike($column, $value)
274
    {
275
        $this->query->orLike($column, $value);
276
        return $this;
277
    }
278
279
    /**
280
     * @param $column
281
     * @param $value
282
     * @param string $type
283
     * @return $this
284
     */
285
    public function between($column, $value, $type = "AND")
286
    {
287
        $this->query->between($column, $value, $type);
288
        return $this;
289
    }
290
291
    /**
292
     * @param $column
293
     * @param $value
294
     * @return $this
295
     */
296
    public function andBetween($column, $value)
297
    {
298
        $this->query->andBetween($column, $value);
299
        return $this;
300
    }
301
302
    /**
303
     * @param $column
304
     * @param $value
305
     * @return $this
306
     */
307
    public function orBetween($column, $value)
308
    {
309
        $this->query->orBetween($column, $value);
310
        return $this;
311
    }
312
313
    /**
314
     * @return bool
315
     */
316
    public function execute()
317
    {
318
        $qArr = $this->query->build($this->grammar);
319
320
        $this->statement = $this->pdo->prepare($qArr[0]);
321
322
        return $this->statement->execute($qArr[1]);
323
    }
324
325
    /**
326
     * @return array
327
     * @throws \Exception
328
     */
329
    public function all()
330
    {
331
        $this->executeIfNotAlreadyExecutedPreviously();
332
333
        if ($this->model) {
334
            $dataModel = array();
335
            while ($model = $this->get()) {
336
                $dataModel[] = $model;
337
            }
338
339
            $this->clear();
340
341
            return $dataModel;
342
        }
343
        return $this->statement->fetchAll();
344
    }
345
346
    /**
347
     * @return mixed
348
     */
349
    public function first()
350
    {
351
        // TODO: use limit after query builder limit finish
352
        $data = $this->get();
353
        $this->clear();
354
        return $data;
355
    }
356
357
    /**
358
     * @return mixed
359
     * @throws \Exception
360
     */
361
    protected function get()
362
    {
363
        $this->executeIfNotAlreadyExecutedPreviously();
364
365
        if ($this->model) {
366
            $data = $this->statement->fetch();
367
            return $data?new $this->model($data, false):$data;
368
        }
369
370
        return $this->statement->fetch();
371
    }
372
373
    /**
374
     * @throws \Exception
375
     */
376
    protected function executeIfNotAlreadyExecutedPreviously()
377
    {
378
        if (!$this->statement) {
379
            $this->execute();
380
        }
381
    }
382
383
    /**
384
     * Clear statement PDO and query builder
385
     */
386
    public function clear()
387
    {
388
        $this->statement = null;
389
        $this->clearUsingModel();
390
391
        $this->query->clear();
392
        $this->grammar->clear();
393
    }
394
395
    /**
396
     *
397
     */
398
    public function clearUsingModel()
399
    {
400
        $this->model = null;
401
    }
402
403
    /**
404
     * @return string
405
     */
406
    public function getModel()
407
    {
408
        return $this->model;
409
    }
410
411
    /**
412
     * @param string $model
413
     * @param null $table
414
     * @throws \Exception
415
     */
416
    public function setModel($model, $table = null)
417
    {
418
        if (!class_exists($model)) {
419
            throw new \Exception("class {$model} is not exist");
420
        }
421
422
        if ($table) {
423
            $this->table($table);
424
        }
425
        $this->model = $model;
426
    }
427
428
    /**
429
     * @return string
430
     */
431
    public function lastInsertId()
432
    {
433
        return $this->pdo->lastInsertId();
434
    }
435
}
436