4

I am using CakePHP 3 and MySQL.

I would like to implement a INSERT on DUPLICATE KEY UPDATE aka upsert query via CakePHP 3 model.

Given the following table:

+----+----------+-----+
| id | username | age |
+----+----------+-----+
|  1 | admin    |  33 |
|  2 | Timmy    |  17 |
|  3 | Sally    |  23 |
+----+----------+-----+

where id is Primary Key and username is unique index

When I have the following values awaiting to be upserted:

Felicia, 27
Timmy, 71

I expect the following result after the upsert:

+----+----------+-----+
| id | username | age |
+----+----------+-----+
|  1 | admin    |  33 |
|  2 | Timmy    |  71 |
|  3 | Sally    |  23 |
|  4 | Felicia  |  27 |
+----+----------+-----+

I know how to do upsert in MySQL query:

INSERT INTO `users` (`username`, `age`) 
VALUES ('Felicia', 27), ('Timmy', 71) 
ON DUPLICATE KEY UPDATE 
`username`=VALUES(`username`),`age`=VALUES(`age`);

I know how to do this in more than a single query in CakePHP3.

   $newUsers = [
        [
            'username' => 'Felicia',
            'age' => 27,
        ],
        [
            'username' => 'Timmy',
            'age' => 71,
        ],
    ];

    foreach ($newUsers as $newUser) {
        $existingRecord = $this->Users->find()
            ->select(['id'])
            ->where(['username' => $newUser['username']])
            ->first();

        if (empty($existingRecord)) {
            $insertQuery = $this->Users->query();
            $insertQuery->insert(array_keys($newUser))
                ->values($newUser)
                ->execute();
        } else {
            $updateQuery = $this->Users->query();
            $updateQuery->update()
                ->set($newUser)
                ->where(['id' => $existingRecord->id])
                ->execute();
        }
    }

What I want to know is :

is there a way to do upsert using CakePHP 3 in a single line even if I use chaining?

Please advise how do I implement that.

9
  • StackOverflow is not a code writing service. Please post what have you tried to date and what problem do you have. Commented Oct 26, 2014 at 12:03
  • 2
    possible duplicate of CakePHP 3.0: How to do an insert on duplicate key update? Commented Oct 26, 2014 at 12:04
  • just to clear: it´s no duplicate of [CakePHP 3.0: How to do an insert on duplicate key update?][1] [1]: stackoverflow.com/questions/24852904/… Commented Oct 27, 2014 at 10:24
  • @Dirk You aren't clarifying anything, you're just making a statement. Care to explain why you think it's not a duplicate? Commented Oct 27, 2014 at 11:04
  • @TomaszKowalczyk is that better now? Commented Oct 27, 2014 at 14:52

1 Answer 1

6

Using the answer provided at https://stackoverflow.com/a/24990944/80353, I want to rephrase this using the code sample given in the question.

To run upsert on the following records

Felicia, 27
Timmy, 71

into this table

+----+----------+-----+
| id | username | age |
+----+----------+-----+
|  1 | admin    |  33 |
|  2 | Timmy    |  17 |
|  3 | Sally    |  23 |
+----+----------+-----+

the best way is to write it as

$newUsers = [
    [
        'username' => 'Felicia',
        'age' => 27,
    ],
    [
        'username' => 'Timmy',
        'age' => 71,
    ],
];

$columns = array_keys($newUsers[0]);

$upsertQuery = $this->Users->query();

$upsertQuery->insert($columns);

// need to run clause('values') AFTER insert()
$upsertQuery->clause('values')->values($newUsers);

$upsertQuery->epilog('ON DUPLICATE KEY UPDATE `username`=VALUES(`username`), `age`=VALUES(`age`)')
                ->execute();

Check this out for details about epilog

Check this out for details on how to write insert multiple records in single query

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.