{
  "schema_version": 2,
  "id": "develop/clients/php/transpipe",
  "title": "Pipelines and transactions",
  "url": "https://redis.io/docs/latest/develop/clients/php/transpipe/",
  "summary": "Learn how to use Redis pipelines and transactions",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-09T09:49:12+01:00",
  "page_type": "content",
  "content_hash": "a285a7f817fc05453bdf366ffd2715191f216eb5d352ca43e8c1aeb1742fe58b",
  "sections": [
    {
      "id": "execute-a-pipeline",
      "title": "Execute a pipeline",
      "role": "content",
      "text": "To execute commands in a pipeline, create a pipeline object with\n[`pipeline()`](https://github.com/predis/predis) and then add commands to it\nusing methods that resemble the standard command methods (for example,\n`set()` and `get()`). The commands are buffered in the pipeline and only\nexecute when you call the `execute()` method on the pipeline object. This\nmethod returns an array containing the results from all the commands in order.\n\nThe command methods for a pipeline always return the original pipeline object,\nso you can chain several commands together. You can also pass a callback to\n`pipeline()` and let Predis execute the batch automatically when the callback\nreturns, as the example below shows:\n\nFoundational: Use pipelines to batch multiple commands together and reduce network round trips\n\n**Difficulty:** Beginner\n\n**Available in:** PHP\n\n##### PHP\n\n[code example]"
    },
    {
      "id": "execute-a-transaction",
      "title": "Execute a transaction",
      "role": "content",
      "text": "A transaction works in a similar way to a pipeline, but all the queued commands\nexecute atomically. With Predis, you can create a transaction by calling\n`transaction()` and adding commands in a callback. Predis wraps those commands\nwith `MULTI` and `EXEC` automatically:\n\nBasic transaction: Execute commands atomically using transaction() to group related writes\n\n**Difficulty:** Beginner\n\n**Available in:** PHP\n\n##### PHP\n\n[code example]"
    },
    {
      "id": "watch-keys-for-changes",
      "title": "Watch keys for changes",
      "role": "content",
      "text": "Redis supports *optimistic locking* to avoid inconsistent updates to keys that\nseveral clients may modify at the same time. The basic idea is to watch for\nchanges to any keys that you use in a transaction while you are preparing the\nupdate. If the watched keys do change, you must restart the update using the\nlatest value from Redis. See\n[Transactions](https://redis.io/docs/latest/develop/using-commands/transactions)\nfor more information about optimistic locking.\n\nThe example below reads a string that represents a `PATH` variable for a\ncommand shell, appends a new command path, and then writes it back inside a\ntransaction. The `cas` option enables check-and-set behavior, `watch` tells\nPredis which key to monitor for changes, and `retry` lets Predis retry the\ntransaction automatically if another client changes the watched key before\n`EXEC` runs:\n\nOptimistic locking: Use WATCH with a CAS transaction to retry updates when another client modifies the key\n\n**Difficulty:** Intermediate\n\n**Available in:** PHP\n\n##### PHP\n\n[code example]"
    }
  ],
  "examples": [
    {
      "id": "execute-a-pipeline-ex0",
      "language": "php",
      "code": "$pipe = $r->pipeline();\n$pipe->set('seat:0', '#0')\n    ->set('seat:1', '#1')\n    ->set('seat:2', '#2')\n    ->set('seat:3', '#3')\n    ->set('seat:4', '#4');\n$pipe->execute();\n\n$pipe = $r->pipeline();\n$pipe->get('seat:0')\n    ->get('seat:1')\n    ->get('seat:2')\n    ->get('seat:3')\n    ->get('seat:4');\n$seats = $pipe->execute();\n\necho implode(', ', $seats), PHP_EOL;\n// >>> #0, #1, #2, #3, #4\n\n$responses = $r->pipeline(function ($pipe) {\n    $pipe->set('seat:5', '#5');\n    $pipe->set('seat:6', '#6');\n    $pipe->set('seat:7', '#7');\n    $pipe->get('seat:5');\n    $pipe->get('seat:6');\n    $pipe->get('seat:7');\n});\n\necho implode(', ', array_slice($responses, 3)), PHP_EOL;\n// >>> #5, #6, #7",
      "section_id": "execute-a-pipeline"
    },
    {
      "id": "execute-a-transaction-ex0",
      "language": "php",
      "code": "$r->transaction(function (MultiExec $tx) {\n    $tx->incr('counter:1');\n    $tx->incrby('counter:2', 2);\n    $tx->incrby('counter:3', 3);\n});\n\necho implode(', ', $r->mget('counter:1', 'counter:2', 'counter:3')), PHP_EOL;\n// >>> 1, 2, 3",
      "section_id": "execute-a-transaction"
    },
    {
      "id": "watch-keys-for-changes-ex0",
      "language": "php",
      "code": "$r->set('shellpath', '/usr/syscmds/');\n\n$r->transaction(\n    ['cas' => true, 'watch' => 'shellpath', 'retry' => 3],\n    function (MultiExec $tx) {\n        $path = $tx->get('shellpath');\n        $tx->multi();\n        $tx->set('shellpath', $path . ':/usr/mycmds/');\n    }\n);\n\necho $r->get('shellpath'), PHP_EOL;\n// >>> /usr/syscmds/:/usr/mycmds/",
      "section_id": "watch-keys-for-changes"
    }
  ]
}
