create dropdown with associative array - yii

I'm trying to create a dynamic dropdown from my database. i noticed when i query using Yii my it doesn't return an array in this format array(1=>1, 2=>2...) which i need for my CHtml::dropDownList()
so i added a for loop to do so. is this correct or following the framework standards? or am i missing something? sorry pretty new to yii
in my model
public function cDropdown()
{
$sql = "SELECT DISTINCT `code`, `name`
FROM `AB`
GROUP BY `code`
ORDER BY `name` ASC";
$query = Yii::app()->db->createCommand($sql)->queryAll();
$arr = array();
foreach($query AS $name=>$value)
$arr[$value['code']] = $value['name'];
return $arr;
}

You can do it in a very much simpler way by using like this: $form->dropDownList($model, 'attribute', CHtml::listData(ModelName::model()->findAll(), 'id', 'name'));
The id and the name, should be replaced by the fields you want in the dropdown. The id will be the value, and the name will be displayed.
You can also change the findAll() and use another method you want.
Okay? Good luck

Related

Yii2: how to use subquery with ActiveRecord?

I want to create a find function to use then in a GridView widget My I don't know how to use a subquery.
This is the simple version of the PostgreSQL query that I have:
SELECT color
FROM cars
LEFT JOIN (
SELECT name
FROM companies
)
Here is what I a trying and doesn't work:
$query = Cars::find()
->select([
'color' => '
SELECT name // Problem here.
FROM companies // Problem here.
',
]);
Your expected query is not what you are trying to do. You can add a custom subquery as
$query = Cars::find()
->select([
'(SELECT name FROM companies) AS xxx'
]);
But if you want to add a field from joined table to the grid, then you should have a relation defined and then you can easily add such a column to your grid. See https://www.yiiframework.com/doc/guide/2.0/en/db-active-record#relational-data
You can use instance of ActiveQuery in leftJoin() method like this:
$subQuery = Companies::find()
->select('name', 'id'); //I've added ID to show how to write on condition
$query = Cars::find()
->select('color')
->leftJoin(
['alias' => $subQuery],
'alias.id = cars.company_id'
);
See documentation for more details about leftJoin() and join() methods.
$query = Cars::find()
->select(['cars.color','companies.name'])
->leftJoin('companies', 'cars.company_id = companies.id');

TYPO3 $query->in('valOne,valTwo,valThree', $arrayTwo)

I have a query in my repository which gets all product by categories and contentTypes.
I am looking for a query like this:
$query = $this->createQuery();
$constraint = $query->in('category', $categories);
if (!empty($contentType)) {
$results = $query->matching(
$query->logicalAnd(
$constraint, $query->in('contentType', $contentType)
)
)
->setLimit((int)$limit)
->setOffset((int)$offset)
->execute()
->toArray();
It works well if 'containType' contains just a single id as string, e.g '261'.
But if it is a string with multiple id's it looks like '261,284,291' and the query does not work longer.
I hope you got all information. Let me know if not :)
You can use GeneralUtility::trimExplode() or in your case probably more specific GeneralUtility::intExplode() to turn the $contentType CSV value into an array of values suitable for QueryInterface::in().

How to write database/SQL query in Yii2, with and without a model

I have a table with multiple column and I want to return a column name using another column name as search criteria. How do I achieve this in yii2?
Below is sample code, normal sql should be:
$name = SELECT type_name FROM ProductTable WHERE type_id = 1;
echo $name;
This should return the value of the column type_name where the value of the column type_id equals 1. I tried this, but it doesn't work
$type_name = ProductTable::find()->where(['type_id' =>$model->type_id]);
$type_name = Product::find(['type_name'])->where(['type_id' =>$model->type_id]);
I also tried this, but I guess it was wrong
I hope my question is clear enough and any help will he appreciated
and u could also use createCommand!
$name = \Yii::$app->getDb()->createCommand("SELECT type_name FROM ProductTable WHERE type_id=:typeId", ['typeId'=>$model->type_id])->queryAll();
For a general introduction to Yii2's ActiveRecord, see the guide: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html
If you want the complete row and have a model, you're just missing a one():
Product::find()->where(['type_id' =>$model->type_id])->one();
If you do have a Model defined and just want a single value, try:
Product::find()->select('type_name')->where(['type_id' =>$model->type_id])->scalar();
Which basically generates an ActiveQuery via the model, and changes it to return only the first column in the first row of matched results.
If you do NOT have a model, you could also generate a normal query without ActiveRecord usage (http://www.yiiframework.com/doc-2.0/yii-db-query.html)
$name = (new Query())->select('type_name')
->from('ProductTable')
->where(['type_id' =>$model->type_id])
->scalar();
I assume you generated ProductTable by using Gii module.
Also, if type_id column is a primary key:
$product = ProductTable::findOne($model->type_id);
if($product !== null) { $product->typeName /*... read value ...*/}
or to get all records
$products = ProductTable::findAll($model->type_id); //match all records.
for any other column use the following syntax instead:
$product = ProductTable::findOne(['type_id' => $model->type_id]);
Use following code to get type_name
$PTable=ProductTable::find()->select('type_name')->where(['type_id' =>$model->type_id])->one();
echo $PTable->type_name;

Using with and together in Yii

I have a grid with paging which displays client data.
Let's say I have a table Client with name, lastName and address in it, a table Phone_Number which has phone numbers for each of the rows in Client and a table Adress which has adresses for each client. So each Client HAS MANY Phone_Numbers and HAS MANY Adresses.
The point is I'm trying to set a limit to the grid's store read.
So let's say I set limit = 2. The grid should display only 2 rows per page (2 clients).
The problem is that if, for example, client1 has two phone numbers, the query will bring two rows, making the grid display only one client. I am aware that setting together=>false in the query will solve this. But I'm getting an unknown column error whenever I set together=>false.
Here's the code I'm using....
Client::model()->with(
'clientPhoneNumbers',
'clientPhoneNumbers'.'PhoneNumber',
'clientAddresses',
'clientAddresses'.'Address'
)->findAll(array(condition=>(('Address.s_street_name LIKE :queryString') OR ('PhoneNumber.n_number LIKE :queryString')), params=>$params, order=>$order, limit=>$limit,together=>false));
If I do this, I get an error like: Column not found: Address.s_street_name . However, if I set together=>true, it works just "fine".
I found a solution to this problem by doing the query like this....
$with = array(
'clientPhoneNumbers',
'clientPhoneNumbers'.'PhoneNumber'=>array(condition=>('PhoneNumber.n_number LIKE :queryString'), params=>array(':queryString'=>$queryString)),
'clientAddresses',
'clientAddresses'.'Address'=>array(condition=>('Address.s_street_name LIKE :queryString'), params=>array(':queryString'=>$queryString))
);
Client::model()->findAll(array(with=>$with, order=>$order, limit=>$limit,together=>false));
The problem is that if I do it like this, the condition is something like this
(('Address.s_street_name LIKE :queryString') AND ('PhoneNumber.n_number LIKE :queryString'))
and I need it to be like this
(('Address.s_street_name LIKE :queryString') OR ('PhoneNumber.n_number LIKE :queryString')).
Any ideas ?
Keep in mind that the names of the relations and tables are not the actual names. The models and relations where created using Gii
Hmm.. this is how I would try it.
<?php
$criteria=new CDbCriteria;
$criteria->with = array('clientPhoneNumbers', 'clientAddresses');
$criteria->together = true;
$criteria->addCondition(array('Address.s_street_name LIKE :queryString', 'PhoneNumber.n_number LIKE :queryString'), 'OR');
$criteria->params = array(':queryString' => $queryString);
$criteria->limit = $limit;
$criteria->order = $order;
$result = Client::model()->findAll($criteria);
?>
Also, I think this describes a case similar to yours. Note that he/she is updating the condition parameter explicitly, but IMO doing it with the addCondition method is more readable.
use criteria with join statement.
public function test()
{
$criteria=new CDbCriteria;
$criteria->alias = 'i';
$criteria->compare('id',$this->id);
.........
.........
$criteria->join= 'JOIN phoneNUmbers d ON (i.id=d.id)';
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'clients ASC',
),
));
}
Alternately use DAO to prepare and execute your own query and return data in the format you wish.
Or you can use CSQLDataProvier. the last 2 options give you more control over the SQL statement

SELECT MAX query returns only 1 variable + codeigniter

I use codeigniter and have an issue about SELECT MAX ... I couldnot find any solution at google search...
it looks like it returns only id :/ it's giving error for other columns of table :/
Appreciate helps, thanks!
Model:
function get_default()
{
$this->db->select_max('id');
$query = $this->db->getwhere('gallery', array('cat' => "1"));
if($query->num_rows() > 0) {
return $query->row_array(); //return the row as an associative array
}
}
Controller:
$default_img = $this->blabla_model->get_default();
$data['default_id'] = $default_img['id']; // it returns this
$data['default_name'] = $default_img['gname']; // it gives error for gname although it is at table
To achieve your goal, your desire SQL can look something like:
SELECT *
FROM gallery
WHERE cat = '1'
ORDER BY id
LIMIT 1
And to utilise CodeIgniter database class:
$this->db->select('*');
$this->db->where('cat', '1');
$this->db->order_by('id', 'DESC');
$this->db->limit(1);
$query = $this->db->get('gallery');
That is correct: select_max returns only the value, and no other column. From the specs:
$this->db->select_max('age');
$query = $this->db->get('members');
// Produces: SELECT MAX(age) as age FROM members
You may want to read the value first, and run another query.
For an id, you can also use $id = $this->db->insert_id();
See also: http://www.hostfree.com/user_guide/database/active_record.html#select
CodeIgniter will select * if nothing else is selected. By setting select_max() you are populating the select property and therefore saying you ONLY want that value.
To solve this, just combine select_max() and select():
$this->db->select('somefield, another_field');
$this->db->select_max('age');
or even:
$this->db->select('sometable.*', FALSE);
$this->db->select_max('age');
Should do the trick.
It should be noted that you may of course also utilize your own "custom" sql statements in CodeIgniter, you're not limited to the active record sql functions you've outlined thus far. Another active record function that CodeIgniter provides is $this->db->query(); Which allows you to submit your own SQL queries (including variables) like so:
function foo_bar()
{
$cat = 1;
$limit = 1;
$sql = "
SELECT *
FROM gallery
WHERE cat = $cat
ORDER BY id
LIMIT $limit
";
$data['query'] = $this->db->query($sql);
return $data['query'];
}
Recently I have been utilizing this quite a bit as I've been doing some queries that are difficult (if not annoying or impossible) to pull off with CI's explicit active record functions.
I realize you may know this already, just thought it would help to include for posterity.
2 helpful links are:
http://codeigniter.com/user_guide/database/results.html
http://codeigniter.com/user_guide/database/examples.html