Is it possible to do a "BETWEEN ? AND ?" where condition LIKE in cakephp 2.5?
In cakephp 2.5 I write something like
'conditions' => ['start_date BETWEEN ? AND ?' => ['2014-01-01', '2014-12-32']]
how can I migrate that?
additionally I would write something like
'conditions' => [ '? BETWEEN start_date AND end_date'] => '2014-03-31']
Expressions
Between expression are supported out of the box, however they only support the first case without additional fiddling:
$Query = $Table
->find()
->where(function($exp) {
return $exp->between('start_date', '2014-01-01', '2014-12-32', 'date');
});
If you'd wanted to handle the second case via the between method, then you'd have to pass all values as expressions, which can easily go wrong, as they will not be subject to escaping/parameter binding in that case, you'd have to do that on your own (which is anything but recommended! See the security notes in the manual for PDO::quote()), something along the lines of:
use Cake\Database\Expression\IdentifierExpression;
use Cake\Database\Expression\QueryExpression;
use Cake\ORM\Query;
// ...
$Query = $Table
->find()
->where(function(QueryExpression $exp, Query $query) {
return $exp->between(
$query->newExpr(
$query->connection()->driver()->quote(
'2014-03-31',
\PDO::PARAM_STR
)
),
new IdentifierExpression('start_date'),
new IdentifierExpression('end_date')
);
});
That might feel a little inconvenient for such a basic SQL expression that is supported by all SQL dialects that CakePHP ships with, so you may have a reason here to use a raw SQL snippet with value bindig instead.
It should be noted however that expressions are often the better choice when it comes to for example cross dialect support, as they can be (more or less) easily transformed at compile time, see the implementations of SqlDialectTrait::_expressionTranslators(). Also expressions usually support automatic identifier quoting.
Value binding
Via manual value binding you can pretty much create anything you like. It should however be noted that whenever possible, you should use expressions instead, as they are easier to port, which happens out of the box for quite a few expressions already.
$Query = $Table
->find()
->where([
'start_date BETWEEN :start AND :end'
])
->bind(':start', '2014-01-01', 'date')
->bind(':end', '2014-12-31', 'date');
That way the second case can also be solved very easily, like:
$Query = $Table
->find()
->where([
':date BETWEEN start_date AND end_date'
])
->bind(':date', '2014-03-31', 'date');
A mixture of both (safest and most compatible approach)
It's also possible to mix both, ie use an expression that makes use of custom bindings, something along the lines of this:
use Cake\Database\Expression\IdentifierExpression;
use Cake\Database\Expression\QueryExpression;
use Cake\ORM\Query;
// ...
$Query = $Table
->find()
->where(function(QueryExpression $exp, Query $query) {
return $exp->between(
$query->newExpr(':date'),
new IdentifierExpression('start_date'),
new IdentifierExpression('end_date')
);
})
->bind(':date', '2014-03-31', 'date');
That way you could handle the second case using possibly portable expressions, and don't have to worry about quoting/escaping input data and identifiers manually.
Regular comparison using array syntax
All that being said, in the end BETWEEN is just the same as using two separate simple conditions like this:
$Query = $Table
->find()
->where([
'start_date >=' => '2014-01-01',
'start_date <=' => '2014-12-32',
]);
$Query = $Table
->find()
->where([
'start_date >=' => '2014-03-31',
'end_date <=' => '2014-03-31',
]);
But don't be mad, if you read all the way down to here, at least you learned something about the ins and outs of the query builder.
See also
Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
API > \Cake\Database\Query::bind()
Currently there seems to be only two options. The core now supports this out of the box, the following is just kept for reference.
Value binding (via the database query builder)
For now the ORM query builder (Cake\ORM\Query), the one that is being retrived when invoking for example find() on a table object, doesn't support value binding
https://github.com/cakephp/cakephp/issues/4926
So, for being able to use bindings you'd have to use the underlying database query builder (Cake\Database\Query), which can for example be retrived via Connection::newQuery().
Here's an example:
$conn = ConnectionManager::get('default');
$Query = $conn->newQuery();
$Query
->select('*')
->from('table_name')
->where([
'start_date BETWEEN :start AND :end'
])
->bind(':start', new \DateTime('2014-01-01'), 'date')
->bind(':end', new \DateTime('2014-12-31'), 'date');
debug($Query->execute()->fetchAll());
This would result in a query similar to this
SELECT
*
FROM
table_name
WHERE
start_date BETWEEN '2014-01-01' AND '2014-12-31'
A custom expression class
Another option would be a custom expression class that generates appropriate SQL snippets. Here's an example.
Column names should be wrapped into identifier expression objects in order to them be auto quoted (in case auto quoting is enabled), the key > value array syntax is for binding values, where the array key is the actual value, and the array value is the datatype.
Please note that it's not safe to directly pass user input for column names, as they are not being escaped! Use a whitelist or similar to make sure the column name is safe to use!
Field between values
use App\Database\Expression\BetweenComparison;
use Cake\Database\Expression\IdentifierExpression;
// ...
$between = new BetweenComparison(
new IdentifierExpression('created'),
['2014-01-01' => 'date'],
['2014-12-31' => 'date']
);
$TableName = TableRegistry::get('TableName');
$Query = $TableName
->find()
->where($between);
debug($Query->execute()->fetchAll());
This would generate a query similar to the one above.
Value between fields
use App\Database\Expression\BetweenComparison;
use Cake\Database\Expression\IdentifierExpression;
// ...
$between = new BetweenComparison(
['2014-03-31' => 'date'],
new IdentifierExpression('start_date'),
new IdentifierExpression('end_date')
);
$TableName = TableRegistry::get('TableName');
$Query = $TableName
->find()
->where($between);
debug($Query->execute()->fetchAll());
This on the other hand would result in a query similar to this
SELECT
*
FROM
table_name
WHERE
'2014-03-31' BETWEEN start_date AND end_date
The expression class
namespace App\Database\Expression;
use Cake\Database\ExpressionInterface;
use Cake\Database\ValueBinder;
class BetweenComparison implements ExpressionInterface {
protected $_field;
protected $_valueA;
protected $_valueB;
public function __construct($field, $valueA, $valueB) {
$this->_field = $field;
$this->_valueA = $valueA;
$this->_valueB = $valueB;
}
public function sql(ValueBinder $generator) {
$field = $this->_compilePart($this->_field, $generator);
$valueA = $this->_compilePart($this->_valueA, $generator);
$valueB = $this->_compilePart($this->_valueB, $generator);
return sprintf('%s BETWEEN %s AND %s', $field, $valueA, $valueB);
}
public function traverse(callable $callable) {
$this->_traversePart($this->_field, $callable);
$this->_traversePart($this->_valueA, $callable);
$this->_traversePart($this->_valueB, $callable);
}
protected function _bindValue($value, $generator, $type) {
$placeholder = $generator->placeholder('c');
$generator->bind($placeholder, $value, $type);
return $placeholder;
}
protected function _compilePart($value, $generator) {
if ($value instanceof ExpressionInterface) {
return $value->sql($generator);
} else if(is_array($value)) {
return $this->_bindValue(key($value), $generator, current($value));
}
return $value;
}
protected function _traversePart($value, callable $callable) {
if ($value instanceof ExpressionInterface) {
$callable($value);
$value->traverse($callable);
}
}
}
You can use one of following 2 methods.
Method 1 :
$start_date = '2014-01-01 00:00:00';
$end_date = '2014-12-31 23:59:59';
$query = $this->Table->find('all')
->where(function ($exp, $q) use($start_date,$end_date) {
return $exp->between('start_date', $start_date, $end_date);
});
$result = $query->toArray();
Method 2:
$start_date = '2014-01-01 00:00:00';
$end_date = '2014-12-31 23:59:59';
$query = $this->Table->find('all')
->where([
'start_date BETWEEN :start AND :end'
])
->bind(':start', new \DateTime($start_date), 'datetime')
->bind(':end', new \DateTime($end_date), 'datetime');
$result = $query->toArray();
I'm using it like this
$this->Table->find()->where(['data_inicio BETWEEN '.'\''.$data_inicio.'\''.' AND .'\''.$data_final.'\''.' ']);
Hello guys please use this query to get data on the basis of range of value
$query = $this->Leads->find('all',
array('conditions'=>array('postcode BETWEEN '.$postcodeFrom.' and'.$postcodeTo.''), 'recursive'=>-1));
debug($query);
print_r($query->toArray());
Related
CakePHP 3.7
I'm trying to generate a query which uses a WHERE...OR pattern. The equivalent in MySQL - which executes and gives the results I want is:
SELECT * FROM groups Groups WHERE (regulation_id = 1 AND label like '%labelling%') OR (id IN(89,1,8,232,228,276,268,294));
I've read the Advanced Conditions (https://book.cakephp.org/3.0/en/orm/query-builder.html#advanced-conditions) part of the documentation but can't generate that query.
Assume the Table class is Groups I have this:
$Groups = TableRegistry::getTableLocator()->get('Groups');
$groups_data = $Groups->find('all')->where(['regulation_id' => 1);
$groups_data = $groups_data->where(['label LIKE' => '%labelling%']);
This produces the first segment of the WHERE statement, i.e.
SELECT * FROM groups Groups WHERE (regulation_id = 1 AND label like '%labelling%')
However I can't see how to attach the OR condition, especially since orWhere() is deprecated.
So I've tried this - which is even given as an example in the docs:
$in_array = [89,1,8,232,228,276,268,294]; // ID's for IN condition
$groups_data = $groups_data->where(['OR' => ['id IN' => $in_array]]);
But this just appends an AND to the inside of my existing SQL:
SELECT * FROM groups Groups WHERE (regulation_id = 1 AND label like '%labelling%' AND id IN(89,1,8,232,228,276,268,294);
Which does not yield the correct results as the syntax isn't what's required to run this query.
How do you "move out" of the WHERE and append an OR condition like in the vanilla query?
I made several attempts using QueryExpression as per the docs, but all of these produced PHP Fatal Errors saying something to do with the Table class - I doubt this was on the right lines anyway.
"moving out" is a little tricky, you have to understand that internally the conditions are pushed into a \Cake\Database\Expression\QueryExpression object which by default uses AND to concatenate the statements, so whatever you push on to that, will be added using AND.
When you create OR statements, being it implicitly with the shown nested array syntax, or explicitly by using the expression builder, this creates a separate, self-contained expression, where its parts are being concatenated using OR, it will compile itself (and since there's only one condition, you don't see any OR's), and the result will be used in the parent expression, which in your case is the main/base expression object for the queries where clause.
Either pass the whole thing at once (being it via array syntax or expressions), eg:
$groups_data->where([
'OR' => [
'AND' => [
'regulation_id' => 1,
'label LIKE' => '%labelling%'
],
'id IN' => $in_array
]
]);
and of course you could build that array dynamically if required, or, if you for some reason need to use separate calls to where(), you could for example overwrite the conditions (third parameter of where()), and include the current ones where you need them:
$groups_data->where(
[
'OR' => [
$groups_data->clause('where'),
'id IN' => $in_array
]
],
[],
true
);
I know this issue is old but maybe someone is looking. Here is my solution:
protected $_hardValues= array(
'company_id' => $company_from_session;
);
function beforeFind($event=null, $query = null, $options = null, $primary = true){
$conds = [];
$columns = $this->getSchema()->columns();
foreach( $this->_hardValues as $field => $value){
if( !is_null($value) && in_array($field, $columns) ){
$conds[$this->_alias . '.' . $field] = $value;
}
}
if( empty( $conds)) return true;
$where = $query->clause('where'); //QueryExpression object;
if( empty( $where)){
$query->where($conds);
}else{
$where->add($conds);
}
}
As of CakePHP 4.x, the documented way of doing this is:
$query = $articles->find()
->where([
'author_id' => 3,
'OR' => [['view_count' => 2], ['view_count' => 3]],
]);
See documentation
I'm trying to pull a column out of the database, simple enough right? I'm using codeigniter's active record.
My Model Function
public function getcolumn($field, $table, $kfield, $key)
{
$this->db->select($field);
$this->db->from($table);
$this->db->where($kfield, $key);
$query = $this->db->get();
$results = $query->result();
return $results;
}
My Controller has:
public function users()
{
$body['handle'] = $this->admin->getcolumn('handle', 'users', 'userid', $userid)
$this->load->view('template/header');
$this->load->view('admin/users', $body);
$this->load->view('template/footer');
}
now when I print_r that variable in my view I get "Array ( [0] => stdClass Object ( [handle] => Zanigade ) ) "
Since I'm trying to use this function as a global "grab and go" function without writing a ton of functions, why won't it just return the name? What am I doing wrong? I've been playing with the output for 3 hours and I know this is a stupid easy fix and I'm just missing the mark.
Any help will be appreciated.
Put it all together using the "chaining" capability like so
$results = this->db->get()->row()->$field;
We get() one row() which (should) contain a field named $field.
It seems you are returning the result instead of single row, try this
public function getcolumn($field, $table, $kfield, $key)
{
$this->db->select($field);
$this->db->from($table);
$this->db->where($kfield, $key);
$query = $this->db->get();
return $query->row()->$field;
}
For More Information, Check the codeigniter user guide
https://www.codeigniter.com/userguide3/database/examples.html
Is there anyway to have cake do a multi-row insert in a single query without writing raw SQL to do this? The saveMany and saveAssociated options will only save multiple rows in a single transaction, but that transaction contains multiple insert statements so these methods are clearly not a solution to write heavy applications.
Thanks for reading.
Yes
Though it's not a common practice to do so in app-land code, and doing so removes the possibility to use almost any application logic (validation rules, behaviors, events etc.). You can see an example of doing this in the way fixtures are loaded:
$db = ConnectionManager::getDataSource('default');
$table = "stuffs";
$fields = array('id', 'name');
$values = array(
array(1, 'one'),
array(2, 'two'),
...
);
$result = $db->insertMulti($table, $fields, $values);
You may also find this repository useful (either directly or as a basis for your code) which loads fixture files into your app database - using multi-inserts.
Yes, Big_Data is good idea for inserting bulk. But as AD7six note, it still use basic value quoting and does not return insert ids. And base on your ideas, i wrote small script to inserting bulk in a single query, using default CakePHP quoting and returning ids of inserted records.
$count = count($records);
$dbSource = $this->getDataSource();
$table = $dbSource->fullTableName($this->table);
$fields = $dbSource->prepareFields($this, array('fields' => array_keys($records[0])));
$values = array();
foreach ($records as $index => $record) {
if (!is_array($record) || !$record) {
return null;
}
foreach ($record as $column => $value) {
$values[$index][$column] = $dbSource->value($value, $this->getColumnType($column));
}
$values[$index] = '(' . implode(',', $values[$index]) . ')';
}
$query = 'INSERT INTO %s (%s) VALUES %s;';
$query = sprintf($query, $table, implode(',', $fields), implode(',', $values));
if (!$dbSource->execute($query)) {
return false;
}
$lastInsertId = $dbSource->getConnection()->lastInsertId();
$insertIds = array();
for ($i = 0; $i < $count; $i++) {
$insertIds[] = $lastInsertId + $i;
}
return $insertIds;
Someone pointed me towards the Big Data Behavior https://github.com/jmillerdesign/CakePHP_Big_Data
If you are using CakePHP 3.0 you can check the answer to this question: How to use insert in query builder insert multiple records?
If you are using CakePHP 2 you will have to use raw SQL like this:
$sql = "INSERT INTO `people` (`name`,`title`) VALUES ";
foreach($people as $person){
list($name,$title) = $person;
$sql.= "('$name','$title'),";
}
$this->query(substr($sql,0,-1));
Source: Inserting Multiple Rows with CakePHP 3
yes you can use like below
The getDataSource() method is static in CakePHP 2.x, so you should be able to use:
$db = ConnectionManager::getDataSource('default');
$db->rawQuery($some_sql);
here i am posting method to do. you have to create some SQL statement manually to insert multiple row in one time.
Please let me know if i can help you more.
OK, this is the situation. In my beforeSave function I want to manipulate some $this->request->data entries.
This is my component:
<?php
App::uses('Component', 'Controller');
class GetStationComponent extends Component {
public function getStationId ($station) {
$stationInstance = ClassRegistry::init('Station');
$conditions = array('OR' => array(
array('Station.code LIKE' => $station),
array('Station.naam LIKE' => $station),
array('Station.naam_overig LIKE' => $station)
));
$result = $stationInstance->find('list', array('conditions'=>$conditions));
$value = array_values($result);
$value = $value[0];
return $value;
}
}
?>
And this is my beforeSave function in my Controller:
public function beforeSave($options = array()) {
if (!empty($this->request->data['Experience']['vertrekstation']) && !empty($this->request->data['Experience']['aankomststation'])) {
$this->request->data['Experience']['vertrekstation'] = $this->GetStation->getStationId($this->request->data['Experience']['vertrekstation']);
$this->request->data['Experience']['aankomststation'] = $this->GetStation->getStationId($this->request->data['Experience']['aankomststation']);
}
return true;
}
It should return an ID of the stations name. But in the Database the name itself is stored (which is filled in by the user) instead of the ID. What do I need to change in my Component (I guess...) to return the right values?
(P.S. The query itself in the component returns an ID, because at first I'd put the 'beforeSave' directly into my function which saves the data, but then my validation error said that it wasn't a right value. Which is correct...)
To complement the other answers; to get just the value of a single field, use Model::field()
return $stationInstance->field('id', $conditions);
It is best to add a sort order to this statement to make sure that the results will always be returned in the same order:
return $stationInstance->field('id', $conditions, 'code ASC');
Since you only perform a single query on the Model, and don't do anything afterwards, you don't even need the intermediate $stationInstance variable. Your code can be further simplified to:
return ClassRegistry::init('Station')->field('id', $conditions, 'code ASC');
Some observations
Because of the 'fuzzy' matching on the name of the station, the first result may not always be the station intended by the user it's best to offer an 'autocomplete' functionality in your front-end and have the user pick the correct station (e.g. To prevent picking Den Haag when the user meant Den Haag HS)
If the station does not fully matches a station, you should present a warning that the station wasn't found
You didn't surround your search-terms with % for the LIKE queries. If you intend to search for 'name "contains", you should use '%' . $station . '%'. For "starts with" use $station . '%'
As #mark suggested; beforeSave() is a callback of the Model and should be located there.
Also; beforeSave() is triggered after validation has taken place, so it will probably be too late. beforeValidate() is the best callback for this
If the Experience model is already attached to the Station model, you don't need to use a component, because you can directly access the Station model. It's best to put the search-method inside the Station model;
Moving it all to the right(*) location
*) Other options are always possible, this is just a possible approach
Add the 'search' method to the Station-model;
app/Model/Station.php
public function getStationIdByName($name)
{
$name = trim($name);
if (empty($name)) {
return null;
}
$name = '%' . $name . '%';
$conditions = array(
'OR' => array(
array($this->alias . '.code LIKE' => $name),
array($this->alias . '.naam LIKE' => $name),
array($this->alias . '.naam_overig LIKE' => $name),
)
);
return $this->field('id', $conditions, 'code ASC');
}
..and use it in the Experience Model
app/Model/Experience.php
public function beforeValidate(array $options = array())
{
if (
!empty($this->data[$this->alias]['vertrekstation'])
&& !empty($this->data[$this->alias]['aankomststation'])
) {
// Directly access the Station-model from within the Experience Model
$this->data[$this->alias]['vertrekstation']
= $this->Station->getStationIdByName($this->data[$this->alias]['vertrekstation']);
$this->data[$this->alias]['aankomststation']
= $this->Station->getStationIdByName($this->data[$this->alias]['aankomststation']);
}
// Call parent-callback after setting the values
return parent::beforeValidate($options);
}
[UPDATE] Using the Conventions, prevent unwanted behavior
After writing the previous example, I noticed there are some flaws in your current setup;
If vertrekstation and aankomststation should hold the 'foreign key' of the station (the station-id) they are not named according to the CakePHP Model and Database Conventions
Because of 1) By putting this code inside the beforeValidate(), it will also be triggered when updating an existing record. Because you're using the aankomststation and vertrekstation field both to hold the name of the station (inside the Form) and the id (inside the database), the Model will attempt to look-up the station-id via the id when updating. NOTE that inside the form you'll still be using vertrekstation and aankomstation as field-name. These field names are not present in your database, and therefore will not be able to directly update data inside your database, that's where the beforeValidate() callback is used for
Because the Experience model needs two relations to the Station model (once as departure station ('vertrekstation'), once for arrival station ('aankomststation')), you will need an alias for the Station-model. See: Multiple relations to the same model
app/Model/Experience.php
class Experience extends AppModel {
/**
* Station will be associated to the 'Experience' Model TWICE
* For clarity, using an 'alias' for both associations
*
* The associated Models will be accessible via;
* $this->DepartureStation
* $this->ArrivalStation
*
* To stick to the CakePHP conventions, name the foreign keys
* accordingly
*/
public $belongsTo = array(
'DepartureStation' => array(
'className' => 'Station',
'foreignKey' => 'departure_station_id',
),
'ArrivalStation' => array(
'className' => 'Station',
'foreignKey' => 'arrival_station_id',
)
);
public function beforeValidate(array $options = array())
{
// vertrekstation and aankomststation hold the 'names' of the
// stations and will only be present if the form has been submitted
if (
!empty($this->data[$this->alias]['vertrekstation'])
&& !empty($this->data[$this->alias]['aankomststation'])
) {
// Directly access the Station-model from within the Experience Model
// using the *aliases*
$this->data[$this->alias]['departure_station_id']
= $this->DepartureStation->getStationIdByName($this->data[$this->alias]['vertrekstation']);
$this->data[$this->alias]['arrival_station_id']
= $this->ArrivalStation->getStationIdByName($this->data[$this->alias]['aankomststation']);
// Invalidate the vertrekstation and aankomststation fields if lookup failed
if (empty($this->data[$this->alias]['departure_station_id'])) {
// Unable to find a station. Mark the Form-field invalid
$this->invalidate('vertrekstation', __('A station with this name was not found'));
}
if (empty($this->data[$this->alias]['arrival_station_id'])) {
// Unable to find a station. Mark the Form-field invalid
$this->invalidate('aankomststation', __('A station with this name was not found'));
}
}
// Call parent-callback after setting the values
return parent::beforeValidate($options);
}
}
The find('list') option of Cake returns an array like
array( 1 => 'name1',
3 => 'name2',
//etc...
)
where the index is the id and the value is the display field you set on the model.
So, when you do $value = array_values($result);, you're extracting the values of the array (meaning, the display fields). I'm assuming you're not using the id as the displayField, so that's why it's returning the names and not the id.
I'm not sure why you're using find('list') instead of find('first') or other alternative, but if you don't want to modify that for whatever reason, the fix that should return the first id obtained by the search is
reset($result); //possibly not needed, but just in case
$value = key($result );
First you must understand how Cake works
There is no $this->request in your models. Its part of the controller.
In your model your passed data will be in $this->data directly.
public function beforeSave($options = array()) {
parent::beforeSave($options); // you also forgot the parent call
if (!empty($this->data[$this->alias]['vertrekstation']) && ...)) {
$this->data[$this->alias]['vertrekstation'] = ...;
}
return true;
}
Your find call also looks pretty screwed up. I dont know what you want to do.
But I strongly advice you to use debug() etc to find out what is returned and correct your code accordingly.
You probably need find(first) if you are only interesting in a single value.
Using Yii, how can I get an array from an Active Record.
Say something like this:
array('foo', 'bar', 'lala')
From something like this:
MyTable::model()->findall()
If i understand you correctly:
$users = User::model()->findAll();
$usersArr = CHtml::listData( $users, 'id' , 'name');
print_r( $usersArr );
It will give you array id => name
Array {
2 => 'someone',
20 => 'kitty',
102 => 'Marian',
// ...
}
For yii2 , use:
yii\helpers\ArrayHelper::map(MyModel::find()->all(), 'id', 'name'));
or
yii\helpers\ArrayHelper::getColumn(MyModel::find()->all(), 'name'));
ActiveRecord class has an attribute called attributes. You can find its description here: http://www.yiiframework.com/doc/api/1.1/CActiveRecord#attributes-detail.
In order to get all attributes in an array, use this: $var = $model->attributes;
You could also do something like
$countries = Country::model()->findAll();
array_values(CHtml::listData($countries, 'country_id', 'country_name'));
which returns an array of all country names, or
array_keys(CHtml::listData($countries, 'country_id', 'country_name'));
which returns an array of all country ids.
How about:
Yii::app()->db->createCommand()
->setFetchMode(PDO::FETCH_COLUMN,0)
->select("mycolumn")
->from(MyModel::model()->tableSchema->name)
->queryAll();
The result would be:
array('foo', 'bar', 'lala')
Use the Yii2 ArrayHelper by including to your controller this will convert a model data to an associated array
use yii\helpers\ArrayHelper;
$post = ArrayHelper::toArray(ClientProfilesForm::findOne(['id' => 1]));
//or use it directly by
$post = yii\helpers\ArrayHelper::toArray(ClientProfilesForm::findOne(['id' => 1]));
Don't use ActiveRecord. Use CDBCommand->queryColumn()
Use Chtml to this is a Ugly Hack! Apply this solution is the better way to this that I found:
public function queryAll($condition = '', $params = array())
{
$criteria = $this->getCommandBuilder()->createCriteria($condition, $params);
$this->applyScopes($criteria);
$command = $this->getCommandBuilder()->createFindCommand($this->getTableSchema(), $criteria);
$results = $command->queryAll();
return $results;
}
You can add this code to an ActiveRecord class, e.g.:
class ActiveRecord extends CActiveRecord {
//...
}
And, use this way:
return $model->queryAll($criteria);
You can read more about in this link.
if you are using Yii1.1 and you need to get ALL data from AR as array you need to care about that it self. Yii1.1 AR doesn't have this feature out of the box
In Yii2 AR has asArray() method, it's very helpful
I hope my answer helps someone
Model::find()->select('id')->column();
Will return array of IDs.