I have a symfony problem: The functionally works good, but this does not work the way I want.
$res = array("4","2","1","3"); // LIST ID (a.id)
$paginas = new sfDoctrinePager('TbArticle', 2);
$paginas->setQuery(Doctrine::getTable('TbArticle')->createQuery('a')->where('a.ifactive = 1')->andWhere('a.dirimage=1')->andWhere('a.stock<>0')->whereIn("a.id", $res));
$paginas->setPage($page);
$paginas->init();
It works okay, but when I call getResults(), the array order is incorrect. For instance, this sort returns: 1,2,3,4. And I like to get: 4, 2, 1, 3 ($res)
Can you help me?
Unfortubately this cannot be done with the query.
The MySQL queries can be returned ordered using the ORDER BY clause in ascending or descending order. Elements in your array use none. When you pass the array as a parameter for the WHERE IN clause MySQL doesn't care about the order of the elements as you can see.
Fortunately there is a solution :)
First you will have to use Doctrine's ability to create a table of results indexed with what you want. Use this:
Doctrine::getTable('TbArticle')->createQuery('a INDEX BY id')->...;
This will return an array of results where the array keys are the id's of the rows. Then you can rearange the results array to match your $res (assuming that $rows has the rows returned by Doctrine):
foreach ($res as $i) {
$new_array[] = $rows[$i];
}
The tricky part is to make it work with the paginator. But I'm sure you can do that as well (try to retrieve the results from the paginator and rearange them before displaying).
Related
I have this following Yii 2 query
$find = People::find()->where(['c_id' => $c_id])->orderBy('totals DESC, id DESC')->all();
So imagine this query was an array. Everything found by this query has an "id" attribute.
Since it's sorted by "totals", I essentially want to return the position in the array where I can find this specific id.
Currently, I'm using this code.
foreach ($find as $t) {
$arr[] = $t->id;
if ($t->id == $id) {
break;
}
}
$key = count($arr);
return $key;
However, this code is vany wayow on a 100k+ result query.
Is there anyway to speed this up?
You could get the result as an array (instead of object) as
$find = People::find()->where(['c_id' => $c_id])
->orderBy('totals DESC, id DESC')
->asArray()
->all();
then you could find your value using array_search()
$my_index = array_search($id,$find);
but for 100k+ you should find using a direct select in db...instead tha looping on php or load all in php and scan with array_search()
To get array from query in YII, you can use queryAll();
$find = People::find()->where(['c_id' => $c_id])->orderBy('totals DESC, id DESC')->queryAll();
OR, another way to convert the object into an array is:
$find = json_decode(json_encode($find), true); // to convert all data into array.
And once you get results in array, you can implement the actual code for your requirement as given below.
You can use array_search() function to get index of your value.
$a=array("a"=>"red","b"=>"green","c"=>"blue");
echo array_search("red",$a);
The array_search() function search an array for a value and returns the key.
Maybe I didn't understand you correctly but I assume that you are trying to detect the index or key for your desired id inside an array returned from an SQL query that is sorted by some other column like total.
So let us fetch records from the database with your query with a little change asArray() like this
$find = People::find()
->where(['c_id' => $c_id])
->orderBy('totals DESC, id DESC')
->asArray()
->all();
in the result, let us assume the People table returns you an array with the following dataset ordered by columns total and id DESC.
[
0 => [
'id' => 2 ,
'c_id'=>2,
'name' => 'John' ,
'age'=>18,
'totals'=>100,
],
1=>[
'id'=>1,
'c_id'=>55,
'name'=>'Bob',
'age'=>20,
'totals'=>80,
],
2=>[
'id'=>3,
'c_id'=>85,
'name'=>'Peter',
'age'=>15,
'totals'=>75,
]
];
Now if you look into \yii\helpers\ArrayHelper you will find ArrayHelper::getColumn().
Let us use this on the array we received from the query, I assume that you are searching $id inside the column id so we will first filter out the id column like below.
$idsArray = ArrayHelper::getColumn($find, 'id');
this will give us the ids in the following sequence which is in the same order as the initial result set.
[2,1,3]
then lets use the built-in php function array_search()
$key=array_search($yourId,$idsArray);
Hope this is what you are looking for.
This question already has answers here:
Preserve key order (stable sort) when sorting with PHP's uasort
(6 answers)
Closed 5 months ago.
I'm using usort to sort an array of objects, but really I want this to act as a kind of "group by" function without disturbing the original relative order of the rows.
Say I have this:
MASTER_CODE, CONFIG_ITEM
foo1, opt_ray
foo2, opt_ray
foo1, opt_fah
foo2, opt_doe
From that data, an array of objects is constructed with an anonymous key. That is, each row is parsed as an object. The objects are collected into an array.
What I want to do is sort the array by the MASTER_CODE value, but without disturbing the order.
That is, the final order should be:
MASTER_CODE, CONFIG_ITEM
foo1, opt_ray
foo1, opt_fah
foo2, opt_ray
foo2, opt_doe
We don't add a sort order, because the data comes from an external source.
I can use usort to order by the master code, but it messes up the original relative order.
Any suggestions?
This is one option - it's not the most elegant solution. It will take the unique values from the first column of your array (the one you want to filter by), sort that, then loop it and add entries from your original array with the same first value.
// Get an unique array of values to use for sorting
$sorting = array_unique(array_column($a, 0));
sort($sorting);
$sorted = [];
foreach ($sorting as $sortValue) {
$sorted = array_merge(
$sorted,
array_filter(
$a,
function($row) use ($sortValue) {
// Find values that have the same first value as each sort value
return ($sortValue === $row[0]);
}
)
);
}
Example
Note: This will work on PHP 5.5. Since you also tagged PHP 5.3, you may need to replace the array_column function. Try something like this:
$sorting = array_unique(array_map(function($row) { return $row[0]; }, $a));
Suppose you have an array of keys
$key_list = array(3, 6, 2);
And you want to retrieve records from a certain table, using these keys as identifiers (WHERE ID = id_from_key_list)
Foo::get()->byIDs($key_list);
This returns the rows with the ID's that match those in $key_list (3, 6 and 2) but not in that order.
How do we maintain the same order when retrieving these items?
What you might need to do is to run a foreah loop of the IDs and push each Foo Object into an ArrayList
$aFooList = ArrayList::create();
foreach ($key_list as $key_list_id){
$oFoo = Foo::get()->byID($key_list_id);
$aFooList->push($oFoo);
}
return $aFooList;
On my models I try to write a php model that will get me a associative array from a database. But I don't quite know how to approach this.
So after I execute this SQL query:
SELECT balance_events.weight,balance_events.added_date,
balance_entries.mid FROM balance_events, balance_entries
WHERE balance_entries.added_date BETWEEN '2016-08-02' AND '2016-08-03'
AND balance_entries.ptid =12
AND balance_entries.beid = balance_events.id
I will get this table:
And from that table I want to extract a asociative array that it will look like this:
count = ['13'=>1, '6'=>4, '16'=>3, '4'=>3]
where 'mid'=>number of how many times that mid can be found in the table.
ex. mid '13'=>1 cause you can found it only once.
I think that I will have to use SQL COUNT function, but how I can aggregate all of this in a PHP model in codeigniter? I know how to configure controller and view, but I don't know how to actually do the actual php model that will get me the desired array.
Try this query may help you ,
$result = $this->db->select('balance_events.weight,balance_events.added_date,COUNT(balance_entries.mid) as mid_count')
->from('balance_events, balance_entries')
->where('balance_entries.added_date BETWEEN "2016-08-02" AND "2016-08-03" ')
->where('balance_entries.ptid','12')
->where('balance_entries.beid','balance_events.id')
->group_by('balance_entries.mid')
->get();
return $result->result_array();
I'm not sure how you would create this in SQL but since you tagged php, I wrote a function that would do just this.
<?php
$query = array(array("mid"=>13), array("mid"=>2), array("mid"=>13), array("mid" =>6), array("mid" => 13), array("mid" => 6));
function createMidArray($queryResult){
$returnArray = array();
foreach ($queryResult as $qr){
$returnArray[$qr['mid']]++;
}
return $returnArray;
}
print_r(createMidArray($query));
?>
The output of this was Array ( [13] => 3 [2] => 1 [6] => 2 ) which matches up to my inputted $query (which is a 2D array). I'm expecting the output of your query is stored in a similar array, but with more data and keys
Assume the following association among three tables in a database:
//working with three tables a client 'has one' business
//and a business has many business hours.
The following would give us an array of Activerecord objects:
$this->client->business->businesshours
and we would have to pull an object form the array to get its column value:
$this->client->business->businesshours[0]->start_time
Since I am new to PHP Activerecord, what are some ways of proceeding to pull/sort/use information from an array of objects other than looping with a foreach() loop? Are there methods to sort through the array of objects, pull information based on a column value, any best practices?
There is not a library-specific practice for sorting or pulling certain businesshour objects out of the result array. If you want to manipulate the returned array of objects you need to use standard PHP array functions like array_map on the result array.
If you know the sort order or the conditions you want for the returned objects in the result array you should instead specify these in your association declaration so you don't return objects that you don't want or need.
Since you haven't posted any code you'll just have to extrapolate to your own situation from this example:
static $has_many = array(
array(
'businesshours',
'conditions' => array('hour BETWEEN ? AND ?' => array(9, 17)),
'order' => 'hour ASC'
)
);
This association declaration will return only the businesshour objects between 9 and 17 and do it in ascending order. So as you can see, if you constrain your associations to only the records you need, there will be no need to sort or parse the result array once received.
Sometimes it's useful to use array_map to get only certain objects from your result array:
// get $result array
$new = array_map(function($obj) { if ($obj->hour > 9){ return $obj; } }, $result);