Skip to content

Commit

Permalink
Merge pull request #8 from InitPHP/main-dev
Browse files Browse the repository at this point in the history
Main dev
  • Loading branch information
muhammetsafak authored Nov 12, 2022
2 parents 69f661e + 3858725 commit ac90b0b
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,44 @@ if ($isUpdate) {
}
```

##### Update Batch

```php
use \InitPHP\Database\Facade\DB;
$data = [
[
'id' => 5,
'title' => 'New Title #5',
'content' => 'New Content #5',
],
[
'id' => 10,
'title' => 'New Title #10',
]
];

$isUpdate = DB::from('post')
->where('status', 1)
->updateBatch($data, 'id');

/**
* This executes the following query.
*
* UPDATE post SET
* title = CASE
* WHEN id = 5 THEN 'New Title #5'
* WHEN id = 10 THEN 'New Title #10'
* ELSE title END,
* content = CASE
* WHEN id = 5 THEN 'New Content #5'
* ELSE content END
* WHERE status = 1 AND id IN (5, 10)
*/
if ($isUpdate) {
// Success
}
```

#### Delete

```php
Expand Down
97 changes: 97 additions & 0 deletions src/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,49 @@ public function update(array $set)
return $res->numRows() > 0;
}

/**
* @param array $set
* @param string $referenceColumn
* @return bool
*/
public function updateBatch(array $set, string $referenceColumn)
{
if($this->_credentials['updatable'] === FALSE){
throw new UpdatableException('');
}
$schemaID = $this->getSchemaID();

$results = [];
$setUpdate = [];

foreach ($set as $data) {
if(!\is_array($data) || \array_key_exists($referenceColumn, $data)){
continue;
}

$setUpdate[] = $data;
$this->_validation->setData($data);
foreach ($data as $column => $value) {
if($column == $referenceColumn){
continue;
}
if($this->_validation->validation($column, $schemaID) === FALSE){
$this->_errors[] = $this->_validation->getError();
return false;
}
}

if(!empty($this->_credentials['updatedField'])){
$setUpdate[$this->_credentials['updatedField']] = \date($this->_credentials['timestampFormat']);
}
}

$res = $this->query($this->_updateBatchQuery($setUpdate, $referenceColumn));
$this->reset();

return $res->numRows() > 0;
}

/**
* @param array $conditions
* @return bool
Expand Down Expand Up @@ -666,6 +709,60 @@ public function _updateQuery(array $data): string
. $this->_limitQuery();
}

public function _updateBatchQuery(array $data, $referenceColumn): string
{
$updateData = []; $columns = []; $where = [];
$schemaID = $this->getSchemaID();
foreach ($data as $set) {
if(!\is_array($set) || !isset($set[$referenceColumn])){
continue;
}
$setData = [];
foreach ($set as $key => $value) {
if($key === $schemaID){
continue;
}
if($this->_credentials['allowedFields'] !== null && $key != $referenceColumn && !\in_array($key, $this->_credentials['allowedFields'])){
continue;
}
if($key == $referenceColumn){
$where[] = $value;
continue;
}
$setData[$key] = Helper::isSQLParameterOrFunction($value) ? $value : Parameters::add($key, $value);
if(!\in_array($key, $columns)){
$columns[] = $key;
}
}
$updateData[] = $setData;
}

$update = [];
foreach ($columns as $column) {
$syntax = $column . ' = CASE';
foreach ($updateData as $key => $values) {
if(!\array_key_exists($column, $values)){
continue;
}
$syntax .= ' WHEN ' . $referenceColumn . ' = '
. (Helper::isSQLParameterOrFunction($where[$key]) ? $where[$key] : Parameters::add($referenceColumn, $where[$key]))
. ' THEN '
. $values[$column];
}
$syntax .= ' ELSE ' . $column . ' END';
$update[] = $syntax;
}
$this->in($referenceColumn, $where);

return 'UPDATE '
. (empty($this->_STRUCTURE['table']) ? $this->getSchema() : end($this->_STRUCTURE['table']))
. ' SET '
. \implode(', ', $update)
. $this->_whereQuery()
. $this->_havingQuery()
. $this->_limitQuery();
}

public function _deleteQuery(): string
{
return 'DELETE FROM'
Expand Down
32 changes: 32 additions & 0 deletions src/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,38 @@ final public function update(array $set)
return $data = $this->callbacksFunctionHandler($data, 'afterUpdate');
}

/**
* @param array $set
* @param string $referenceColumn
* @return array|false
*/
final public function updateBatch(array $set, string $referenceColumn)
{
if($this->isUpdatable() === FALSE){
throw new UpdatableException('"' . \get_called_class() . '" is not a updatable model.');
}

foreach ($set as &$data) {
$data = $this->callbacksFunctionHandler($data, 'beforeUpdate');
if($data === FALSE){
return false;
}
}

if(parent::updateBatch($set, $referenceColumn) === FALSE){
return false;
}

foreach ($set as &$row) {
$row = $this->callbacksFunctionHandler($row, 'afterUpdate');
if($row === FALSE){
return false;
}
}

return $set;
}

/**
* @param int|string|null $id
* @return array|bool
Expand Down
24 changes: 24 additions & 0 deletions tests/QueryBuilderUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,30 @@ public function testUpdateStatementBuild()
$this->db->reset();
}

public function testUpdateBatchStatementBuild()
{
Parameters::reset();
$this->db->from('post')
->where('status', true);

$data = [
[
'id' => 5,
'title' => 'New Title #5',
'content' => 'New Content #5',
],
[
'id' => 10,
'title' => 'New Title #10',
]
];

$expected = 'UPDATE post SET title = CASE WHEN id = :id THEN :title WHEN id = :id_1 THEN :title_1 ELSE title END, content = CASE WHEN id = :id_2 THEN :content ELSE content END WHERE status = :status AND id IN (5, 10)';

$this->assertEquals($expected, $this->db->_updateBatchQuery($data, 'id'));
$this->db->reset();
}

public function testDeleteStatementBuild()
{
Parameters::reset();
Expand Down

0 comments on commit ac90b0b

Please sign in to comment.