Codeigniter Query Doesnot Give Proper Answer - php

I have a web project that is under development. I want to select data from database by group having a condition. But the problem is CodeIgniter doesn't give me the actually expected result. For reference, I am sharing code below.
First query
$this->db->select('serial, wardno, COUNT(serial) as total');
$this->db->where('status','active');
$this->db->group_by('wardno');
$data['wards'] = $this->db->get('certi_charter_inherit')->result_object();
First query give doesnot give me the targated result. It generates result.
[wards] => Array
(
[0] => stdClass Object
(
[serial] => 6
[wardno] => 2
[total] => 2
)
)
This is not my expectation. But If I use another direct query then it works clearly.
Second Query
$data['wards'] = $this->db->query("SELECT serial, wardno, COUNT(serial) as 'total' from certi_trade WHERE status='active' GROUP by wardno")->result_object();
[wards] => Array
(
[0] => stdClass Object
(
[serial] => 3
[wardno] => 1
[total] => 2
)
[1] => stdClass Object
(
[serial] => 6
[wardno] => 2
[total] => 1
)
)
The second query generates the result like below. And it is correct. I have tested my phpmyadmin console. So I confused which one should be used. I like the first one.
Any help is highly appriciated.

Please change your table name here as per your second query :
$data['wards'] = $this->db->get('certi_trade')->result_object();

Related

PHP search/filter array with given conditions, recursively

I am getting data from an api (that I cannot query agains, just get lump of data), and then I need to query against those data like I would do using database. Only It would be great if I could do it recursively.
Data example
[0] => Array
(
[id] => 1
[url] => https://domain.com/api/1.0/item/1/
[name] => some_item
[category] => some category
[created_by] => Array
(
[id] => 1
[screen_name] => tomino
)
[current_user_domain_access] => Array
(
[is_active] => 1
[is_administrator] => 1
)
[alerts_enabled] => 0
)
(much shortened version)
I receive an array of objects like that and then I need to select/filter/search by values.
Something like this
SomeModel::find(['category'=>'some category','current_user_domain_access' => ['is_administrator' => 1]]);
Is that something that would be possible in PHP? I was thinking about flattening the array, but then there might be key conflicts
1) select data : You can select data by (array_name->id),(array_name->url) and so on...
2)Filter : add conditions according to requirement
3)search : in_array(),array_search

PHP Find value in object

I have a result of an SQL query that looks like this
Array
(
[0] => stdClass Object
(
[field_number] => 1
[value] => Joe
)
[1] => stdClass Object
(
[field_number] => 2
[value] => Bloggs
)
[2] => stdClass Object
(
[field_number] => 3
[value] => 12566
)
[3] => stdClass Object
(
[field_number] => 4
[value] => 2000-07-24
)
)
It wont always return all the fields as some are not required therefore not saved to the database.
I know that first name is stored with field number 1. How can I look this up in the object.
EG
$first_name = $result => field_number == 1
I know thats not right, but Im sure there must be a simple way to get this info?
Thanks
If the values in the array are not in order (eg array[0] does not always contain field_number 1) then you will need to iterate the array:
foreach($array as $item){
if($item->field_number==1){
$first_name = $item->value;
break;
}
}
However, if this is the result of an SQL query, probably you need to rewrite the query to give you data in a more useable form

PDO fetchAll() primary key as array group key

I want to store the contents of a specific database into an array, grouped by their primary keys. (Instead of the useless way PDO fetchAll() organises them).
My current code:
$DownloadsPDO = $database->dbh->prepare("SELECT * FROM `downloads`");
$DownloadsArray = $DownloadsPDO->execute();
$DownloadsArray = $DownloadsPDO->fetchAll();
Which then outputs:
Array ( [0] => Array ( [id] => 0 [0] => 0 [path] => /xx-xx/testfile.zip [1] => /xx-xx/testfile.zip [name] => Test Script [2] => Test Script [status] => 1 [3] => 1 ) [1] => Array ( [id] => 1 [0] => 1 [path] => /xx-xx/test--file.zip [1] => /xxxx/testfile.zip [name] => New Script-UPDATE [2] => New Script-UPDATE [status] => 1 [3] => 1 ) )
I was considering to use PDO::FETCH_PAIR, however I will be very soon expanding the amount of data I want to be able to use on this script. This works currently, but when I start to expand the amount of downloads and more clients come into play, obviously the way the data is grouped causes an issue.
Is it possible for me to group each array by their primary key (which is id)?
You can just use
$results = array_map('reset', $stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC))
PDO::FETCH_GROUP|PDO::FETCH_ASSOC returns an array of arrays. The first column is used as the key, and then within key is an array of all the results for that key. However, in our scenario each key will only contain 1 row. reset() returns the first element in array, thus eliminating 1 level of nesting.
This should yield what you are looking for :
$results = $pdos->fetchAll(\PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC);
I decided to just loop through the results with fetch() and enter them into an array as I go along, this is the code I have used and it works just fine:
$DownloadsPDO = $database->dbh->query("SELECT * FROM `downloads`");
$Array = array();
while ($d = $DownloadsPDO->fetch()) {
$Array[$d['id']]["id"] = $d['id'];
$Array[$d['id']]["name"] = $d['name'];
$Array[$d['id']]["path"] = $d['path'];
}
// Outputs
Array ( [1] => Array ( [id] => 1 [name] => Test Script [path] => /xxxx/testfile.zip ) [2] => Array ( [id] => 2 [name] => New Script-UPDATE [path] => /xxxx/testfile.zip ) )
Which uses the primary key (being id) as the name for the array key, and then adds the data into it.
Thought I would add this as the answer as this solved it, thanks to the guys that helped out and I hope this is helpful to anyone else hoping to achieve the same thing.
I'd like to point out the only solution that works for me:
fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_UNIQUE|\PDO::FETCH_ASSOC);
Beware that this will strip the first column from the resultset. So the query must be:
SELECT id_keyname AS arrkey, id_keyname, .... FROM ...
I'm still suggesting you to loop using fetch() method. Otherwise, you can use array_reduce() to iterate over the array. A sample on codepad is here.
The code(in human readable form) will be:
$myFinalArray = array_reduce($myInputArray, function($returnArray, $temp) {
$temp2 = $temp['id'];
unset($temp['id']);
$returnArray[$temp2] = $temp;
return $returnArray;
}
);
So, my question is; is it possible for me to group each array by their
primary key (which is id)
Off course, you have 2 options here: Either to change the query or parse a result-set.
So, I'm sure you don't want to change query itself, so I'd go with parsing result-set.
Note:
You should use prepared SQL statements when they make sense. If you want to bind some parameters then its OKAY. But in this case, you only want get get result-set, so prepare() and fetch() will be kinda overdo.
So, you have:
Array ( [0] => Array ( [id] => 0 [0] => 0 [path] => /xx-xx/testfile.zip [1] => /xx-xx/testfile.zip [name] => Test Script [2] => Test Script [status] => 1 [3] => 1 ) [1] => Array ( [id] => 1 [0] => 1 [path] => /xx-xx/test--file.zip [1] => /xxxx/testfile.zip [name] => New Script-UPDATE [2] => New Script-UPDATE [status] => 1 [3] => 1 ) )
And you want:
Array( [id] => Array('bar' => 'foo') ....)
Well, you can do something like this:
$stmt = $database->dbh->query("SELECT * FROM `downloads`");
$result = array();
foreach($stmt as $array){
$result[$array['id']] = $array;
}
print_r($result); // Outputs: Array(Array('id' => Array(...)))

trying to get a multi table sql query into one result array

I have four tables: followers, users, mixes, songs I am trying to get all the mixes from all the followers of one user, I have that part figured out, but I also want to get the songs from each of those mixes, currently my query is giving me results but each result is for one song on the mix, rather than an array of songs within each result for one mix ... any help would be amazing, my sql skills aren't the greatest and I have spent a lot of time trying to figure this out!
my current query is:
SELECT followers.following_id, users.id, users.user_username, mixes.id, mixes.mix_created_date, mixes.mix_name,songs.song_artist
FROM followers, users, mixes,songs
WHERE followers.user_id = 46
AND users.id = followers.following_id
AND mixes.user_id = followers.following_id
AND mixes.id > 0
ORDER BY mixes.mix_created_date DESC
LIMIT 10
the current result is (from running this through a cakephp custom query)
Array
(
[0] => Array
(
[followers] => Array
(
[following_id] => 47
)
[users] => Array
(
[id] => 47
[user_username] => someguy
)
[mixes] => Array
(
[id] => 45
[mix_created_date] => 2012-07-21 2:42:17
[mix_name] => this is a test
)
[songs] => Array
(
[song_artist] => Yo La Tengo
)
)
[1] => Array
(
[followers] => Array
(
[following_id] => 47
)
[users] => Array
(
[id] => 47
[user_username] => someguy
)
[mixes] => Array
(
[id] => 45
[mix_created_date] => 2012-07-21 2:42:17
[mix_name] => this is a test
)
[songs] => Array
(
[song_artist] => Animal Collective
)
)
as you can see the mix id's are the same, I am trying to get the songs to be an array inside of each result like :
Array
(
[0] => Array
(
[followers] => Array
(
[following_id] => 47
)
[users] => Array
(
[id] => 47
[user_username] => someguy
)
[mixes] => Array
(
[id] => 45
[mix_created_date] => 2012-07-21 2:42:17
[mix_name] => this is a test
)
[songs] => Array
(
[0]=>array(
['song_artist'] => Yo La Tengo
),
[1]=>array(
['song_artist'] => Animal Collective
)
)
)
Really hoping this can be done with just one sql statement! thanks in advance!
You can use the SQL join command to make multiple queries together..
Use this...
sql_join
first a note: it looks like you have a missing condition. according to the above query, every song in songs table will be joined with every result possible. probably there should be a condition similar to the following added: (column names can be different based on your tables):
...
and mix.song_id=songs.song_id
...
as for your question: I don't know php so i regard mysql alone: I don't think it is possible to do it with mysql. mysql returns rows in the result set and each row can contain a single value in each column. to add a group of values (song names) in one column, they must be concatenated (and that is possible: Can I concatenate multiple MySQL rows into one field?), and later you split them back in your php script. this is not a good idea as you will need to choose a separator that you know will never appear in the values that are concatenated. therefore I think its better to remove the songs table from the query and after getting the mix id, run a second query to get all songs in that mix.

cakephp - sorting by a second level association in paginate

I am playing around with a quotes database relating to a ski trip I run. I am trying to list the quotes, but sort by the person who said the quote, and am struggling to get the paginate helper to let me do this.
I have four relevant tables.
quotes, trips, people and attendances. Attendances is essentially a join table for people and trips.
Relationships are as follows;
Attendance belongsTo Person hasMany Attendance
Attendance belongsTo Trip hasMany Attendance
Attendance hasMany Quote belongs to Attendance
In the QuotesController I use containable to retrieve the fields from Quote, along with the associated Attendance, and the fields from the Trip and Person associated with that Attendance.
function index() {
$this->Quote->recursive = 0;
$this->paginate['Quote'] = array(
'contain' => array('Attendance.Person', 'Attendance.Trip'));
$this->set('quotes', $this->paginate());
}
This seems to work fine, and in the view, I can echo out
foreach ($quotes as $quote) {
echo $quote['Attendance']['Person']['first_name'];
}
without any problem.
What I cannot get to work is accessing/using the same variable as a sort field in paginate
echo $this->Paginator->sort('Name', 'Attendance.Person.first_name');
or
echo $this->Paginator->sort('Location', 'Attendance.Trip.location');
Does not work. It appears to sort by something, but I'm not sure what.
The $quotes array I am passing looks like this;
Array
(
[0] => Array
(
[Quote] => Array
(
[id] => 1
[attendance_id] => 15
[quote_text] => Hello
)
[Attendance] => Array
(
[id] => 15
[person_id] => 2
[trip_id] => 7
[Person] => Array
(
[id] => 2
[first_name] => John
[last_name] => Smith
)
[Trip] => Array
(
[id] => 7
[location] => La Plagne
[year] => 2000
[modified] =>
)
)
)
I would be immensely grateful if someone could suggest how I might be able to sort by the the first_name of the Person associated with the Quote. I suspect my syntax is wrong, but I have not been able to find the answer. Is it not possible to sort by a second level association in this way?
I am pretty much brand new with cakephp so please be gentle.
Thanks very much in advance.
I've had the similar problem awhile back. Not with sort though. Try putting the associated table in another array.
echo $this->Paginator->sort('Name', 'Attendance.Person.first_name');
change to:
echo $this->Paginator->sort('Name', array('Attendance' => 'Person.first_name'));
Hope this helps
i'm also looking for help with this.
so far i've found that you can sort multi level associations in controller's pagination options after using the linkable plugin https://github.com/Terr/linkable.
but it breaks down when you try to sort form the paginator in the view. i'm using a controller for magazine clippings. each clipping belongs to an issue and each issue belongs to a publication.
$this->paginate = array(
"recursive"=>0,
"link"=>array("Issue"=>array("Publication")),
"order"=>array("Publication.name"=>"ASC",
"limit"=>10);
after debugging $this->Paginator->params->paging->Clipping in the view, you can see that the sort is described in two separate places, "defaults" and "options". the sort info needs to be present in both for it to work in the view.
here is after setting order in controller:
[Clipping] => Array
(
[page] => 1
[current] => 10
[count] => 6685
[prevPage] =>
[nextPage] => 1
[pageCount] => 669
[defaults] => Array
(
[limit] => 10
[step] => 1
[recursive] => 0
[link] => Array
(
[Issue] => Array
(
[0] => Publication
)
)
[order] => Array
(
[Publication.name] => ASC
)
[conditions] => Array
(
)
)
[options] => Array
(
[page] => 1
[limit] => 10
[recursive] => 0
[link] => Array
(
[Issue] => Array
(
[0] => Publication
)
)
[order] => Array
(
[Publication.name] => ASC
)
[conditions] => Array
(
)
)
)
and here is after using $this->Paginator->sort("Publication","Publication.name");.
notice the options array is empty.
[Clipping] => Array
(
[page] => 1
[current] => 10
[count] => 6685
[prevPage] =>
[nextPage] => 1
[pageCount] => 669
[defaults] => Array
(
[limit] => 10
[step] => 1
[recursive] => 0
[link] => Array
(
[Issue] => Array
(
[0] => Publication
)
)
[order] => Array
(
[Publication.name] => DESC
)
[conditions] => Array
(
)
)
[options] => Array
(
[page] => 1
[limit] => 10
[recursive] => 0
[link] => Array
(
[Issue] => Array
(
[0] => Publication
)
)
[order] => Array
(
)
[conditions] => Array
(
)
)
does one really need to modify the paginator class to make this work?
UPDATE:
i found out the problem:
in the core cake controller paginator merges default and options to create the find query.
but the options array is empty when using linkable to sort. because options is listed after default it overrides default and the empty array replaces the default array of options.
solution to this is extending the paginate function inside of app_controller.php and unsetting the options array order value if it is empty:
(line 1172 in cake/libs/controller/controller.php)
if(empty($options["order"])){
unset($options["order"]);
}
then the options will not be overwritten by thte blank array.
of course this should not be changed inside of controller.php, but put it in app_controller.php and move it to your app folder.
On CakePHP 3 this problem can be solved by adding 'sortWhitelist' params to $this->paginate on your controller.
$this->paginate = [
// ...
'sortWhitelist' => ['id', 'status', 'Attendance.Person.first_name']
];
And then in your view:
echo $this->Paginator->sort('Name', 'Attendance.Person.first_name');
This is noted in the docs:
This option is required when you want to sort on any associated data, or computed fields that may be part of your pagination query:
However that could be easily missed by tired eyes, so hope this helps someone out there!

Categories