Random data container using magic methods __get and __set - php

Is it possible to create a PHP class that can hold whatever type of data you throw at it, even recursively, using magic methods?
I saw this: PHP - Indirect modification of overloaded property
but it doesn't handle recursive data:
class ActiveRecord extends Creator {
}
$a = new ActiveRecord();
$a->_id = "123456789";
$a->persona_info = [
"name" => "Bob",
"surnames" => ["First", "Second", "Third"]
];
$a->history = [
"logins" => [
[
"date" => "1999",
"ip" => "1.2.3.4"
],
[
"date" => "1129",
"ip" => "1.2.3.4"
]
],
"purchases" => [
[
"date" => "1819",
"amount" => "1884"
],
[
"date" => "1459",
"amount" => "14"
]
]
];
var_dump($a->history->logins);
That gives me:
PHP Notice: Trying to get property of non-object in /tmp/x.php on line 90
PHP Stack trace:
PHP 1. {main}() /tmp/x.php:0
NULL
Trying to investigate further, I see that $a->history is a plain php array instead of a Value object (or even a Creator object.

The problem is $a->history is an array and not a object. It should be var_dump($a->history['logins']);

Related

PHP: array_map to return specific array of objects

I have a codepen here which shows a large array of objects. From which I would like to extract a specific property and display as shown in the console log, but in PHP.
Unfortunately for me, I'm quite new to PHP and can't seem to figure it out:
My attempt so far:
$suppliersNotInDB = array_map(function ($order) {
if (isset($order->items) && is_array($order->items)) {
return array_map(function ($item) {
return [...$item];
}, $order->items);
}
}, $ordersData);
Which, I understand isn't even remotely close, but I've been at it for hours now. Any help would be appreciated.
The long and short is that I want to perform this filtering and sorting in the backend(Laravel), not the frontend, where there is already too much going on.
Since you are using Laravel, start using Collections.
If I understood correctly what you are trying to do in your Javascript example, this can be done in a one-liner:
$suppliersNotInDB = collect($ordersData)
->pluck('items')
->flatten()
->pluck('supplier')
->unique()
->map(
fn($supplier) => ['name' => $supplier, 'lowercased' => strtolower($supplier)]
)
->values();
This can probably be further refined, just quickly jotted it down to reproduce your result.
The output of this would then be:
=> Illuminate\Support\Collection {#4999
all: [
[
"name" => "Walmart",
"lowercased" => "walmart",
],
[
"name" => "Bestbuy",
"lowercased" => "bestbuy",
],
[
"name" => "TCI",
"lowercased" => "tci",
],
[
"name" => "lkj",
"lowercased" => "lkj",
],
[
"name" => "Thousand Needles",
"lowercased" => "thousand needles",
],
],
}

ElasticSearch 7 & PHP - Create mapping for parent / child relation

I want to index in my index buildings 2 types of documents: building & apartment.
A building can have several apartment, so I want to use parent/child relationships.
I use ES 7.10 and PHP with official PHP lib (elasticsearch/elasticsearch).
According to the doc (https://www.elastic.co/guide/en/elasticsearch/guide/current/parent-child-mapping.html), I have to use something like :
PUT index buildings
{
"mappings": {
"building": {},
"apartment": {
"_parent": {
"type": "building"
}
}
}
}
In my PHP I have :
$this->getClient()->indices()
->create([
'index' => 'buildings',
'body' => [
'mappings' => [
'building' => [],
'apartment' => [
'_parent' => [
'type' => 'building'
]
]
]
]
]);
Which throws the error:
Root mapping definition has unsupported parameters: [apartment: {_parent={type=building}}] [building: []]"}},"status":400}
Did I miss something?
Parent/type has been deprecated in favor of join type in Elasticsearch 7 as far as I remember, so this might be the reason you're getting the exception.
Link to docs: https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html

Firebase PHP Data Submission - arrayValue, mapValue

I am trying to push data to a firestore DB using PHP and the Google apis.
Inside the documentation and examples I have seen around the web, I am able to use mapValue and arrayValue when sending data.
The example I am using is as follows:-
[
"orderName" => [
"stringValue" => "Gbeila Aliu Wahab"
],
"orderLocationName" => [
"stringValue" => "Accra Mall Limited"
],
"orderTotalAmount" => [
"doubleValue" => 150.5
],
"orderDescription" => [
"stringValue" => "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
],
"orderLocationGeoPoints" => [
"geoPointValue" => (object) [
"latitude" => 5.5557,
"longitude" => -0.1963
]
],
"orderStatus" => [
"stringValue" => "NotAssigned"
],
]
This works perfectly fine, but when I attempt to send an object or an array I get the following error returned to me:-
"message": "Invalid JSON payload received. Unknown name \"map_value\" at 'document.fields[0].value': Proto field is not repeating, cannot start list.",
when attempting to map the value using the following code:-
"orderName" => [
"mapValue" => ["Gbeila Aliu Wahab", 123]
]
// or
"orderName" => [
"arrayValue" => [
"first" => [
"stringValue" => "test"
],
"second" => [
"stringValue" => "test123"
]
]
]
I have tried many variations to try to get this to work.
How am I supposed to be using the mapValue and arrayValue I can see a lot of mentions regarding the value option but I cannot see any examples on how to use the.
Any help would be greatly appreciated.
Payload to your array or map you're generating is incorrect as per the documentation. You need to wrap your actual data (to store) under values key, your final array should be:
["orderName" => ["arrayValue" => ["values" => [["stringValue" => "test"], ["stringValue" => "test123"]]]]]
Similarly your mapValue should be
["orderName" => ["mapValue" => ["fields" => ["field1" => ["stringValue" => "Gbeila Aliu Wahab"]]]]]
Also, you can play with other data mapper via this package.

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?

Combine two queries in one request

I want to execute multiple queries on elasticsearch server with one request. Specifically I have the following query (is on elastcisearch-php-client)
$params = [
"index" => "bookydate",
"type" => "vendor_service",
"body" => [
"query" => [
"bool" => [
"must" => [
"term" => [
"sys_service_id" => $request->input("sys_service_id")
]
],
"should" => [
"geo_shape" => [
"served_location" => [
"shape" => [
"type" => "point",
"coordinates" => [
"{$request->input('loc_lon')}",
"{$request->input('loc_lat')}"]
]
]
]
]
]
]
]
];
What I want to do is the fetch also all the documents that have the "hole_country" field to true.
What I have tried already is to make another request to Elasticsearch server and with array_merge combine the two results, but did not work because of PHP restrictions on arrays with multiple same keys.
UPDATE
Elastcisearch supports a feature called Multisearch that is exactly what im looking for. The problem is that php-client does not support multisearch so I have to use Guzzle in order to send the requests.
Guzzle docs does not have a full info about how to construct a correct request body. Any info is welcome
Already i have the following body but elastcisearch is returing bad request error
$body = [
["index"=>"bookydate"],
["query"=>["bool"=> ["must"=>[["term"=>["sys_service_id"=>"1"]],["geo_shape"=>["served_location"=>["shape"=>["type"=>"circle","coordinates"=>[25,3],"radius"=>"90km"]]]]]]]],
["index"=>"bookydate"],
["query"=>["bool"=>["must"=>["term"=>["hole_country"=>true]]]]]
];
You can use the multisearch API of Elasticsearch. This is more or less appending all your queries as JSON format in a single POST request. I hope the PHP client supports this, otherwise you might have to manually do the POST request.
Multi-search API
Although it's not documented the Multi Search API is supported by the elasticsearch php client.
Instead of search call msearch, and group your queries like this:
$params = [
'body' => [
["index" => "bookydate", "type" => "vendor_service"],
["query" => [
"bool" => [
"must" => [
"term" => [
"sys_service_id" => $request - > input("sys_service_id")
]
],
"should" => [
"geo_shape" => [
"served_location" => [
"shape" => [
"type" => "point",
"coordinates" => [
"{$request->input('loc_lon')}",
"{$request->input('loc_lat')}"
]
]
]
]
]
]
]]
];
So using your updated syntax is correct. You must just call msearch.

Categories