How can i set a dynamic date for a JSON value? - php

Im trying to set a POST request to a file in my website with some data in JSON. There is a value response that needs to be a dynamic date so when the request is made the current date is saved in a custom field. How can i set up the code under "value" so the date is generated?
Have tried things like "variable":{ new Date(), } but can't make it work since always ends displaying the code and not a date, or the code is not validated if i add [ or { , etc.
{
"version": "v2",
"content": {
"messages": [],
"actions": [{
"action": "set_field_value",
"field_name": "bday_reg_date",
"value": "2019-06-22"
}, {
"action": "set_field_value",
"field_name": "bday_exp_date",
"value": "2019-06-29"
}
That's the code im basing mine. Everytime i access the file (apparently a .php file), a new date is generated on "value", that date is send and to a custom field called reg_date on another platform. What should be the correct way to get that dynamic value?
Thanks.

If your are trying to create a new json object in PHP you have to create an array first then use the json_encode($arr) function to convert it to json.
https://www.php.net/manual/en/function.json-encode.php
IE:
<?php
$dateNow = new DateTime('now');
$dateNextWeek = new DateTime('now');
$dateNextWeek->modify('+1 week');
$arr = [
'version' => 'v2',
'content' => [
'messages' => [],
'actions' => [
[
'action' => 'set_field_value',
'field_name' => 'bday_reg_date',
'value' => $dateNow->format('d-m-Y'),
],
[
'action' => 'set_field_value',
'field_name' => 'bday_reg_date',
'value' => $dateNextWeek->format('d-m-Y'),
],
]
]
];
return json_encode($arr);

Related

How can i apply cell format dynamically by columns name?

good day, my current problems here is to apply date and decimal format based on columns name.
`
//Date Format
new \Google\Service\Sheets\Request([
"repeatCell" => [
"range" => [
"sheetId" => $sheet_id,
"startColumnIndex" => 1,
"endColumnIndex" => 3,
],
"cell" => [
"userEnteredFormat" => [
"numberFormat" => [
"type" => "DATE",
"pattern" => "dd-mm-yyyy"
]
]
],
"fields" => "userEnteredFormat.numberFormat",
],
]),
//Decimal Format
new \Google\Service\Sheets\Request([
"repeatCell" => [
"range" => [
"sheetId" => $sheet_id,
"startColumnIndex" => 2,
"endColumnIndex" => (sizeof($this->dataCols->all())),
],
"cell" => [
"userEnteredFormat" => [
"numberFormat" => [
"type" => "NUMBER",
"pattern" => "#,##0.00"
]
]
],
"fields" => "userEnteredFormat.numberFormat",
],
]),
`
I already figure it out based on column range. My real question is which part do i need to modified to apply cell format based on column name? Thank you.
The sample:
This is date columns.
This is Amount column.
i have alots of columns name that goes by default datatype.Currently, i set the format based on range, for examples like setIndexColumns =>0, endIndexColumns =>3, . How do i set the datatype format by columns name? for examples, if the columns name Doc. Date, the whole column or the data will be shown as date format. if the columns name Amount(MYR), the whole column or data will be shown as decimal format.
I believe your goal is as follows.
You want to set the number format to the columns by searching the column title. The request body of the number format is shown in your script.
In your Spreadsheet, the header row is row 3. And, you want to set the number format from row 3 to the last row.
You want to achieve this using googleapis for PHP.
You have already been able to get and put values to Google Spreadsheet using Sheets API.
In this case, I thought that the following flow is required to be done.
Retrieve the header row (In your situation, it's row 3.).
Create the request body by searching the column using the header title.
Request Sheets API using the created request body.
When this flow is reflected in the sample script, it becomes as follows.
Sample script:
$service = ###; // Please use your client.
$spreadsheet_id = "###"; // please set Spreadsheet ID.
$sheet_name = "Sheet1"; // Please set the sheet name.
$sheet_id = "###"; // Please set the sheet ID of the sheet name.
// Object for searching the header title. This is from your showing script.
$obj = [
"Doc. Date" => ["numberFormat" => ["type" => "DATE", "pattern" => "dd-mm-yyyy"]],
"Amount (MYR)" => ["numberFormat" => ["type" => "NUMBER", "pattern" => "#,##0.00"]]
];
// Retrieve the header title.
$res1 = $service->spreadsheets_values->get($spreadsheet_id, "'" . $sheet_name . "'!A3:3");
$header = $res1["values"][0];
// Create a request body for batchUpdate.
$requests = [];
foreach ($header as $i => $h) {
if (array_key_exists($h, $obj)) {
array_push($requests,
new \Google\Service\Sheets\Request([
"repeatCell" => [
"range" => [
"sheetId" => $sheet_id,
"startColumnIndex" => $i,
"endColumnIndex" => $i + 1,
"startRowIndex" => 3,
],
"cell" => ["userEnteredFormat" => $obj[$h]],
"fields" => "userEnteredFormat.numberFormat",
],
]),
);
};
}
// Request Sheets API using the created request body.
if (count($requests) > 0) {
$batchUpdateCellFormatRequest = new \Google\Service\Sheets\BatchUpdateSpreadsheetRequest(["requests" => $requests]);
$service->spreadsheets->batchUpdate($spreadsheet_id, $batchUpdateCellFormatRequest);
};
When this script is run, the header title is retrieved from row 3, and create a request body using the header title and object. And, request Sheets API using the request body.
Note:
If your actual header titles are different from $obj, please modify them for your actual header title.
References:
Method: spreadsheets.values.get
Method: spreadsheets.batchUpdate

Elasticsearch and Laravel scout-elasticsearch-driver timestamps malformed error

I have successfully configured ES and the babenkoivan/scout-elasticsearch-driver, but run into this error when adding new entries to the DB:
{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to parse [updated_at.raw]"}],"type":"mapper_parsing_exception","reason":"failed to parse [updated_at.raw]","caused_by":{"type":"illegal_argument_exception","reason":"Invalid format: \"2018-07-13 07:52:02\" is malformed at \" 07:52:02\""}},"status":400}
I have set the format in the mapping like this, and according to the ES docs this format should work:
protected $mapping = [
'properties' => [
'created_at' => [
'type' => 'date',
'format' => 'yyyy-MM-DD HH:mm:ss',
'fields' => [
'raw' => [
'type' => 'date',
'index' => 'not_analyzed'
]
]
],
'updated_at' => [
'type' => 'date',
'format' => 'yyyy-MM-DD HH:mm:ss',
'fields' => [
'raw' => [
'type' => 'date',
'index' => 'not_analyzed'
]
]
]
]
];
https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html#multiple-date-formats
Is there something I'm missing here?
In your mapping you defined a custom date format (yyyy-MM-DD HH:mm:ss) for created_at and updated_at. The raw fields instead are a date type too, but use the default format (which according the doc is date_optional_time, meaning yyyy-MM-DD'T'HH:mm:ss).
This means that the former expects 2018-07-13 07:52:02, while the latter 2018-07-13T07:52:02, so you indexing can't possibly avoid breaking one of the two.
Now, the use of multi-fields is meant to index values in different ways, but what you are doing is to create a new field raw with basically the same properties of the base value (they are both date types, except for the inconsistency in the format, of course).
So, in my opinion you options are:
if you don't have any specific use for raw you can remove it from the mapping. Sorting and matching works well with the base field.
"created_at": {"type": "date", "format": "yyyy-MM-DD HH:mm:ss"}
if you need to keep the original string format (as "raw" may suggest) you can use a keyword type
"created_at": {"type": "date", "format": "yyyy-MM-DD HH:mm:ss", "fields": {"raw": {"type": "keyword"}}}
if you really need the raw field as is, you have to specify a format that is consistent with the other one:
"created_at": {"type": "date", "format": "yyyy-MM-DD HH:mm:ss", "fields": {"raw": {"type": "date", "format": "yyyy-MM-DD HH:mm:ss"}}}

Craft Element API data output as a hash instead of an array

I'm building and API feed using Element API plugin from Craft, and I'd like the data output to be serialized as a hash, but currently it's returning an array, as example bellow:
<?php
namespace Craft;
return [
'endpoints' => [
'event-name/feed.json' => [
'elementType' => ElementType::Entry,
'criteria' => ['section' => 'event1'],
'transformer' => function(EntryModel $entry) {
$speakersList = [];
foreach ($entry->speakersList as $speaker) {
$speakersList[] = [
'name' => $speaker->speakerFullName,
'jobTitle' => $speaker->speakerJobTitle,
'company' => $speaker->speakerCompany,
];
}
return [
'speakers' => $speakersList,
];
},
],
];
And the output:
{
"data": [
{
"speakers": [
{
"name": "John Doe",
"jobTitle": "Marketing",
"company": "Company 1",
},
...
I've tried the serialize options in the documentation, but none seemed to solve the issue.
Currently if I'd like to access the speakers within data I'd have to first access index[0] to be able to get to the speakers key.
Is there a way to get rid of this array level?

Laravel & PHP: Return special formatted JSON

After doing a query, how can I create and echo a formatted JSON like this:
{
"results": [
{
"user_id": "1",
"name": "Apple",
"address": "7538 N LA CHOLLA BLVD",
"city": "Palo Alto",
"state": "CA",
"latlon": [
-111.012654,
32.339807
],
},
{
"user_id": "2",
"name": "Microsoft",
"address": "75 S BWY STE 400",
"city": "Palo Alto",
"state": "CA",
"latlon": [
-73.764497,
41.031858
],
},
],
"meta": {
"page": 1,
"per_page": 10,
"count": 493,
"total_pages": 50
}
}
This is my current query:
public function getAgenciesJson() {
$agencies = DB::table('users')->where('type','a')->orWhere('type','l');
}
Haven't figured out how to output JSON like that, considering I have a "latlon" field like [-111.012654,32.339807], also a "results" tag and a "meta" tag.
Thanks in advance
What you need is something called a transformer (or presenter) to convert your raw model into a format that can be sent to your users.
A very popular package is called Fractal (http://fractal.thephpleague.com/) by Phil Sturgeon. There's a Laravel package, that might make it a bit easier to use, called Larasponse (https://github.com/salebab/larasponse).
Phil actually a blog post about this just the other day - https://philsturgeon.uk/api/2015/05/30/serializing-api-output/ - that goes into why you should always have some kind of transformer between your models and what you send to your users.
There's also a guide about using Larasponse and Fractal that might be of use here - http://laravelista.com/laravel-fractal/.
The gist of it boils down to passing the model through another class that will take the models values and build an array/object in a known/fixed format, e.g. (from Phil's blog post)
return [
'id' => (int) $book->id,
'title' => $book->title,
'year' => (int) $book->yr,
'author' => [
'name' => $book->author_name,
'email' => $book->author_email,
],
'links' => [
[
'rel' => 'self',
'uri' => '/books/'.$book->id,
]
]
];
This way you're not exposing your original field names and if at any point your column names should change you only need to update that in 1 place rather than having to get any user of your JSON to update their site/app. It will also allow you to do string manipulation of your latlon column so that you can split it into 2 different values.
Using a slightly modified example from the Fractal documentation. Say you have a transformer for a User
class UserTransformer extends Fractal\TransformerAbstract
{
public function transform(User $user)
{
return [
'id' => (int) $user->id,
'name' => $user->first_name . ' ' . $user->last_name,
];
}
}
You can then use this class to either transform a single item of a collection
$user = User::find(1);
$resource = new Fractal\Resource\Item($user, new UserTransformer);
// Or transform a collection
// $users = User::all();
// $resource = new Fractal\Resource\Collection($users, new UserTransformer);
// Use a manager to convert the data into an array or json
$json = (new League\Fractal\Manager)->createData($resource)->toJson();
Fractal includes a paginator adapter for Laravel that can be used straight away
$paginator = User::paginate();
$users = $paginator->getCollection();
$resource = new Collection($users, new UserTransformer);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
The method exists:
->toJson()
REF: http://laravel.com/docs/4.2/eloquent#converting-to-arrays-or-json
Update your getAgenciesJson to :
public function getAgenciesJson() {
return DB::table('users')->where('type','a')->orWhere('type','l')->toJson();
}
Then you could echo by:
<?= SomeModel::getAgenciesJson(); ?>
To modify the column names you can update your select. Here is an example taken from the Laravel Docs:
$users = DB::table('users')->select('name as user_name')->get();
Here would be a more fully realized version of what you are looking for minus the column aliases since you didn't really mention what they were.
public function getAgenciesJson($page, $per_page = 10) {
$output = [
'results' => [],
'meta' => [],
];
// Get Results
$output['results'] = DB::table('users')->where('type','a')->orWhere('type','l')->take($per_page)->skip($per_page * ($page - 1))->get();
// Set Meta
$output['meta'] = [
'page' => $page,
'per_page' => $per_page,
'count' => DB::select('SELECT FOUND_ROWS()'),
'total_pages' => DB::table('users')->count() / $per_page
];
// Return
return json_encode($output);
}
Your original code didn't attempt to get or handle the pagination information but this example covers that in order to provide the meta data you indicated you wanted returned.
Not sure if you wanted Count to be the number of the current result set or a count of all the records on that table. If you don't want the current set you but rather the entire count you can use DB::table('users')->count() though I would assign it to a variable and use that rather than calling it twice in the meta info.
public function getAgenciesJson() {
$agencies = DB::table('users')->where('type','a')->orWhere('type','l')->get();
return response()->tojson($agencies,200);//for response with status code 200
}
You should call get function to get data in array format and response function will format your output to json. Second paramater signifies which status code you have to assign for your response.

Store and retrieve nested JSON in DynamoDB with PHP SDK

I have created the following table in DynamoDB:
Field1: messageId / Type: String / Example value: 4873dd28-190a-4363-8299-403c535e160f
Field2: microtime / Type: Number / Example value: 14143960092414
Field3: data / Type: nested JSON-Array / Example value: {"foo":"bar","other":{"nested":1}}
I am performing the following request using PHP SDK for DynamoDB to create an entry
$raw = '{"foo":"bar","other":{"nested":1}}';
$result = $client->putItem(array(
'TableName' => 'requests2',
'Item' => array(
'messageId' => array('S' => '4873dd28-190a-4363-8299-403c535e160f'),
'microtime' => array('N' => microtime(true)*10000),
'data' => array('S' => $raw),
)
));
I want then to query the table and filter using variables within the JSON-array data field. Is my above solution to entering the data the right approach? The JSON-array gets stored as string, as to my understanding. Do we need another datatype? Basically, I can already query the table like below to retrieve messages that were added within the last minute:
$iterator = $client->getIterator('Query', array(
'TableName' => 'requests2',
'KeyConditions' => array(
'messageId' => array(
'AttributeValueList' => array(
array('S' => '4873dd28-190a-4363-8299-403c535e160f')
),
'ComparisonOperator' => 'EQ'
),
'microtime' => array(
'AttributeValueList' => array(
array('N' => strtotime("-1 minutes")*10000)
),
'ComparisonOperator' => 'GT'
)
)
));
foreach ($iterator as $item) {
echo $item['messageId']['S']." ";
}
But how can I modify my request to allow querying by ANY value within the data-field? For example, filter by only those who have [data][other][nested]=1
I've spent the past hours on this issue and I can't get it to work... I am very grateful for any tips, thanks in advance!
I know this was posted in 2014, but I was looking exactly for this answer and so I'd like to share the result in my search to anyone that will land on this question in the future.
Best practice is to store a JSON as a string, but use a Marshaler object to turn the JSON into something that DynamoDB can digest, and that you will be able to query too:
Using marshalJSON method you turn a JSON, as you can see described in this amazon link
For the ones that are looking for a quick example, I add here below the key parts of the procedure:
If you have a JSON like the following
{
"id": "5432c69300594",
"name": {
"first": "Jeremy",
"middle": "C",
"last": "Lindblom"
},
"age": 30,
"phone_numbers": [
{
"type": "mobile",
"number": "5555555555",
"preferred": true
},
{
"type": "home",
"number": "5555555556",
"preferred": false
}
]
}
stored in a string variable $json, you can simply do
use AwsDynamoDbDynamoDbClient;
use AwsDynamoDbMarshaler;
$client = DynamoDbClient::factory(/* your config */);
$marshaler = new Marshaler();
$client->putItem([
'TableName' => 'YourTable',
'Item' => $marshaler->marshalJson($json)
]);
I don't think AWS PHP SDK for DynamoDB has yet implemented the support for JSON based document storage. Their recent notification published on their blog on 8th October 2014, mentions about the support of this new feature only in Java, .NET, Ruby and JS SDK.

Categories