### Model.beforeFind event
Each find() will trigger a Model.beforeFind event for all attached
listeners. Any listener can set a valid result set using $query
By default, $options will recognize the following keys:
- fields
- conditions
- order
- limit
- offset
- page
- group
- having
- contain
- join
### Usage
Using the options array:
$query = $articles->find('all', [
'conditions' => ['published' => 1],
'limit' => 10,
'contain' => ['Users', 'Comments']
]);
Using the builder interface:
$query = $articles->find()
->where(['published' => 1])
->limit(10)
->contain(['Users', 'Comments']);
### Calling finders
The find() method is the entry point for custom finder methods.
You can invoke a finder by specifying the type:
$query = $articles->find('published');
Would invoke the findPublished method.
public find ( $type = 'all', $options = [] ) : |
||
return | The query builder |
/** * Helper generator for use with importTable(). * * Yields a single new Entity instance approciate for $Table for each * of $records where the values are merged with $defaults. * * Will skip any records that fail to validate, dumping validation * errors to the console in the process. * * Used by imporTables(). * * @param Cake\ORM\Table $Table A Table instance to save records into. * @param array $records An array of Entity records to save into the Table. * @param array $defaults Optional array of default field values to merge into each record. * @param array $options Optional array of newEntity() options to use. * @return void */ public function entityGenerator(Table $Table, array $records, array $defaults = [], array $options = []) { $defaultOptions = ['validate' => true, 'accessibleFields' => ['*' => true]]; $options = $options + $defaultOptions; $keyField = $Table->primaryKey(); foreach ($records as $r) { $r = Hash::merge($defaults, $r); $id = !empty($r[$keyField]) ? $r[$keyField] : false; if ($id) { $entity = $Table->find()->where([$keyField => $id])->first(); if ($entity) { $entity = $Table->patchEntity($entity, $r, $options); if (!$entity->dirty()) { $this->verbose("<success>{$Table->alias()} ({$id}): No changes.</success>"); continue; } } else { $entity = $Table->newEntity($r, $options); $entity->isNew(true); } } else { $entity = $Table->newEntity($r, $options); } $errors = $entity->errors(); if ($errors) { $this->printValidationErrors($Table->alias(), $id, $errors); continue; } (yield $entity); } }
/** * test WHERE conditions against unary expression. * * @return void */ public function testUnaryExpression() { $this->table->addColumn('user-birth-date', ['type' => 'date'], false); $first = $this->table->get(1); $first->set('user-birth-date', time()); $this->table->save($first); $second = $this->table->find('all', ['eav' => true])->where(['user-birth-date IS' => null])->order(['id' => 'ASC'])->first(); $this->assertTrue(!empty($second) && $second->get('id') == 2); }
/** * Method used to read from a database session. * * @param int|string $id The key of the value to read * @return mixed The value of the key or false if it does not exist */ public function read($id) { $result = $this->_table->find('all')->select(['data'])->where([$this->_table->primaryKey() => $id])->hydrate(false)->first(); if (empty($result)) { return false; } return $result['data']; }
public function listCronsAction() { $cronSettings = $this->cronSettings->find()->hydrate(false)->toArray(); if (empty($cronSettings)) { $cronSettings = ['output' => 'cron-all.log', 'recipients' => $this->site['sender']]; $this->cronSettings->save($this->cronSettings->newEntity()->set($cronSettings)); } echo $this->twig->render('cron/list.twig', ['crons' => $this->cronsTable->find()->hydrate(false)->toArray(), 'cronSettings' => $this->cronSettings->find()->hydrate(false)->toArray()[0]]); }
/** * Tests find('list') with hydrated records * * @return void */ public function testFindListHydrated() { $table = new Table(['table' => 'users', 'connection' => $this->connection]); $table->displayField('username'); $query = $table->find('list', ['fields' => ['id', 'username']])->order('id'); $expected = [1 => 'mariano', 2 => 'nate', 3 => 'larry', 4 => 'garrett']; $this->assertSame($expected, $query->toArray()); $query = $table->find('list', ['groupField' => 'odd'])->select(['id', 'username', 'odd' => new FunctionExpression('MOD', [new IdentifierExpression('id'), 2])])->hydrate(true)->order('id'); $expected = [1 => [1 => 'mariano', 3 => 'larry'], 0 => [2 => 'nate', 4 => 'garrett']]; $this->assertSame($expected, $query->toArray()); }
/** * Setup modules for layout. * * @return void */ private function __setForLayout() { $positions = $this->Theme->getThemePositions(); $theme = Inflector::underscore(Configure::read('Theme.' . Theme::CLIENT_FRONT_END)); foreach ($positions as $position) { $cacheKey = $theme . '_' . $position; $modules = $this->_table->find()->where(['position' => $position])->order(['ordering' => 'ASC'])->cache($cacheKey, 'positions')->toArray(); if (!empty($modules)) { $this->_modulesForLayout[$position] = $modules; } } $this->_controller->set('module_for_layout', $this->_modulesForLayout); }
/** * Method used to read from a database session. * * @param int|string $id The key of the value to read * @return string The value of the key or empty if it does not exist */ public function read($id) { $result = $this->_table->find('all')->select(['data'])->where([$this->_table->primaryKey() => $id])->hydrate(false)->first(); if (empty($result)) { return ''; } if (is_string($result['data'])) { return $result['data']; } $session = stream_get_contents($result['data']); if ($session === false) { return ''; } return $session; }
protected function getFilteredPostsIds(array $identifiers, $mask, array $orX = []) { $orX = array_map(function ($value) { return str_replace('p.', 'Posts.', $value); }, $orX); $query = $this->Posts->find(); $aclFilter = new CakephpOrmAclFilter($query); $aclFilter->setAclSchema($this->aclSchema); $aclFilter->apply('Posts', 'id', 'post-', $identifiers, $mask, $orX); $postsIds = []; foreach ($query->all() as $post) { $postsIds[] = $post->id; } return $postsIds; }
public function testFind() { $entities = []; foreach ($this->entityMap as $discriminator => $class) { $data = ['discriminator' => $discriminator]; $entities[] = $this->table->newEntity($data); } $this->table->saveMany($entities); $found = $this->table->find()->toArray(); $this->assertCount(6, $found); foreach ($found as $entity) { $class = $this->entityMap[$entity->discriminator]; $this->assertInstanceOf($class, $entity); } }
/** * Builds a query for loading the passed list of entity objects along with the * associations specified in $contain. * * @param Cake\Collection\CollectionInterface $objects The original entitites * @param array $contain The associations to be loaded * @param Cake\ORM\Table $source The table to use for fetching the top level entities * @return Cake\ORM\Query */ protected function _getQuery($objects, $contain, $source) { $primaryKey = $source->primaryKey(); $method = is_string($primaryKey) ? 'get' : 'extract'; $keys = $objects->map(function ($entity) use($primaryKey, $method) { return $entity->{$method}($primaryKey); }); $query = $source->find()->select((array) $primaryKey)->where(function ($exp, $q) use($primaryKey, $keys, $source) { if (is_array($primaryKey) && count($primaryKey) === 1) { $primaryKey = current($primaryKey); } if (is_string($primaryKey)) { return $exp->in($source->aliasField($primaryKey), $keys->toList()); } $types = array_intersect_key($q->defaultTypes(), array_flip($primaryKey)); $primaryKey = array_map([$source, 'aliasField'], $primaryKey); return new TupleComparison($primaryKey, $keys->toList(), $types, 'IN'); })->contain($contain); foreach ($query->eagerLoader()->attachableAssociations($source) as $loadable) { $config = $loadable->config(); $config['includeFields'] = true; $loadable->config($config); } return $query; }
/** * Modifies the entity before it is saved so that translated fields are persisted * in the database too. * * @param \Cake\Event\Event $event The beforeSave event that was fired * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved * @param \ArrayObject $options the options passed to the save method * @return void */ public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options) { $locale = $entity->get('_locale') ?: $this->locale(); $newOptions = [$this->_translationTable->alias() => ['validate' => false]]; $options['associated'] = $newOptions + $options['associated']; $this->_bundleTranslatedFields($entity); $bundled = $entity->get('_i18n') ?: []; if ($locale === $this->config('defaultLocale')) { return; } $values = $entity->extract($this->_config['fields'], true); $fields = array_keys($values); $primaryKey = (array) $this->_table->primaryKey(); $key = $entity->get(current($primaryKey)); $model = $this->_config['referenceName']; $preexistent = $this->_translationTable->find()->select(['id', 'field'])->where(['field IN' => $fields, 'locale' => $locale, 'foreign_key' => $key, 'model' => $model])->bufferResults(false)->indexBy('field'); $modified = []; foreach ($preexistent as $field => $translation) { $translation->set('content', $values[$field]); $modified[$field] = $translation; } $new = array_diff_key($values, $modified); foreach ($new as $field => $content) { $new[$field] = new Entity(compact('locale', 'field', 'content', 'model'), ['useSetters' => false, 'markNew' => true]); } $entity->set('_i18n', array_merge($bundled, array_values($modified + $new))); $entity->set('_locale', $locale, ['setter' => false]); $entity->dirty('_locale', false); foreach ($fields as $field) { $entity->dirty($field, false); } }
/** * ResetSlugs method. * * Regenerate all slugs. On large dbs this can take more than 30 seconds - a time * limit is set to allow a minimum 100 updates per second as a preventative measure. * * Note that you should use the Reset behavior if you need additional functionality such * as callbacks or timeouts. * * @param array $params * @return bool Success */ public function resetSlugs($params = []) { if (!$this->_table->hasField($this->_config['field'])) { throw new Exception('Table does not have field ' . $this->_config['field']); } $defaults = ['page' => 1, 'limit' => 100, 'fields' => array_merge([$this->_table->primaryKey()], $this->_config['label']), 'order' => $this->_table->displayField() . ' ASC', 'conditions' => $this->_config['scope'], 'overwrite' => true]; $params = array_merge($defaults, $params); $count = $this->_table->find('all', compact('conditions'))->count(); $max = ini_get('max_execution_time'); if ($max) { set_time_limit(max($max, $count / 100)); } $this->_table->behaviors()->Slugged->config($params, null, false); while ($records = $this->_table->find('all', $params)->toArray()) { foreach ($records as $record) { $record->isNew(true); $options = ['validate' => true, 'fieldList' => array_merge([$this->_table->primaryKey(), $this->_config['field']], $this->_config['label'])]; if (!$this->_table->save($record, $options)) { throw new Exception(print_r($this->_table->errors(), true)); } } $params['page']++; } return true; }
/** * TreeHelperTest::testGenerateProductive() * * @return void */ public function testGenerateProductive() { $tree = $this->Table->find('threaded')->toArray(); $output = $this->Tree->generate($tree, ['indent' => false]); $expected = '<ul><li>One<ul><li>One-SubA</li></ul></li><li>Two<ul><li>Two-SubA<ul><li>Two-SubA-1<ul><li>Two-SubA-1-1</li></ul></li></ul></li></ul></li><li>Three</li><li>Four<ul><li>Four-SubA</li></ul></li></ul>'; $this->assertTextEquals($expected, $output); }
public function testGET_index() { // 1. Submit submit request, examine response, observe no redirect, and parse the response. $book_id = FixtureConstants::bookTypical; $book = $this->Books->get($book_id); $this->get('/books/' . $book_id . '/transactions'); $this->assertResponseCode(200); $this->assertNoRedirect(); $dom = new \DomDocument(); $dom->loadHTML($this->_response->body()); $xpath = new \DomXPath($dom); // 2. Isolate the content produced by this controller method (excluding the layout.) $content_node = $this->getTheOnlyOne($xpath, "//div[@id='TransactionsIndex']"); // 3. Count the A tags. $unknownATagCnt = $xpath->query(".//a", $content_node)->length; // 4. Look for the create new transaction link $this->getTheOnlyOne($xpath, "//a[@id='TransactionNewform']", $content_node); $unknownATagCnt--; // 5. Ensure that there is a suitably named table to display the results. $table_node = $this->getTheOnlyOne($xpath, "//table[@id='TransactionsTable']", $content_node); // 6. Now inspect the caption of the table. $this->assertContains($book['title'], $this->getTheOnlyOne($xpath, "caption", $table_node)->textContent); // 7. Ensure that said table's thead element contains the correct // headings, in the correct order, and nothing else. $column_header_nodes = $xpath->query("thead/tr/th", $table_node); $this->assertEquals($column_header_nodes->length, 3); // no other columns $this->getTheOnlyOne($xpath, "thead/tr/th[1][@id='note']", $table_node); $this->getTheOnlyOne($xpath, "thead/tr/th[2][@id='tran_datetime']", $table_node); $this->getTheOnlyOne($xpath, "thead/tr/th[3][@id='actions']", $table_node); // 8. Ensure that the tbody section has the correct quantity of rows. $dbRecords = $this->Transactions->find()->where(['book_id' => $book_id])->order(['tran_datetime' => 'desc']); $tbody_nodes = $xpath->query("tbody/tr", $table_node); $this->assertTrue($tbody_nodes->length == $dbRecords->count()); // 9. Ensure that the values displayed in each row, match the values from // the fixture. The values should be presented in a particular order // with nothing else thereafter. $iterator = new \MultipleIterator(); $iterator->attachIterator(new \ArrayIterator($dbRecords->execute()->fetchAll('assoc'))); $iterator->attachIterator(new \ArrayIterator(iterator_to_array($tbody_nodes))); foreach ($iterator as $values) { $fixtureRecord = $values[0]; $row_node = $values[1]; $column_nodes = $xpath->query("td", $row_node); $this->assertEquals($fixtureRecord['Transactions__note'], $column_nodes->item(0)->textContent); //$this->assertEquals($fixtureRecord['Transactions__datetime'], $column_nodes->item(1)->textContent); // 9.1 Now examine the action links $action_nodes = $xpath->query("a", $column_nodes->item(2)); $this->assertTrue($action_nodes->length == 2); $this->getTheOnlyOne($xpath, "a[@name='TransactionView']", $column_nodes->item(2)); $unknownATagCnt--; $this->getTheOnlyOne($xpath, "a[@name='TransactionEditform']", $column_nodes->item(2)); $unknownATagCnt--; // 9.9 No other columns $this->assertEquals($column_nodes->length, $column_header_nodes->length); } // 10. Ensure that all the <A> tags have been accounted for $this->assertEquals(0, $unknownATagCnt); }
/** * Overload find to cause issues. * * @param string $type Find type * @param array $options find options * @return object */ public function find($type = 'all', $options = []) { if (empty($options['conditions'])) { $options['conditions'] = []; } $options['conditions'] = array_merge($options['conditions'], ['Comments.published' => 'Y']); return parent::find($type, $options); }
public function find($type = 'all', $options = []) { $data = parent::find($type, $options); return $data->formatResults(function ($r) { return $r->map(function ($r) { $r['number'] = $this->showNumber($r['number']); return $r; }); }); }
/** * Returns the maximum index value in the table. * * @return int */ protected function _getMax() { $config = $this->config(); $field = $config['right']; $edge = $this->_scope($this->_table->find())->select([$field])->order([$field => 'DESC'])->first(); if (empty($edge->{$field})) { return 0; } return $edge->{$field}; }
/** * Implementation of afterDelete event for images table, handles deleting image files. * * @param Event $event Event object. * @param Entity $entity Entity object. * @param \ArrayObject $options Options array. * @return void */ public function imageAfterDelete(Event $event, Entity $entity, \ArrayObject $options) { $shared = $this->_imagesTable->find()->where(['foreign_key !=' => $entity->foreign_key, 'model' => $entity->model, 'filename' => $entity->filename]); if (!$shared->count()) { $basePath = $this->basePath(); (new File($basePath . DS . $entity->filename))->delete(); foreach ($this->config('presets') as $preset => $options) { (new File($basePath . DS . $preset . DS . $entity->filename))->delete(); } } }
/** * Modifies the entity before it is saved so that translated fields are persisted * in the database too. * * @param \Cake\Event\Event $event The beforeSave event that was fired * @param \Cake\Datasource\EntityInterface $entity The entity that is going to be saved * @param \ArrayObject $options the options passed to the save method * @return void */ public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options) { $locale = $entity->get('_locale') ?: $this->locale(); $newOptions = [$this->_translationTable->alias() => ['validate' => false]]; $options['associated'] = $newOptions + $options['associated']; $this->_bundleTranslatedFields($entity); $bundled = $entity->get('_i18n') ?: []; $noBundled = count($bundled) === 0; // No additional translation records need to be saved, // as the entity is in the default locale. if ($noBundled && $locale === $this->config('defaultLocale')) { return; } $values = $entity->extract($this->_config['fields'], true); $fields = array_keys($values); $noFields = empty($fields); // If there are no fields and no bundled translations, or both fields // in the default locale and bundled translations we can // skip the remaining logic as its not necessary. if ($noFields && $noBundled || $fields && $bundled) { return; } $primaryKey = (array) $this->_table->primaryKey(); $key = $entity->get(current($primaryKey)); // When we have no key and bundled translations, we // need to mark the entity dirty so the root // entity persists. if ($noFields && $bundled && !$key) { foreach ($this->_config['fields'] as $field) { $entity->dirty($field, true); } return; } if ($noFields) { return; } $model = $this->_config['referenceName']; $preexistent = $this->_translationTable->find()->select(['id', 'field'])->where(['field IN' => $fields, 'locale' => $locale, 'foreign_key' => $key, 'model' => $model])->bufferResults(false)->indexBy('field'); $modified = []; foreach ($preexistent as $field => $translation) { $translation->set('content', $values[$field]); $modified[$field] = $translation; } $new = array_diff_key($values, $modified); foreach ($new as $field => $content) { $new[$field] = new Entity(compact('locale', 'field', 'content', 'model'), ['useSetters' => false, 'markNew' => true]); } $entity->set('_i18n', array_merge($bundled, array_values($modified + $new))); $entity->set('_locale', $locale, ['setter' => false]); $entity->dirty('_locale', false); foreach ($fields as $field) { $entity->dirty($field, false); } }
/** * Find or create new draft database entry and return entity ID * * @param \Cake\ORM\Table $table Table instance * @param array|null $conditions Find conditions * * @return int $id Draft Id */ public function getDraftId(Table $table, $conditions = []) { $conditions = array_merge($this->config[$table->alias()]['conditions'], $conditions); $result = $table->find()->select(['id' => $table->primaryKey()])->andWhere($conditions)->first(); if ($result) { return $result->id; } else { $entity = $table->newEntity($conditions, ['validate' => false]); $entity = $table->save($entity); return $entity->id; } }
/** * Merges each of the elements from `$data` into each of the entities in `$entities` * and recursively does the same for each of the association names passed in * `$options`. When merging associations, if an entity is not present in the parent * entity for a given association, a new one will be created. * * Records in `$data` are matched against the entities using the primary key * column. Entries in `$entities` that cannot be matched to any record in * `$data` will be discarded. Records in `$data` that could not be matched will * be marshalled as a new entity. * * When merging HasMany or BelongsToMany associations, all the entities in the * `$data` array will appear, those that can be matched by primary key will get * the data merged, but those that cannot, will be discarded. * * ### Options: * * - validate: Whether or not to validate data before hydrating the entities. Can * also be set to a string to use a specific validator. Defaults to true/default. * - associated: Associations listed here will be marshalled as well. * - fieldList: A whitelist of fields to be assigned to the entity. If not present, * the accessible fields list in the entity will be used. * - accessibleFields: A list of fields to allow or deny in entity accessible fields. * * @param array|\Traversable $entities the entities that will get the * data merged in * @param array $data list of arrays to be merged into the entities * @param array $options List of options. * @return array */ public function mergeMany($entities, array $data, array $options = []) { $primary = (array) $this->_table->primaryKey(); $indexed = (new Collection($data))->groupBy(function ($el) use($primary) { $keys = []; foreach ($primary as $key) { $keys[] = isset($el[$key]) ? $el[$key] : ''; } return implode(';', $keys); })->map(function ($element, $key) { return $key === '' ? $element : $element[0]; })->toArray(); $new = isset($indexed[null]) ? $indexed[null] : []; unset($indexed[null]); $output = []; foreach ($entities as $entity) { if (!$entity instanceof EntityInterface) { continue; } $key = implode(';', $entity->extract($primary)); if ($key === null || !isset($indexed[$key])) { continue; } $output[] = $this->merge($entity, $indexed[$key], $options); unset($indexed[$key]); } $maybeExistentQuery = (new Collection($indexed))->map(function ($data, $key) { return explode(';', $key); })->filter(function ($keys) use($primary) { return count(array_filter($keys, 'strlen')) === count($primary); })->reduce(function ($query, $keys) use($primary) { $fields = array_map([$this->_table, 'aliasField'], $primary); return $query->orWhere($query->newExpr()->and_(array_combine($fields, $keys))); }, $this->_table->find()); if (!empty($indexed) && count($maybeExistentQuery->clause('where'))) { foreach ($maybeExistentQuery as $entity) { $key = implode(';', $entity->extract($primary)); if (isset($indexed[$key])) { $output[] = $this->merge($entity, $indexed[$key], $options); unset($indexed[$key]); } } } foreach ((new Collection($indexed))->append($new) as $value) { if (!is_array($value)) { continue; } $output[] = $this->one($value, $options); } return $output; }
/** * testBeforeFind * * @return void * @access public */ public function testBeforeFind() { $condicoes = ['nome' => '1.000,00', 'valor' => '1.500,03']; $consulta = $this->Produtos->find('all')->where($condicoes); $consulta->all(); $condicoesTratadas = []; $todosCampos = []; /** * @var Query $consulta */ $consulta->clause("where")->traverse(function ($comparison) use(&$condicoesTratadas, &$todosCampos) { /** * @var Comparison $comparison */ if (isset($comparison)) { if ($this->Produtos->schema()->columnType($comparison->getField()) === "float") { $condicoesTratadas[$comparison->getField()] = $comparison->getValue(); } $todosCampos[$comparison->getField()] = $comparison->getValue(); } }); $this->assertEquals("1.000,00", $todosCampos["nome"]); $this->assertEquals("1500.03", $condicoesTratadas["valor"]); }
/** * Finds all the categories * * @param Table $extensionsTable The extensions database table * @return array The categories and all their settings */ protected function _getSettings(Table $extensionsTable) { $extensions = $extensionsTable->find('all', ['fields' => ['Extensions.id', 'Extensions.short_name'], 'contain' => ['Categories' => ['fields' => ['Categories.id', 'Categories.extension_id', 'Categories.short_name', 'Categories.enabled'], 'Settings' => ['fields' => ['Settings.short_name', 'Settings.category_id', 'Settings.default_value'], 'SettingValues' => ['fields' => ['SettingValues.value']]]]]])->all()->toArray(); $extensions = Hash::combine($extensions, '{n}.short_name', '{n}'); foreach ($extensions as $extension) { $extension->categories = Hash::combine($extension->categories, '{n}.short_name', '{n}'); foreach ($extension->categories as $category) { $category->settings = Hash::combine($category->settings, '{n}.short_name', '{n}'); foreach ($category->settings as $setting) { if (isset($setting->setting_value->value)) { $setting->setting_value = $setting->setting_value->value; } } } } return $extensions; }
/** * Retrieve and return associated record Entity, by primary key value. * If the record has been trashed - query will return NULL. * * @param \Cake\ORM\Table $table Table instance * @param string $value Primary key value * @return object */ protected function _getAssociatedRecord(Table $table, $value) { $options = ['conditions' => [$table->primaryKey() => $value], 'limit' => 1]; // try to fetch with trashed if finder method exists, otherwise fallback to find all try { $query = $table->find('withTrashed', $options); } catch (BadMethodCallException $e) { $query = $table->find('all', $options); } return $query->first(); }
/** * Tests find('list') with composite keys * * @return void */ public function testFindListCompositeKeys() { $table = new Table(['table' => 'site_authors', 'connection' => $this->connection]); $table->displayField('name'); $query = $table->find('list')->hydrate(false)->order('id'); $expected = ['1;1' => 'mark', '2;2' => 'juan', '3;2' => 'jose', '4;1' => 'andy']; $this->assertEquals($expected, $query->toArray()); $table->displayField(['name', 'site_id']); $query = $table->find('list')->hydrate(false)->order('id'); $expected = ['1;1' => 'mark;1', '2;2' => 'juan;2', '3;2' => 'jose;2', '4;1' => 'andy;1']; $this->assertEquals($expected, $query->toArray()); $query = $table->find('list', ['groupField' => ['site_id', 'site_id']])->hydrate(false)->order('id'); $expected = ['1;1' => ['1;1' => 'mark;1', '4;1' => 'andy;1'], '2;2' => ['2;2' => 'juan;2', '3;2' => 'jose;2']]; $this->assertEquals($expected, $query->toArray()); }
/** * Checks whether a variable is an array * * @param Table $table Instance of a table * @param string $methodName Name of method * @param string $findMethod Find method to use * @param array $findOptions array of options to pass to the table method * @return mixed **/ public function getData(Table $Table, $methodName, $findMethod, $findOptions) { if (empty($methodName)) { $methodName = 'find'; } if (empty($findMethod)) { $findMethod = 'first'; } if ($methodName == 'find') { return $Table->find($findMethod, $findOptions); } return $Table->{$methodName}($findOptions); }
/** * Login and submit a POST request to a $url that is expected to add a given record. * Retrieve the record with the highest id, which we hope is the new record we just * added, and return that to the caller. * * @param int $user_id The user to login as. * @param String $url The url to send the request to. * @param array $newRecord * @param String $redirect_url The url to redirect to, after the deletion. * @param \Cake\ORM\Table $table The table to receive the new record. * @param boolean $redirect2_new_id By default, redirection should go to $redirect_url. However, * if $redirect2_new_id=true, then redirect to $redirect_url/$redirect2_new_id. * * @return \Cake\ORM\Entity The newly added record, as read from the db. */ protected function genericPOSTAddProlog($user_id, $url, $newRecord, $redirect_url, $table, $redirect2_new_id = false) { //$this->fakeLogin($user_id); $this->post($url, $newRecord); // Now retrieve the newly written record. $fromDbRecord = $table->find('all')->order(['id' => 'DESC'])->first(); $this->assertResponseCode(302); if ($redirect2_new_id) { $this->assertRedirect("{$redirect_url}/{$fromDbRecord->id}"); } else { $this->assertRedirect($redirect_url); } return $fromDbRecord; }
/** * Test find('list') with value field from associated table * * @return void */ public function testFindListWithAssociatedTable() { $articles = new Table(['table' => 'articles', 'connection' => $this->connection]); $articles->belongsTo('Authors'); $query = $articles->find('list', ['valueField' => 'author.name'])->contain(['Authors'])->order('articles.id'); $this->assertEmpty($query->clause('select')); $expected = [1 => 'mariano', 2 => 'larry', 3 => 'mariano']; $this->assertSame($expected, $query->toArray()); }
/** * Processes the records. * * @param \Cake\ORM\Table $table * @param int $chunkCount * @param int $chunkSize * @return void */ protected function _process(Table $table, $chunkCount, $chunkSize) { $query = $table->find(); if ($table->hasFinder('purifier')) { $query->find('purifier'); } $fields = explode(',', $this->param('fields')); $fields[] = $table->primaryKey(); $results = $query->select($fields)->offset($chunkCount)->limit($chunkSize)->orderDesc($table->aliasField($table->primaryKey()))->all(); if (empty($results)) { return; } foreach ($results as $result) { try { $table->save($result); $chunkCount++; } catch (\Exception $e) { $this->error($e->getMessage()); } } }
/** * Assert MPTT values * * Custom assert method to make identifying the differences between expected * and actual db state easier to identify. * * @param array $expected tree state to be expected * @param \Cake\ORM\Table $table Table instance * @param \Cake\ORM\Query $query Optional query object * @return void */ public function assertMpttValues($expected, $table, $query = null) { $query = $query ?: $table->find(); $primaryKey = $table->primaryKey(); if (is_array($primaryKey)) { $primaryKey = $primaryKey[0]; } $displayField = $table->displayField(); $options = ['valuePath' => function ($item, $key, $iterator) use($primaryKey, $displayField) { return sprintf('%s:%s - %s:%s', str_pad($item->lft, 2, ' ', STR_PAD_LEFT), str_pad($item->rght, 2, ' ', STR_PAD_LEFT), str_pad($item->{$primaryKey}, 2, ' ', STR_PAD_LEFT), $item->{$displayField}); }]; $result = array_values($query->find('treeList', $options)->toArray()); if (count($result) === count($expected)) { $subExpected = array_diff($expected, $result); if ($subExpected) { $subResult = array_intersect_key($result, $subExpected); $this->assertSame($subExpected, $subResult, 'Differences in the tree were found (lft:rght id:display-name)'); } } $this->assertSame($expected, $result, 'The tree is not the same (lft:rght id:display-name)'); }