Skip to content

Commit

Permalink
Merge pull request #16 from binarygary/feature/upsert
Browse files Browse the repository at this point in the history
Add a basic upsert method
  • Loading branch information
borkweb authored Nov 14, 2023
2 parents e299e35 + 6b2daf4 commit 9c76724
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ composer require stellarwp/db
- [CRUD](#crud)
- [Insert](#insert)
- [Update](#update)
- [Upsert](#upsert)
- [Delete](#delete)
- [Get](#get)

Expand Down Expand Up @@ -847,6 +848,28 @@ DB::table('posts')
]);
```

### Upsert

The `QueryBuilder::upsert` method may be used to update an existing record or create a new record if it doesn't exist.

```php
// Would result in a new row - Oakland to San Diego for 100.
DB::table('table_name')
->upsert(
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => '100'] ,
['departure','destination']
);


// Would update the row that was just inserted - Oakland to San Diego for 99.
DB::table('table_name')
->upsert(
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => '99'] ,
['departure','destination']
);

```

### Delete

The `QueryBuilder::delete` method may be used to delete records from the table.
Expand Down
26 changes: 26 additions & 0 deletions src/DB/QueryBuilder/Concerns/CRUD.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,32 @@ public function update( $data, $format = null ) {
);
}

/**
* Upsert allows for inserting or updating a row depending on whether it already exists.
*
* @since 1.0.8
*
* @param array<string, string|int|float|bool|null> $data The data to insert or update.
* @param array $match The columns to match on.
* @param string|array|null $format Array of formats to be mapped to each value in $data. If string, the format will be used for all values in $data.
*
* @return false|int Number of rows updated/inserted, false on error.
*/
public function upsert( $data, $match = [], $format = null ) {
// Build the where clause(s).
foreach ( $match as $column ) {
$this->where( $column, $data[ $column ] );
}

// If the row exists, update it.
if ( $this->get() ) {
return $this->update( $data, $format );
}

// Otherwise, insert it.
return $this->insert( $data, $format );
}

/**
* @since 1.0.0
*
Expand Down
85 changes: 85 additions & 0 deletions tests/wpunit/QueryBuilder/CRUDTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,89 @@ public function testDeleteShouldDeleteRowInDatabase()
$this->assertNull($post);
}

/**
* Tests if upsert() adds a row to the database.
*
* @return void
*/
public function testUpsertShouldAddRowToDatabase()
{
$data = [
'post_title' => 'Query Builder CRUD test',
'post_type' => 'crud_test',
'post_content' => 'Hello World!',
];

DB::table('posts')->upsert($data);

$id = DB::last_insert_id();

$post = DB::table('posts')
->select('post_title', 'post_type', 'post_content')
->where('ID', $id)
->get();

$this->assertEquals($data['post_title'], $post->post_title);
$this->assertEquals($data['post_type'], $post->post_type);
$this->assertEquals($data['post_content'], $post->post_content);
}

/**
* Tests if upsert() updates a row in the database.
*
* @return void
*/
public function testUpsertShouldUpdateRowInDatabase()
{
$data = [
'post_title' => 'Query Builder CRUD test - upsert update',
'post_type' => 'crud_test',
'post_content' => 'Hello World from upsert!',
];

DB::table('posts')->insert($data);

$original_id = DB::last_insert_id();

$updated_data = [
'post_title' => 'Query Builder CRUD test - upsert update',
'post_type' => 'crud_test',
'post_content' => 'Hello World from upsert! - updated',
];

$match = [
'post_title',
];

DB::table('posts')->upsert( $updated_data, $match );

$post = DB::table('posts')
->select('post_title', 'post_type', 'post_content')
->where('ID', $original_id)
->get();

$this->assertEquals($updated_data['post_content'], $post->post_content);

// Test multiple match columns
$further_updated_data = [
'post_title' => 'Query Builder CRUD test - upsert update',
'post_type' => 'crud_test',
'post_content' => 'Hello World from upsert! - updated even more!',
];

$match = [
'post_title',
'post_type',
];

DB::table('posts')->upsert( $further_updated_data, $match );

$post = DB::table('posts')
->select('post_title', 'post_type', 'post_content')
->where('ID', $original_id)
->get();

$this->assertEquals($further_updated_data['post_content'], $post->post_content);
}

}

0 comments on commit 9c76724

Please sign in to comment.