Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a basic upsert method #16

Merged
merged 12 commits into from
Nov 14, 2023
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
22 changes: 22 additions & 0 deletions src/DB/QueryBuilder/Concerns/CRUD.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,28 @@ public function update( $data, $format = null ) {
);
}

/**
borkweb marked this conversation as resolved.
Show resolved Hide resolved
* @param $data
* @param $match
* @param $format
*
* @return false|int
borkweb marked this conversation as resolved.
Show resolved Hide resolved
borkweb marked this conversation as resolved.
Show resolved Hide resolved
*/
public function upsert( $data, $match = [], $format = null ) {
// Build the where clause(s).
foreach( $match as $column ) {
borkweb marked this conversation as resolved.
Show resolved Hide resolved
$this->where( $column, $data[$column] );
borkweb marked this conversation as resolved.
Show resolved Hide resolved
}

// 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);
}

}