I have some code running on my website that uses API calls to pull events from a calendar and show them on my website. The code is fairly simple overall, and works well, however to prevent the code from running every time the page loads, I'm using PHP Redis to save the key data to a Redis List, then a cronjob to run the php code that uses the Redis List to fetch the information from the calendar API, and save the information to Redis.
Everything works fine, except I am using foreach to run through each instance of the Redis List; and it keeps running through all the entries but saving only the last one. What can I do to fix this?
My code:
<?php
function redis_calendar_fetch() {
$redisObj1 = new Redis();
$redisObj1 -> connect('localhost', 6379, 2.5, NULL, 150 );
date_default_timezone_set('America/Edmonton');
$fetcharray = $redisObj1-> smembers('fetch_list');
$effectiveDate = date('Y-m-d', strtotime('+12 months'));
$application_id = "REDACTED";
$secret = "REDACTED";
$fafull = array();
foreach($fetcharray as $faraw) {
$fa1 = json_decode($faraw);
$fa2 = json_decode(json_encode($fa1), true);
$fafull[] = $fa2;
}
$redisObj1 -> close(); // This code all works perfectly, and returns the Redis List results in an array that can be used by foreach
foreach($fafull as $fa) {
$redisObj = new Redis();
$redisObj -> connect('localhost', 6379, 2.5, NULL, 150 );
// After this, I run through all the array data, pull data & process it properly. I have omitted this from this question because it is long and arduous, and runs perfectly fine.
// Right before this, an array called $redisarray is created that contains all the relevant event data //
$redisarrayfixed = json_encode($redisarray);
$redisObj->set($key, $redisarrayfixed);
$redisObj -> close();
// If I put a line here saying 'return = $redisarrayfixed', the code runs only the first instance of the array and stops. If I omit this, it runs through all of them, but only saves the last one
}
}
redis_calendar_fetch();
As mentioned, I then use a cronjob to run this code every 30 minutes, and I have a separate piece of php code that handles the shortcode & fetches the proper saved events for the proper page.
My concern solely is with the foreach($fafull as $fa), which only saves the final result to Redis. Is there a better way to force each array instance to save?
For performance, you might want to keep just one instance of a redis connection active.
Secondly, it's only going to save the final result because on each iteration, you are using the same $key. It seems like what you want to do is iterate and push to an array, then at the end, save it entirely.
Example of how I'm understanding this;
$redisObj = new Redis();
$redisObj -> connect('localhost', 6379, 2.5, NULL, 150 );
$someArray = array();
foreach($fafull as $fa) {
$redisarrayfixed = json_encode($redisarray);
array_push($someArray, $redisarrayfixed);
}
$redisObj->set($key, $someArray);
$redisObj -> close();
Related
A number of Xero accounts API samples have PHP variables which start with {
Example:
$invoices = {invoices:[{type: Invoice.TypeEnum.ACCREC, contact:{contactID:"00000000-0000-0000-000-000000000000"}, lineItems:[{ description:"Acme Tires", quantity:2.0, unitAmount:20.0, accountCode:"000", taxType:"NONE", lineAmount:40.0}], date:"2019-03-11", dueDate:"2018-12-10", reference:"Website Design", status: Invoice.StatusEnum.DRAFT}]};
I am struggling to understand how this can work. I am trying to use the API to create multiple invoices in the same call, I can do it fine in Postman so I know my code is OK.
I have tried following:
creating-an-invoice-using-oauth2-in-xero
Using the documents
But for some reason I just can't find a way to make it work.
All our SDKs and documentation is generated from our OpenAPI specs. Generating runnable code in our docs is our long term goal. In the interim, we needed to offer "some" generated docs, but the JSON payloads are not meant to be used.
We have created a sample app that demonstrates different endpoints and displays the code used to make the call.
https://github.com/XeroAPI/xero-php-oauth2-app
Here is the code you'll need to create an invoices
$result = $apiInstance->getContacts($xeroTenantId);
$contactId = $result->getContacts()[0]->getContactId();
$contact = new XeroAPI\XeroPHP\Models\Accounting\Contact;
$contact->setContactId($contactId);
$arr_invoices = [];
$invoice_1 = new XeroAPI\XeroPHP\Models\Accounting\Invoice;
$invoice_1->setReference('Ref-456')
->setDueDate(new DateTime('2019-12-10'))
->setContact($contact)
->setLineItems($lineitems)
->setStatus(XeroAPI\XeroPHP\Models\Accounting\Invoice::STATUS_AUTHORISED)
->setType(XeroAPI\XeroPHP\Models\Accounting\Invoice::TYPE_ACCPAY)
->setLineAmountTypes(\XeroAPI\XeroPHP\Models\Accounting\LineAmountTypes::EXCLUSIVE);
array_push($arr_invoices, $invoice_1);
$invoice_2 = new XeroAPI\XeroPHP\Models\Accounting\Invoice;
$invoice_2->setReference('Ref-123')
->setDueDate(new DateTime('2019-12-02'))
->setContact($contact)
->setLineItems($lineitems)
->setStatus(XeroAPI\XeroPHP\Models\Accounting\Invoice::STATUS_AUTHORISED)
->setType(XeroAPI\XeroPHP\Models\Accounting\Invoice::TYPE_ACCPAY)
->setLineAmountTypes(\XeroAPI\XeroPHP\Models\Accounting\LineAmountTypes::EXCLUSIVE);
array_push($arr_invoices, $invoice_2);
$invoices = new XeroAPI\XeroPHP\Models\Accounting\Invoices;
$invoices->setInvoices($arr_invoices);
$result = $apiInstance->createInvoices($xeroTenantId,$invoices);
I am able to connect to my elasticache cluster like so:
$awsElasticache = new ElastiCacheClient(CredentialProvider::atsDefaultConfigConstructor(false, false));
$clusterResult = $awsElasticache->describeCacheClusters(array('CacheClusterId'=>'my_cluster'));
When I print $clusterResult, I get info about the cluster, good.
But how can I actually interact with the endpoint to set key/value pairs?
I am trying this without success:
$this->mem = new Memcached();
$this->mem->addServer($this->endPoint,11211);
$this->mem->set('myKey','myValue',3600);
$result = $this->mem->get('myKey');
echo $result;
I get nothing printed from $result.
I am confused about which object to use to set and get key/value pairs.
To set key/value pair in Memcached, always extend the time of expiry from current time.
Try this
$this->mem = new Memcached();
$this->mem->addServer($this->endPoint,11211);
$expires = Carbon::now()->addMinutes(10);
$this->mem->set('myKey','myValue', $expires);
$result = $this->mem->get('myKey');
echo $result;
NOTE: For some reason, Memcached works best with Carbon time
See https://artisansweb.net/work-php-datetime-using-carbon/ on how to setup and use Carbon on your current project
I have this project in php in which my goal is to compare data from the database with some data I get from outlook, and if it's the same data i skip to the next row, otherwise I update.
The data in the DB comes like below:
$db = 'Meeting F2F Planung Meetings/Bilas 2018 2017-09-19 10:002017-09-19 12:0000KI Büro'
The data from outlook:
$outlook = 'Meeting F2F Planung Meetings/Bilas 2018<font size="2"><span style="font-size:10pt;"><div class="PlainText"> </div></span></font>2017-09-19 10:002017-09-19 12:0000KI Büro'
What i do is to get the data from outlook look like the one in DB is:
$outlook = (strip_tags(html_entity_decode($outlook)));
I still get the 'Büro' when I transfrom the data from outlook, so when i compare $outlook and $event, they appear as not equal so in my project it updates.
By asking here I got to the code above, but in this case it doesn't seem to work.
Try this
$outlook = utf8_decode(strip_tags(htmlspecialchars_decode($outlook)));
echo $outlook;
MongoDB + PHP: How do you query the size of a document stored in a mongodb object? The document limit, at the time of this writing (recently raised from 4MB), is 16MB.
How can I query the size of a Document using the ObjectId?
Object.bsonsize(document) is the function you're after. I'm reading this thread and finding a few suggestions about how to do it in php. The easiest is probably to query for the document object and run strlen on the bson_encode'd object giving you the size in bytes.
$byteSize = strlen( bson_encode( $yourDocument ) );
If you're wanting to do this check on a lot of documents, say in a loop, without reading back every document you'll need to run a command execute (Mardix had posted this little function to do just that - note: it could easily be rewritten a little better to avoid the hardcoded and global variables):
$DBName = "MyDBName";
$MongoDB = new MongoDB(new Mongo(),$DBName);
function documentSize(Array $Criteria){
global $MongoDB;
$collectionName = "MyCollection";
$jsonCriteria = json_encode($Criteria);
$code = "function(){
return Object.bsonsize(db.{$collectionName}.findOne({$jsonCriteria}))
}";
$resp = $MongoDB->execute($code);
return $resp["retval"];
}
PHP example where $id is the document id
$myDocSize = documentSize(array("_id"=>$id));
As part of a PHP webapp I have MySQL contacts table. It is integrated throughout the app, allowing you add a contact, edit a contact or add a contact as a relation to another table. However, currently it is self-contained. The company would like it to sync with Exchange, so that contacts added to Exchange will show up on the webapp and contacts added on the webapp will show up through Exchange.
So I have two problems: 1) communicating with Exchange 2) syncing with Exchange.
As far as the basic communication goes, it looks like this library will be able to manage it https://github.com/jamesiarmes/php-ews. However, I am quite lost as to how to manage syncing and don't where to start.
The build-in way to sync items is via function called SyncFolderItems. Basically to Exchange everything, including contacts is a folder, so you'll just pass CONTACTS as DistinguishedFolderId in your sync request.
The sync works by donloading all the items for given account in batches of max 512 elements and after each batch it gives you SyncState as a refernce point for Exchange to know where you left off. So it gives you ability to do incremental sync.
Now, that's one way of course, meaning Exchange -> Your DB. The other way it aeound you should preform atomic updates/request - the moment you change/add/delete item form your db you should issue adequate request to Exchange server to keep data in sync, elese it'll be overwritten on your next SyncFolderItems.
You can read up more on SyncFolderItems # MSDN
If you'd like to see example of SyncFolderItems you can take a look # python version of EWSWrapper, it's been added in recently. Although it's python, you can still get the basic idea how to construct the request / handle response.
Hope this helps :)
I am aware that this topic is pretty old. However, for future reference find a solution below. It is using the above-mentioned library php-ews.
I have also just added this to the official php-ews wiki: https://github.com/jamesiarmes/php-ews/wiki/Calendar:-Synchronization
// Define EWS
$ews = new ExchangeWebServices($host, $username, $password, $version);
// fill with string from last sync
$sync_state = null;
$request = new EWSType_SyncFolderItemsType;
$request->SyncState = $sync_state;
$request->MaxChangesReturned = 512;
$request->ItemShape = new EWSType_ItemResponseShapeType;
$request->ItemShape->BaseShape = EWSType_DefaultShapeNamesType::ALL_PROPERTIES;
$request->SyncFolderId = new EWSType_NonEmptyArrayOfBaseFolderIdsType;
$request->SyncFolderId->DistinguishedFolderId = new EWSType_DistinguishedFolderIdType;
$request->SyncFolderId->DistinguishedFolderId->Id = EWSType_DistinguishedFolderIdNameType::CALENDAR;
$response = $ews->SyncFolderItems($request);
$sync_state = $response->ResponseMessages->SyncFolderItemsResponseMessage->SyncState;
$changes = $response->ResponseMessages->SyncFolderItemsResponseMessage->Changes;
// created events
if(property_exists($changes, 'Create')) {
foreach($changes->Create as $event) {
$id = $event->CalendarItem->ItemId->Id;
$change_key = $event->CalendarItem->ItemId->ChangeKey;
$start = $event->CalendarItem->Start;
$end = $event->CalendarItem->End;
$subject = $event->CalendarItem->Subject;
}
}
// updated events
if(property_exists($changes, 'Update')) {
foreach($changes->Update as $event) {
$id = $event->CalendarItem->ItemId->Id;
$change_key = $event->CalendarItem->ItemId->ChangeKey;
$start = $event->CalendarItem->Start;
$end = $event->CalendarItem->End;
$subject = $event->CalendarItem->Subject;
}
}
// deleted events
if(property_exists($changes, 'Delete')) {
foreach($changes->Delete as $event) {
$id = $event->CalendarItem->ItemId->Id;
$change_key = $event->CalendarItem->ItemId->ChangeKey;
$start = $event->CalendarItem->Start;
$end = $event->CalendarItem->End;
$subject = $event->CalendarItem->Subject;
}
}