Iterating through an array and replacing data within a template - php

I have an XML document with "tags" that are replaced based on data within an array. There are two types of tags, one is a parent tag to define a set, another is simply a tag that is replaced by a value. Here's an example of the data used to build and fill in the template:
$array = array(
'name' => 'name',
'city' => 'city',
'addresses' => array(
array(
'street' => '123',
'city' => 'main'
),
array(
'street' => '123',
'city' => 'main'
'phone' => array(
array(
'home' => '123456', 'work' => '1234567'
)
Here is an example template:
<name>%name%</name>
<city>%city%</city>
%%addresses%%
<street>%street%</street>
<city>%city%</city>
%%phone%%
<home>%%home%%</home>
<work>%%work%%</work>
%%/phone%%
%%/addresses%%
The key values of the array, match the tags within the template. If the key is an array itself, then it loops through the data contained within that key's tag (%%).
I've tried doing a recursive function but it only seems to work one level deep.
Does anyone have any suggestions? Thank you!

I suggest you use an existing simple template language that "just works"tm, like Mustache (there are plenty much others). I know that Mustache supports looping over arrays, used it, does the job, easy to integrate. Available for many languages.

Related

Algolia filtering not working

I have a search index with the following settings:
$index->setSettings([
'searchableAttributes' => ['title', 'datePublished'],
'attributesForFacetting' => ['filterOnly(tags)']
]);
I add objects to the index like so:
$index->addObject([
'objectID' => $object->getId(),
'title' => $object->getTitle(),
'tags' => $object->getTags(), // i.e. ['tag one (special)', 'tag two', 'tag three']
'datePublished' => $object->getDatePublished()->getTimestamp()
]);
I then conduct a search to get related items like so:
$index->search(
[
'filters' => $tags, // i.e. "tags:tag one (special)" OR "tags:tag two"
'hitsPerPage' => 12
]
);
However, this always returns 0 results, even though there are multiple records with the tags being searched for. I verified this in the Algolia dashboard. So what am I doing wrong here and how do I fix this?
Everything you're doing seems to be correct. The only issue is coming from the way you are escaping the filters in the final search() call.
Your $tags variable should be {"filters": "tags:'tag one (special)' OR tags:'tag two'"}.
The filters key should always be a string, with each filter delimited by OR/AND. When the value is a single word, you don't need any quotes, but if it has several words, you need to enclose them in '.

Zend 2 Form Validator 'InArray' - Complicated array returning invalid

I am trying to implement the 'InArray' validator in Zend 2 on a form and it keeps on returning invalid. Here is the code:
The Form Element setup:
$enquiryType = new Element\Select('enquiryType');
$enquiryType->setLabel('* What is your enquiry about?')
->setLabelAttributes(array('class' => 'sq-form-question-title'))
->setAttribute('class', 'sq-form-field required')
->setValueOptions($enquiryTypes);
The Filter/Validator setup:
$enquiryType = new Input('enquiryType');
$enquiryType->getValidatorChain()
->addByName('InArray', array('haystack' => $enquiryTypes));
And here is the array that gets passed into $enquiryTypes via the module.config.php file
'enquiryCategories' => array(
'empty_option' => 'Please select an option',
array(
'label' => 'General enquiries',
'options' => array(
'skype' => 'Skype with your library feedback',
'question' => 'Ask a question',
'feedback' => 'Library feedback',
'eresource' => 'Electronic resources (e.g. e-book, e-journal, database)',
'webbridge' => 'WebBridge Problems',
'dro' => 'DRO'
)
),
array(
'label' => 'Application to review',
'options' => array(
'10400' => 'I\'ve returned the item',
'10401' => 'I didn\'t know about overdue points but now I have some',
'10402' => 'Why did I get this invoice?',
'10403' => 'The item I borrowed is lost',
'10404' => 'The item I borrowed has been damaged',
'10405' => 'I never got/had the book',
'10406' => 'Other'
)
)
),
I have tried different variations of this (using the recursive validation also) but have not been able to work this out.
One thing that I'd try, is as follows:
$enquiryType = new Input('enquiryType');
$enquiryType->getValidatorChain()
->addByName('InArray', array('haystack' => $enquiryTypes['enquiryCategories']));
The reason I say that, is that it looks like you might be creating an array inside of the array perhaps. Unless I've misunderstood the description.
If that isn't working for you then maybe you might need to explore the Explode option as pointed out in the following question
ZF2: How do I use InArray validator to validate Multiselect form element?
Good luck.
I finally got a working solution for this. I feel there should be a better solution but I could not find one.
Here is the filter I used:
$enquiryType = new Input('enquiryType');
$enquiryType->getValidatorChain()
->addByName('InArray', array('haystack' => array_keys(
$enquiryTypes[0]['options']+$enquiryTypes[1]['options']
)));
$enquiryType->getFilterChain()
->attach(new Filter\StringToLower())
->attachByName('StripTags');
Basically I had to disect the array options into a straight associative array. As the array remains static in this instance then this works well.
If the data becomes dynamic then something more would be required (loop through and find the 'option' key, add children to filter array etc...)

How to update/replace a field in an ElasticSearch document using PHP?

I want to update my Elasticsearch indexed document's field. In my case its the tags field.
This is the code I currently have:
// Index tags in the page document
$es_client->update([
'index' => 'myappname',
'type' => 'page',
'id' => $page_id,
'body' => [
'doc' => [
'tags' => $tagsArray
]
]
]);
So, this would update my document by adding the tags array to it, but it won't remove the old tags.
How can I make sure that the old tags get removed when I add the new tags?
I did look in the documentation, but as we all know, the Elasticsearch docs can be very confusing and all-over-the-place. Hence I am asking here after days of searching.
Any help or advice would be greatly appreciated.
Standard update behavior is to merge array/object fields as explained in the update API documentation .
...objects are merged together, existing scalar fields are overwritten
and new fields are added.
So instead you would use a script to modify the document source directly. You can make it generic and thus cacheable, and pass in params for better performance. Php API documentation
// Index tags in the page document
$es_client->update([
'index' => 'myappname',
'type' => 'page',
'id' => $page_id,
'body' => [
'script' => 'ctx._source.tags=tags',
'params' => ['tags' => $tagsArray]
]
]);

Difference in array composing

I'm trying to build an array and while doing so, I was wondering if it makes any difference in how you create such array. Things I have in mind are performance, maintainability, readability,...
Declaration 1:
$data = array(
'my_array' => array(
'table' => array(
'group' => t('My group'),
'join' => array(
'commerce_product' => array(
'left_field' => 'sku',
'field' => 'artc',
),
),
);
Declaration 2:
$data['my_array']['table']['group'] = 'My group';
$data['my_array']['table']['join']['commerce_product'] = array(
'left_field' => 'sku',
'field' => 'artc',);
Because for some reason, my Drupal site accepts the first declaration but not the second. Since it's about creating arrays in PHP I don't think it has something to do with Drupal, rather with the way the array is created...
The feature of automatically creating an array with the second syntax (assigning a value to a key in a non-existent variable) is a more recent feature than using the array syntax.
Check the PHP version installed on your two servers.

Dynamically add fields to http_build_query

I have built an API that I want to test. By that reason I'm building a simple client to try out the different features (CRUD). Below is the function for updating a producer, which works fine. However, I also want to be able to update parts of a producer, e.g. address (/producers/8?method=put&address=milkyway).
The array producer always contains the same elements (name, address, zipcode etc) but I only want to update the producer with the elements in the array which contains of anything. What I mean with that is that if for example the name element in the array is empty then name shouldn't be included in *http_build_query*. If only the name element contains of anything then only name should be updated.
So, let's say that the array (except for id that of course is mandatory) contains of address. How can I dynamically add only that to *http_build_query* ?
Thanks in advance!
public function UpdateProducer($producer) {
$url = 'http://localhost/webbteknik2/Labb2/api/v1/producers/ . $producer['id'] . '?method=put';
$data = http_build_query(array(
'name' => $producer['name'],
'address' => $producer['address'],
'zipcode' => $producer['zipcode'],
'town' => $producer['town'],
'url' => $producer['url'],
'imgurl' => $producer['imgurl'],
'latitude' => $producer['latitude'],
'longitude' => $producer['longitude'],
));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
...
the rest of the curl code
}
Note: I know this is bad coding in many ways, but as I said I only, asap want to be able to test the CRUD functionality through the client.
use array_filter to remove the empty elements....
$params = array(
'name' => $producer['name'],
'address' => $producer['address'],
'zipcode' => $producer['zipcode'],
'town' => $producer['town'],
'url' => $producer['url'],
'imgurl' => $producer['imgurl'],
'latitude' => $producer['latitude'],
'longitude' => $producer['longitude'],
);
$data = http_build_query(array_filter($params, 'is_null'));

Categories