Browse Source

Implement setter for param() that supports immutable objects.

Add `withParam()` that implements the immutable object pattern that PSR7
uses. This deprecates the setter mode of param() as the request becomes
start to implement more of the immutable patterns.
Mark Story 9 years ago
parent
commit
2150a249fb
2 changed files with 46 additions and 0 deletions
  1. 21 0
      src/Network/Request.php
  2. 25 0
      tests/TestCase/Network/RequestTest.php

+ 21 - 0
src/Network/Request.php

@@ -1218,6 +1218,9 @@ class Request implements ArrayAccess
     /**
      * Safely access the values in $this->params.
      *
+     * As of 3.4.0, the setter mode of this method is *deprecated*.
+     * Use `withParam` instead.
+     *
      * @param string $name The name of the parameter to get.
      * @return mixed|$this The value of the provided parameter. Will
      *   return false if the parameter doesn't exist or is falsey.
@@ -1396,6 +1399,24 @@ class Request implements ArrayAccess
     }
 
     /**
+     * Update the request with a new routing parameter
+     *
+     * Returns an updated request object. This method returns
+     * a *new* request object and does not mutate the request in-place.
+     *
+     * @param string $name The dot separated path to insert $value at.
+     * @param mixed $value The value to insert into the the request parameters.
+     * @return self
+     */
+    public function withParam($name, $value)
+    {
+        $copy = clone $this;
+        $copy->params = Hash::insert($copy->params, $name, $value);
+
+        return $copy;
+    }
+
+    /**
      * Array access read implementation
      *
      * @param string $name Name of the key being accessed.

+ 25 - 0
tests/TestCase/Network/RequestTest.php

@@ -2538,6 +2538,31 @@ XML;
     }
 
     /**
+     * Test updating params in a psr7 fashion.
+     *
+     * @return void
+     */
+    public function testWithParam()
+    {
+        $request = new Request([
+            'params' => ['controller' => 'Articles']
+        ]);
+        $result = $request->withParam('action', 'view');
+        $this->assertNotSame($result, $request, 'New instance should be made');
+        $this->assertFalse($request->param('action'), 'No side-effect on original');
+        $this->assertSame('view', $result->param('action'));
+
+        $result = $request->withParam('action', 'index')
+            ->withParam('plugin', 'DebugKit')
+            ->withParam('prefix', 'Admin');
+        $this->assertNotSame($result, $request, 'New instance should be made');
+        $this->assertFalse($request->param('action'), 'No side-effect on original');
+        $this->assertSame('index', $result->param('action'));
+        $this->assertSame('DebugKit', $result->param('plugin'));
+        $this->assertSame('Admin', $result->param('prefix'));
+    }
+
+    /**
      * Test updating POST data in a psr7 fashion.
      *
      * @return void