3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
12 namespace Civi\Api4\Generic
;
15 * Container for api results.
17 * The Result object has three functions:
19 * 1. Store the results of the API call (accessible via ArrayAccess).
20 * 2. Store metadata like the Entity & Action names.
21 * - Note: some actions extend the Result object to store extra metadata.
22 * For example, BasicReplaceAction returns ReplaceResult which includes the additional $deleted property to list any items deleted by the operation.
23 * 3. Provide convenience methods like `$result->first()` and `$result->indexBy($field)`.
25 class Result
extends \ArrayObject
implements \JsonSerializable
{
44 * Not for public use. Instead, please use countFetched(), countMatched() and count().
51 * How many entities matched the query, regardless of LIMIT clauses.
53 * This requires that row_count is included in the SELECT.
57 protected $matchedCount;
62 * Return first result.
65 public function first() {
66 foreach ($this as $values) {
76 public function last() {
77 $items = $this->getArrayCopy();
78 return array_pop($items);
82 * Return the one-and-only result record.
84 * If there are too many or too few results, then throw an exception.
87 * @throws \API_Exception
89 public function single() {
91 foreach ($this as $values) {
92 if ($result === NULL) {
96 throw new \
API_Exception("Expected to find one {$this->entity} record, but there were multiple.");
100 if ($result === NULL) {
101 throw new \
API_Exception("Expected to find one {$this->entity} record, but there were zero.");
111 public function itemAt($index) {
112 $length = $index < 0 ?
0 - $index : $index +
1;
113 if ($length > count($this)) {
116 return array_slice(array_values($this->getArrayCopy()), $index, 1)[0];
120 * Re-index the results array (which by default is non-associative)
122 * Drops any item from the results that does not contain the specified key
126 * @throws \API_Exception
128 public function indexBy($key) {
129 $this->indexedBy
= $key;
132 foreach ($this as $values) {
133 if (isset($values[$key])) {
134 $newResults[$values[$key]] = $values;
138 throw new \
API_Exception("Key $key not found in api results");
140 $this->exchangeArray($newResults);
146 * Returns the number of results.
148 * If row_count was included in the select fields, then this will be the
149 * number of matched entities, even if this differs from the number of
152 * If row_count was not included, then this returns the number of entities
153 * fetched, which may or may not be the number of matches.
155 * Your code might be easier to reason about if you use countFetched() or
156 * countMatched() instead.
160 public function count() {
161 return $this->rowCount ?? parent
::count();
165 * Returns the number of results fetched.
167 * If a limit was used, this will be a number up to that limit.
169 * In the case that *only* the row_count was fetched, this will be zero, since no *entities* were fetched.
173 public function countFetched() :int {
174 return parent
::count();
178 * Returns the number of results
182 public function countMatched() :int {
183 if (!isset($this->matchedCount
)) {
184 throw new \
API_Exception("countMatched can only be used if there was no limit set or if row_count was included in the select fields.");
186 return $this->matchedCount
;
190 * Provides a way for API implementations to set the *matched* count.
192 * The matched count is the number of matching entities, regardless of any imposed limit clause.
194 public function setCountMatched(int $c) {
195 $this->matchedCount
= $c;
197 // Set rowCount for backward compatibility.
198 $this->rowCount
= $c;
202 * Reduce each result to one field
207 public function column($name) {
208 return array_column($this->getArrayCopy(), $name, $this->indexedBy
);
214 public function jsonSerialize() {
215 return $this->getArrayCopy();