I'm in a situation where I need to be able to run a direct mongodb query from inside of PHP, and am having troubles with the execute() function.
The following code will correctly execute and return a result from the database:
$m = new MongoClient();
$db = $m-><dbName>;
print_r($db->execute('db.<collection>.count()'));
However, if I replace count() with find() I get the following result:
Array
(
[retval] => Array
(
[value] => DBQuery: <dbName>.<collection>-> undefined
)
[ok] => 1
)
Why does one of these queries work, and the other fail? And how can I overcome this issue? I've thought about writing something that will convert a MongoDB query into the necessary array format for the PHP Mongo library to work with, but that would be a lot of work that I don't want to go through.
This is the same problem that was brought up here: How to access MongoDB profile in PHP? - but no answers were given at that time.
This question: PHP MongoDB execute() locking collection utilizes the execute() method with find() and they say it works for them, but I'm not sure how.
Update:
So I'd updated mongo in pecl, but that didn't solve anything. However, I also did a YUM update, and that provided a separate package update for php-pecl-mongo-1.2.12-1.el6.x86_64 that brought me to 1.3.4-1.
Now, $db->execute('db.<collection>.find()) returns something...but not at all what I expect. Instead of returning a MongoCursor object instead an Array is returned, and while it has a retval field, there's no actual information in there from the query performed. It looks like this:
Array
(
[retval] => Array
(
[_mongo] => Array
(
[slaveOk] =>
[host] => EMBEDDED
)
[_db] => Array
(
[_mongo] => Array
(
[slaveOk] =>
[host] => EMBEDDED
)
[_name] => test
)
[_collection] => Array
(
[_mongo] => Array
(
[slaveOk] =>
[host] => EMBEDDED
)
[_db] => Array
(
[_mongo] => Array
(
[slaveOk] =>
[host] => EMBEDDED
)
[_name] => test
)
[_shortName] => hits
[_fullName] => test.hits
)
[_ns] => test.hits
[_query] => Array
(
)
[_fields] =>
[_limit] => 0
[_skip] => 0
[_batchSize] => 0
[_options] => 0
[_cursor] =>
[_numReturned] => 0
[_special] =>
)
[ok] => 1
)
As you can see, there's not actually anything from the database there: how do I get to my actual rows?
$m = new MongoClient();
$db = $m-><dbName>;
print_r($db->execute('db.<collection>.toArray()'));
Suppose your databse name is test and collection name is foo .
print_r($m->test->execute('return db.foo.find().toArray()'));
I had the same problem, this is my solution using execute:
$m = new MongoClient();
$db = $m-><dbName>;
print_r($db->execute('return { count : db.<collection>.count() }'));
My result:
Array
(
[retval] => Array
(
[count] => 10
)
[ok] => 1
)
Related
I am trying to execute queries on statements stored in Learning Locker via PHP and TinCanPHP API. Going by this answer, I was able to fetch a response from Learning Locker. Here is a part of the response:
TinCan\LRSResponse Object
(
[success] => 1
[content] => TinCan\StatementsResult Object
(
[statements:protected] => Array
(
[0] => TinCan\Statement Object
(
[id:protected] => 9ea9e6b6-8278-4545-a02c-c46113f3ba30
[stored:protected] => 2016-02-28T12:04:01.670600+00:00
[authority:protected] => TinCan\Agent Object
(
[objectType:protected] => Agent
[name:protected] => New Client
[mbox:protected] => mailto:hello#learninglocker.net
[mbox_sha1sum:protected] =>
[openid:protected] =>
[account:protected] =>
)
[version:protected] => 1.0.0
[attachments:protected] => Array
(
)
[actor:protected] => TinCan\Agent Object
(
[objectType:protected] => Agent
[name:protected] => Subhayan Roy
[mbox:protected] => mailto:subhayanroy5#gmail.com
[mbox_sha1sum:protected] =>
[openid:protected] =>
[account:protected] =>
)
[verb:protected] => TinCan\Verb Object
(
[id:protected] => http://activitystrea.ms/schema/1.0/search
[display:protected] => TinCan\LanguageMap Object
(
[_map:protected] => Array
(
[en-US] => Searched
)
)
)
The list of statements returned has permission protected, so I'm not being able to access them. How do I access the statements? What am I missing here?
You need to use the methods built into the library. In this case the one you want is getStatements.
$statementResult->content->getStatements();
See the documentation here: http://rusticisoftware.github.io/TinCanPHP/doc/api/latest/classes/TinCan.StatementsResult.html#method_getStatements
To answer the question which you will ask next (Why aren't I getting all statements returned in the result?), Take a look at the Statement Result getMore method which gives you the more URL and the Remote LRS moreStatements method which accepts a more URL and fetches the next batch of statements. See this code sample: https://github.com/garemoko/TinBadgesPHP/blob/b8789042f4af23f0f7927596e8e7f2a06655db72/TinBadges/RemoteLRS.php#L84-L96
I have the following array in my Moodle plugin:
Array (
[0] => stdClass Object (
[id] => 32
[sessionid] => 5
[sessiontimezone] => CET
[timestart] => 1464071400
[timefinish] => 1464102000 )
[1] => stdClass Object (
[id] => 33
[sessionid] => 5
[sessiontimezone] => CET
[timestart] => 1465281000
[timefinish] => 1465311600 )
)
How to get the data. Right now, when I make:
$pluginsessiondates = $DB->get_record('plugin_sessions', array('id'=>$sessionid));
I get only data from the frist array [0]
How to get the data from every array key and then the single values? Thanks in advance.
The Moodle DB functions are for getting data out of the database, rather than from an array somewhere inside your plugin.
If you have an array somewhere, then you can get fields from it by writing:
echo $myarray[0]->id;
echo $myarray[1]->id;
etc.
If you are not trying to get data out of an existing array and want, instead, to get it out of the database, then $DB->get_record() will, as its name implies, get you only a single record, whereas $DB->get_records() will get you all the matching records:
$sessions = $DB->get_records('plugin_sessions', array('sessionid' => $sessionid));
foreach ($sessions as $session) {
echo $session->id;
}
My data like this:
Array
(
[_id] => MongoId Object
(
[$id] => 51a6fca3f348aca011000000
)
[first_name] => Phan
[last_name] => Chuong
[interests] => Array
(
[0] => football
[1] => swimming
[2] => PHP
[3] => music
)
)
I want edit value PHP to PHP1 or set PHP to null. Please help me how can i do it? Thanks all!
You could use the MongoCollection::update() method like this:
// $c is your MongoCollection Object
$updatedata = array('$set' => array("interests.2" => "PHP1"));
$id = new MongoID('51a6fca3f348aca011000000')
$c->update(array("_id" => $id), $updatedata);
The update method needs two arrays, the first one will tell the DB which Object to update ( In this example where id = our id, always use the MongoID Object, always!), the second array defines what to update, note that you can get to values in nested arrays wit the dot like above. $set is an Field Update Operator, read more on them here:
http://docs.mongodb.org/manual/reference/operator/update-field/
Or you could just get the entire Array, change it, and save it back.
$cursor = $c findOne("_id",4cb30f560107ae9813000000);
$cursor['interests'][2] = 'whatever';
$c->update($cursor);
I've come across a weird scenario I do not know how to code around. I'm creating a JSON API for a wordpress site. I'm using the Connections plugin and trying to pull out the "original" image filename. The output of my sql command is this:
{
["options"]=>
string(396) "a:4:{s:5:"entry";a:1:{s:4:"type";s:12:"organization";}s:5:"group";a:1:{s:6:"family";a:0:{}}s:4:"logo";a:2:{s:6:"linked";b:0;s:7:"display";b:0;}s:5:"image";a:3:{s:6:"linked";b:1;s:7:"display";b:1;s:4:"name";a:4:{s:9:"thumbnail";s:25:"invoicelogo_thumbnail.jpg";s:5:"entry";s:21:"invoicelogo_entry.jpg";s:7:"profile";s:23:"invoicelogo_profile.jpg";s:8:"original";s:24:"invoicelogo_original.jpg";}}}"
}
}
I'm using the following command to acquire that:
querystr = "SELECT options FROM {$wpdb->prefix}connections WHERE id= '{$_GET['companyID']}'";
$options = $wpdb->get_results($querystr);
I'm not sure how to pull out the "original" part of this code though as it's not all that organized. Any help would be appreciated.
What you are seeing is the results of a php serialize call
To get at the original name just do this.
$decodedOptions = unserialize($options);
$original = $decodedOptions["image"]["name"]["original"];
Hope that helps
As a side note the deserialized data looks like
Array
(
[entry] => Array
(
[type] => organization
)
[group] => Array
(
[family] => Array
(
)
)
[logo] => Array
(
[linked] =>
[display] =>
)
[image] => Array
(
[linked] => 1
[display] => 1
[name] => Array
(
[thumbnail] => invoicelogo_thumbnail.jpg
[entry] => invoicelogo_entry.jpg
[profile] => invoicelogo_profile.jpg
[original] => invoicelogo_original.jpg
)
)
)
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(...)))