How to get collection class object from mongodb/driver/manager in PHP - php

I am using the (current? not sure, php documentation is very opaque to me) method to connect to a MongoDB from PHP:
$manager = new MongoDB\Driver\Manager("mongodb://{$user}:{$pwd}#{$url}", array("ssl" => true), array("context" => $ctx));
From there, if I want to write something I do the following:
$bson = MongoDB\BSON\fromJSON($newData);
$value = MongoDB\BSON\toPHP($bson);
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->update(
$filter,
['$set' => $value],
['multi' => false, 'upsert' => $upsert]
);
$results = $manager->executeBulkWrite("$DB.$collection", $bulk);
var_dump($results);
All the documentation on the MongoDB PHP tutorials starts with a $collection object... and the functions thereafter seem much more user-friendly (getInsertedID... insertOne...find...findOne...etc).
For example:
<?php
$collection = (new MongoDB\Client)->test->users;
$insertManyResult = $collection->insertMany([
[
'username' => 'admin',
'email' => 'admin#example.com',
'name' => 'Admin User',
],
[
'username' => 'test',
'email' => 'test#example.com',
'name' => 'Test User',
],
]);
printf("Inserted %d document(s)\n", $insertManyResult->getInsertedCount());
var_dump($insertManyResult->getInsertedIds());
It is not clear to me, how they are actually connecting to the DB... how would I go from the $manager connection to a $collection?
On the MongoDB PHP documentation page, it says 'You can construct collections directly using the driver’s MongoDB\Driver\Manager class'. Unfortunately, a search on the resulting page doesn't include the word 'collection' other than as a side comment in a user contributed note'
Elsewhere on the MongoDB PHP reference pages, I see nowhere that the MongoDB\Manager class is described.
So, how do I get access to the many features in the MongoDB\Collection class?

I was not able to get a collection out of the Manager class, however, I was able to use the bulkWrite class to execute an insert in a secure fashion (I believe). I expect the same pattern will work for reads and updates as well.
Code snippet for those that come here after me:
//echo "Specify the cert...";
$SSL_DIR = ".";
$SSL_FILE = "XXXXXX.pem";
$ctx = stream_context_create(array(
"ssl" => array(
"cafile" => $SSL_DIR . "/" . $SSL_FILE,
))
);
//echo "Done\n";
// echo "Creating manager...";
$manager = new MongoDB\Driver\Manager("mongodb://{$user}:{$pwd}#{$url}", array("ssl" => true), array("context" => $ctx));
// echo "Done!\n";
// echo "Making BSON...";
$bson = MongoDB\BSON\fromJSON($newData);
// echo "Done!\nMaking Value...";
$value = MongoDB\BSON\toPHP($bson);
$value->_id = (string) new MongoDB\BSON\ObjectID;
// echo "Done!\nMaking Bulk...";
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert($value);
// echo "Done!\nExecuting Bulk Write";
$results = $manager->executeBulkWrite("$db.$collection", $bulk);
if($results->getInsertedCount()==1) {
echo $value->_id;
} else {
echo $results->getWriteErrors();
}
// echo "Done!\n";

Related

MongoDB PHP Error: Warning: Undefined property: MongoDB\Driver\Manager

I'm trying to use MongoDB on my local machine using the advice in this stack overflow. I'm using XAMPP on Windows 10, php version 8.01, and MongoDB extension 1.9.0.
It's a very basic script that connects to MongoDB and tries to use one of the databases.
But I am still getting this warning:
Connection to database successfully
Warning: Undefined property: MongoDB\Driver\Manager::$aws_inventories in C:\xampp\htdocs\mongo_connect.php on line 8
This is my code:
<?php
require 'C:\xampp\htdocs\vendor\autoload.php'; // include Composer's autoloader
$DB_CONNECTION_STRING="mongodb://localhost:27017";
// connect to mongodb
$m = new MongoDB\Driver\Manager( $DB_CONNECTION_STRING );
echo "Connection to database successfully";
// select a database
$db = $m->aws_inventories;
?>
How can I get rid of the warning and connect to the DB correctly?
First, you're trying to access a property which doesn't exists in MongoDB\Driver\Manager class object.
Second, $db = $m->aws_inventories; works with MongoDB\Client library.
Here are few example to get collections list or find all/specific document/s or insert/bulk insert, update a document or to perform a distinct query
Get all collections of aws_inventories:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$command = new MongoDB\Driver\Command(["listCollections" => 1]);
$cursor = $manager->executeCommand("aws_inventories", $command);
// list of all collections in aws_inventories
$collections = $cursor->toArray();
var_dump($collections);
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
Get all documents from a collection:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
// setting options and filter
$filter = [];
$options = [];
/*
// or to find specific documents based on a condition and limit records
$filter = [
'service' => 'ec2',
'instance' => 'co',
'type' => 'c5',
'vCPU' => [
'$gt' => 2
]
];
$options = [
'limit' => 10,
'maxTimeMS' => 1000, // to limit the execution time of a query
'sort' => [
'vCPU' => -1
]
];
*/
// constructing the query
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $manager->executeQuery('aws_inventories.test', $query);
foreach ($cursor as $document) {
var_dump($document);
}
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
To perform distinct query:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$query = [
'size' => '2xlarge'
];
$command = new MongoDB\Driver\Command([
'distinct' => 'test', // Collection name
'key' => 'instance', // field for which we want to get distinct values
'query' => $query // criteria to filter documents
]);
$cursor = $manager->executeCommand("aws_inventories", $command);
// to get distinct values as array
$instances = current($cursor->toArray())->values;
var_dump($instances);
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
To insert single/multiple document/s:
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert([
'service' => 'ec2',
'instance' => 'co',
'type' => 'c5',
'size' => 'large',
'model' => 'c5.large',
'vCPU' => 2,
'memory' => 4,
'storage' => 'ebs-only',
'network_bandwidth' => 10,
'ebs_bandwidth' => 4750
]);
$bulk->insert([
'service' => 'ec2',
'instance' => 'gp',
'type' => 't3',
'size' => 'nano',
'model' => 't3.nano',
'vCPU' => 2,
'memory' => 0.5,
'storage' => 'ebs-only',
'network_bandwidth' => 5
]);
$result = $manager->executeBulkWrite('aws_inventories.test', $bulk);
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
To update existing document/s: (Taken from executeUpdate example)
try {
$manager = new MongoDB\Driver\Manager('mongodb://localhost:27017');
$criteria = [
'service' => 'ec2',
'type' => 'c5'
];
$document = [
'$set' => [
'features' => [
'Powered by the AWS Nitro System, a combination of dedicated hardware and lightweight hypervisor'
]
]
];
$updateOptions = array(
'multi' => true, // false - to update only first matching document, true - update all matching documents
'upsert' => 0
);
$writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 100);
$result = $manager->executeUpdate('aws_inventories.test', $criteria, $document, $updateOptions, $writeConcern);
printf("Updated %d document(s)\n", $result->getModifiedCount());
printf("Matched %d document(s)\n", $result->getMatchedCount());
printf("Upserted documents: %d\n", $result->getUpsertedCount());
foreach ($result->getUpsertedIds() as $index => $id) {
printf("upsertedId[%d]: ", $index);
var_dump($id);
}
/* If the WriteConcern could not be fulfilled */
if ($writeConcernError = $result->getWriteConcernError()) {
printf("%s (%d): %s\n", $error->getMessage(), $error->getCode(), var_export($error->getInfo(), true));
}
/* If the write could not happen at all */
foreach ($result->getWriteErrors() as $writeError) {
printf("%s (%d)\n", $error->getMessage(), $error->getCode());
}
} catch (\MongoDB\Driver\Exception\Exception $e) {
}
$m->aws_inventories That looks like as the older/deprecated approach. Could you try to follow this tutorial?
https://zetcode.com/db/mongodbphp/
<?php
try {
$mng = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$stats = new MongoDB\Driver\Command(["dbstats" => 1]);
$res = $mng->executeCommand("aws_inventories", $stats);
$stats = current($res->toArray());
print_r($stats);
} catch (MongoDB\Driver\Exception\Exception $e) {
$filename = basename(__FILE__);
echo "The $filename script has experienced an error.\n";
echo "It failed with the following exception:\n";
echo "Exception:", $e->getMessage(), "\n";
echo "In file:", $e->getFile(), "\n";
echo "On line:", $e->getLine(), "\n";
}
?>
This example is adapted from the official doc https://www.php.net/manual/en/mongodb-driver-manager.executequery.php
<?php
require 'vendor/autoload.php';
$manager = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$db = 'test_database';
$col = 'mycol';
$namespace = $db.'.'.$col;
// insert data
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert(['x' => 1]);
$bulk->insert(['x' => 2]);
$bulk->insert(['x' => 3]);
$manager->executeBulkWrite($namespace, $bulk);
// query
$query = new MongoDB\Driver\Query(['x' => ['$gt' => 1]], []);
$cursor = $manager->executeQuery($namespace, $query);
foreach ($cursor as $document) {
var_dump($document);
}
As the document suggests, MongoDB\Driver\Manager is a generic abstraction to manage any type of MongoDB connection (standalone server, replica set, or sharded cluster) so the methods will look a bit too complicated for simple CRUD on standalone server.
If you just want to connect to a standalone server, you may want to check MongoDB\Client. Here is the code that do exactly the same thing:
<?php
require 'vendor/autoload.php';
$client = new MongoDB\Client("mongodb://localhost:27017");
$col = $client->test_database->mycol;
// insert data
$col->insertMany([
['x' => 1],
['x' => 2],
['x' => 3],
]);
// query
$docs = $col->find(['x' => ['$gt' => 1]]);
foreach ($docs as $document) {
var_dump($document);
}

Facebook Ad API Error

I am getting error while creating Creative using the FB Ads PHP SDK
$parent_id as a parameter of constructor is being deprecated, please try not to use this in new code.
The code was working before the 2.9 and 2.10 update.
The Code I am using to create Creative is:
$link_data = new AdCreativeLinkData();
$link_data->setData(array(
AdCreativeLinkDataFields::MESSAGE => 'Product Description',
AdCreativeLinkDataFields::LINK => $url_of_website,
AdCreativeLinkDataFields::IMAGE_HASH => $image->hash,
AdCreativeLinkDataFields::DESCRIPTION => 'Link Description',
AdCreativeLinkDataFields::CALL_TO_ACTION => array(
'type' => AdCreativeCallToActionTypeValues::LEARN_MORE,
'value' => array(
'link_title' => 'View Similar Products Now!',
'lead_gen_form_id' => $form_id,
),
),
));
$story = new AdCreativeObjectStorySpec();
$story->setData(array(
AdCreativeObjectStorySpecFields::PAGE_ID => $page_id,
AdCreativeObjectStorySpecFields::LINK_DATA => $link_data,
));
$creative = new AdCreative(null, $account_id);
$creative->setData(array(
AdCreativeFields::NAME => $nm,
AdCreativeFields::OBJECT_STORY_SPEC => $story,
AdCreativeFields::URL_TAGS => 'product=' . $p_id,
));
$creative->create();
I do not see any parent id in this statement. Please help
$parent_id is deprecated
The issue was reported on facebook github with issue# 314
Response from Facebook Developer
"We are depreciating creation with parent_id. We are seeing multiple endpoints that can create the same type of object. We do not have good ways to decide which one we should use if you are creating new object with parent_id. Moving forward, please instantiate the parent object with the parent_id and call create_XXX function to create the object you want."
Sample Code:
use FacebookAds\Object\AdCreative;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Fields\AdCreativeFields;
$link_data = new AdCreativeLinkData();
$link_data->setData(array(
AdCreativeLinkDataFields::MESSAGE => 'try it out',
AdCreativeLinkDataFields::LINK => '<URL>',
AdCreativeLinkDataFields::IMAGE_HASH => '<IMAGE_HASH>',
));
$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
AdCreativeObjectStorySpecFields::LINK_DATA => $link_data,
));
$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
$creative->setData(array(
AdCreativeFields::NAME => 'Sample Creative',
AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
));
$creative->create();
Hope this helps.
Use setParentId($parrent_id).
Sample code:
$product_catalog = new ProductCatalog();
$product_catalog->setParentId($parrent_id);
$product_catalog->setData(
[
ProductCatalogFields::NAME => "Testjon Autojon Catalog",
ProductCatalogFields::VERTICAL => "vehicles",
]
);
$product_catalog->create();
I found even though the accepted answer mentioned in here, which is the use of $parent_id is deprecated, the sample code shared there is still shows the old way of doing it.
In that example, the second argument passed to in AdCreative() is still the $parent_id.
$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
For clarity mentioned below is the method signature of the constructor of \FacebookAds\Object\AbstractCrudObject which is what \FacebookAds\Object\AdCreative is extended from and, you'd see the deprecation notice there.
/**
* #deprecated deprecate constructor with null and parent_id
* #param string $id Optional (do not set for new objects)
* #param string $parent_id Optional, needed for creating new objects.
* #param Api $api The Api instance this object should use to make calls
*/
public function __construct($id = null, $parent_id = null, Api $api = null) {
parent::__construct();
//...
}
Said that as for the new approach, this is the way it should be done now :)
require __DIR__ . '/vendor/autoload.php';
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;
use FacebookAds\Object\AdAccount;
$access_token = '<ACCESS_TOKEN>';
$app_secret = '<APP_SECRET>';
$app_id = '<APP_ID>';
$id = '<AD_ACCOUNT_ID>';
$api = Api::init($app_id, $app_secret, $access_token);
$api->setLogger(new CurlLogger());
$fields = array();
$params = array(
'name' => 'Sample Creative',
'object_story_spec' => ['page_id' => '<pageID>',
'video_data' => ['IMAGE_URL' => '<imageURL>',
'video_id' => '<videoID>',
'call_to_action' => ['type' => 'LIKE_PAGE',
'value' => ['page' => '<pageID>']
]
]
],
);
$adCreative = (new AdAccount($id))->createAdCreative($fields, $params);
echo json_encode($adCreative->exportAllData(), JSON_PRETTY_PRINT);
I found this example here. Please note even though the title of this document is "Create an Ad Video Creative" it actually shows how to create the Ad creative. There are numerous inconsistencies in the Facebook Marketing API reference and this is such a case :)

How to get the item count on a DynamoDB table using PHP in real-time?

I have a table in Amazon DynamoDB. I want to get the number of items in the table using PHP script.
Now, I know that there are a lot of questions about this topic, but they are all obsolete, and the solutions use an out-of-date APIs.
I tried running this code, but probably, as I said, it uses an out-of-date API, since it can't find the class:
$dynamodb = new DynamoMetadata();
$scan_response = $dynamodb->scan(array(
'TableName' => 'Table',
'Count' => true
));
echo "Count: ".$scan_response->body->Count."\n";
I also tried with this, but again, it couldn't find the class:
$dynamodb = new AmazonDynamoDB();
I also tried using describeTable, to get ItemCount, but this number isn't updated. It gets updated only every 6 hours.
Is there a way so I could view the number of of items in the table in real-time?
Following solution helped me to get counts using php7 and AWS SDK v3:
<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\DynamoDb\Exception\DynamoDbException;
$sharedConfig = [
'region' => 'us-east-1',
'version' => 'latest',
'DynamoDb' => [
'region' => 'us-east-1'
]
];
$sdk = new Aws\Sdk($sharedConfig);
$client = $sdk->createDynamoDb();
$tableName = '<TABLE NAME>';
$params = [
'TableName' => $tableName,
'Select' => 'COUNT'
];
try {
$result = $client->scan($params);
$count = current($result)['Count'];
echo $count;
} catch (DynamoDbException $e) {
echo "Unable to query:\n";
echo $e->getMessage() . "\n";
}
So, I found a solution:
$result = $client->describeTable(array(
'TableName' => 'errors'
));
// The result of an operation can be used like an array
echo $result['Table']['ItemCount'] . "\n";
But this is not what I wanted...
I need a solution that will show me the number in real-time and not the number which was true 6 hours ago...

HORDE Imap PHP client - how to fetch messages

Okay, had no luck with the ZETA email client, so now I tried installing the Horde IMAP Client library. I've managed to login to my account, and make a search for e-mails, also got back the results, but I don't know how to fetch the email data, and the documentation is not really helping:|
I presume that I would have to use the Horde_Imap_Client_Base::fetch() method to get some e-mails, which accepts two parameters, a mailbox name, and a Horde_Imap_Client_Fetch_Query object, but I don't know how to get this second object:|
Should this object be returned by one of the Base functions, or should I build this object with the query parameters I want? If the second, how should I rebuild my search query in the fetch query object from the below example?
Here's how I am searching my INBOX, for mails from a specific contact on a specific day:
$client = new Horde_Imap_Client_Socket(array(
'username' => 'my.email#address.com',
'password' => 'xxxxxxxxxx',
'hostspec' => 'my.mail.server',
'port' => '143',
'debug' => '/tmp/foo',
));
$query = new Horde_Imap_Client_Fetch_Query();
$query->dateSearch(new Date(), Horde_Imap_Client_Search_Query::DATE_ON);
$query->headerText("from","mycontact#contact.email");
$results = $client->search('INBOX', $query);
The Horde_Imap_Client_Base::search() returns an array, which contains the search results(the message id's of the searched emails), and some additional data.
Not completely answering your questions. This is how I search for messages which are not deleted.
$client = new Horde_Imap_Client_Socket(array(
'username' => $user,
'password' => $pass,
'hostspec' => $server,
'secure' => 'ssl'
));
$query = new Horde_Imap_Client_Search_Query();
$query->flag(Horde_Imap_Client::FLAG_DELETED, false);
$results = $client->search('INBOX', $query);
foreach($results['match'] as $match) {
$muid = new Horde_Imap_Client_Ids($match);
$fetchQuery = new Horde_Imap_Client_Fetch_Query();
$fetchQuery->imapDate();
$list = $client->fetch('INBOX', $fetchQuery, array(
'ids' => $muid
));
var_dump($list);
}
$results = $client->search($mailbox, $searchquery, array('sort' => array($sSortDir, $sSort)));
$uids = $results['match'];
for ($i = $i_start; $i < $i_to; $i++)
{
$muid = new Horde_Imap_Client_Ids($uids->ids[$i]);
$list = $client->fetch($mailbox, $query, array(
'ids' => $muid
));
$flags = $list->first()->getFlags();
$part = $list->first()->getStructure();
$map = $part->ContentTypeMap();
$envelope = $list->first()->getEnvelope();
}

PHP Xml-RPC array and struct

I am using XML-RPC Lib for PHP to use online signature.
This is the official doc :
$doc = array(
"content" => new xmlrpcval($doc_content, "base64"),
"name" => new xmlrpcval($doc_name, "string")
);
$language = "fr";
$signers = array(new xmlrpcval($signer, "struct"));
$request = array(
"documents" => new xmlrpcval(array(new xmlrpcval($doc, "struct")), "array"),
...
But now I want to put several documents in the request. Here is my code :
$docs = array();
foreach ($documents as $document)
{
// Signature field
$field = array(
'page' => new xmlrpcval($document->page, 'int'),
'x' => new xmlrpcval($document->x, 'int'),
'y' => new xmlrpcval($document->y, 'int'),
'label' => new xmlrpcval($document->nom, 'string'),
);
// Document
$docs []= new xmlrpcval(array(
'content' => new xmlrpcval($document->content, 'base64'),
'name' => new xmlrpcval($document->nom, 'string'),
'signatureFields' => new xmlrpcval($field, 'array'),
),'struct');
}
$request = array(
'documents' => new xmlrpcval($docs, 'array'),
And I catch this error :
Message: Call to a member function serialize() on a non-object
Does someone allready used this library ? Cause I am lost right now..
I have come to realise that even if we have an array still for using the phpxmlrpc library, we need to define the array individually, so if one has to pass an array here is what can be done,
$listids // this was my one dimensional array
$subs_list_array = array();
foreach ($listids as $id) {
$subs_list_array[] = new xmlrpcval($id, "int");
}
$msg = new xmlrpcmsg(
"contact.subscribe", array(
//Set user id
new xmlrpcval($registration_id, "int"),
new xmlrpcval($subs_list_array, "array")// <- Now I am able to use the array
)
);
For recursive encoding of php arrays, you can also use the php_xmlrpc_encode function that will recursively convert arbitrarily deep data structures

Categories