i am trying to figure out why i am not returning any data when i use json_decode. i'm trying to get values that are in a valid json file (yes, i tested it). when i try and use:
foreach($json['designs']['filters'] as $filters) {
echo $filters['filterTypeName'];
}
i am returning the values ... that's great, but i am trying to get down to the next level of the json file to pull just the values for each array under "values". here is the json file results from file_get_contents('url'):
{"designs": {
"filters" :
[
{
"filterTypeName":"Year",
"filterProperty":"year",
"values":
[
{
"name":"2018",
"value":"2018",
"sortvalue":"1"
},
{
"name":"2017",
"value":"2017",
"sortvalue":"2"
}, (etc.)
]
},
{
"filterTypeName":"Division",
"filterProperty":"division",
"values":
[
{
"name":"Resort-Apparel",
"value":"Resort-Apparel",
"sortvalue":"1"
},
{
"name":"College-Apparel",
"value":"College-Apparel",
"sortvalue":"2"
}, (etc.)
]
}, (etc.)
essentially, i have a select options on my form that checking against the values listed above to return designs that match the criteria.
how do i specifically search for all of the years in one select group, then all of the divisions in another select group and so-on?
thanks for any and all of your help!!
Try using $json->designs-> filters for accessing filters instead of $json['designs']['filters']
As the others have said, json_decode returns an object unless true is specified as the second parameters, so your options are either:
Use $json->designs->filters
or use json_decode($json, true)
i used foreach($json['designs']['filters'][0]['values'] as $name) i forgot to specify the number of the array i was trying to access.
Related
I have a JSON array of data that I am trying to extract particular value/keys(?) from, and would like to add them into a new array.
The array looks like this:
{ "total':2000,
"achievements":[
{
"id":6,
"achievement":{},
"criteria":{
"id":2050,
"is_completed":false
},
"completed_timestamp":1224053510000
},
{
"id":8,
"achievement":{},
"criteria":{
"id":1289,
"is_completed":true
},
"completed_timestamp":0000000
}
]
}
I want to search for true in the is_completed, and then add the id from that array into a new array.
Basically, find the id's of all the key/array (sorry unsure of terminology) where is_completed is true.
I've tried something simple like finding trying to find the key of an ID, but struggling to get that to work. And also seen some of the multi-level for loop examples but can't get them to work for my data.
Example:
$key = array_search('1289', array_column($array, 'id'));
As pointed out in the comments, you could combine array_filter (to filter completed events) and array_column (to extract their IDs).
$completedAchievements = array_filter(
$array->achievements,
static function (\stdClass $achievement): bool {
return $achievement->criteria->is_completed === true;
}
);
$completedAchievementsIds = array_column($completedAchievements, 'id');
print_r($completedAchievementsIds); // Array([0] => 8)
Note: the code above supposes your JSON was decoded as an object. If it was decoded as an array, just replace -> syntax with the corresponding array index access.
Demo
I'm using Laravel Form Request Validation to validate an array of objects, within each object we have two keys neverExpires and numberOfBillingCycles. Neither of these two keys are required, but if both have a value validation should fail as I only want to accept one or the other.
"addOns": {
"add": [
{
"inheritedFromId": "EMEX1",
"neverExpires": "false",
"numberOfBillingCycles": "10"
},
{
"inheritedFromId": "EX1",
"neverExpires": "true"
},
{
"inheritedFromId": "EX2"
}
]
},
So, in the first instance, because both neverExpires and numberOfBillingCycles have values it should fail validation. The second and third instances should pass as it only contains neverExpires or doesn't contain either.
I've tried creating a custom validator and passing in the two fields as parameters eg.addOns.add.*.neverExpires and addOns.add.*.numberOfBillingCycles but the problem is the parameter index is not set and I can't seem to find the array index within the custom rule to enable me to check the right array object values.
Hope this makes sense? Cheers in advance.
As long as you're using >= Laravel 5.5 you could validate the item in the add array rather than the individual attributes:
public function rules()
{
return [
'addOns.add.*' => [
function ($attr, $value, $fail) {
if (array_has($value, ['inheritedFromId', 'numberOfBillingCycles'])) {
$fail('You can not have both');
}
},
],
];
}
I have a JSON Feed which is accessed by an api.
The json feed it returns is as below:
[
{
"isoDate":"2017-09-15T00:00:00.0000000",
"events":[
{
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
},
{
"isoDate":"2017-09-16T00:00:00.0000000",
"events":[
{
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
}
]
I need the isoDate to be listed with each event instead of individually.
e.g.
[
{
"events":[
{
"isoDate":"2017-09-15T00:00:00.0000000",
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"isoDate":"2017-09-15T00:00:00.0000000",
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
},
{
"events":[
{
"isoDate":"2017-09-16T00:00:00.0000000",
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"isoDate":"2017-09-16T00:00:00.0000000",
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
}
]
Can this be achieved with php? Basically fetch that feed from a url and then display it in my preferred format?
So this is what you have to do, to get back your desired format of the json,
$json is your json string:
$eventList = json_decode($json);
foreach($eventList as $eventEntry){
$isoDate = $eventEntry->isoDate;
foreach($eventEntry->events as $subEventEntry){
$subEventEntry->isoDate = $isoDate;
}
//delete the isoDate from outer
unset($eventEntry->isoDate);
}
echo json_encode($eventList);
So basically, you are first decoding your json into php structure, apply your changes and after that, encode it back. Note here, that I have not appened true as second parameter for the $json_decode, but working with the resulting object.
Also: Your json is not standard comform and could result in errors. PHP will properly not decode it, because your object end with a comma. The last element of an object should be without comma. Instead of
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
make it like this:
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo"
}
I know, this can be a problem, when you get it from an API, but this is another problem of itself...
EDIT:
To get every "events" into one big array, you have to store them just like your imagination ;) . Think it like this: $subEventEntry holds one "events"-object. Because you are iterating both levels, you see everyone object of them. My suggestion would be to store them in a new array, and recreating the structure around it:
$everything = new stdClass();
$everything->events = array();
and then, in the inner loop:
foreach($eventList as $eventEntry){
$isoDate = $eventEntry->isoDate;
foreach($eventEntry->events as $subEventEntry){
$subEventEntry->isoDate = $isoDate;
$everything->events[] = $subEventEntry; // <-- this has to be added
}
//delete the isoDate from outer
unset($eventEntry->isoDate);
}
When recreating the structure, and you don't need the old structure anymore you could remove the unset.
Just remeber every [ ] pair in the json represents an array, every { } pair an object (stdClass). The name of this object/array is referenced -> by its class property in the superobject.
Yes you can using json_decode() function for example:
$yourjson;/* your json */
$events = json_decode($yourjson, true);
foreach($events as $event){
echo $event["isoDate"];
}
You can use json_decode to decode the json object to php array then modify the array and encode it using json_encode
I am trying to make a selection based on multiple ids in joins, each of the ids should match another condition of another join.
I need to get "Types" that have all the "Dichotomies" in "Position" 1 or 2. At the moment it gives me results that match one of the Dichotomies passed to the function, but not all of them.
$QB->select("Types","Types,ElementsPositions, Elements, Positions, Dichotomies, Quadras,TypesDescriptions,Relations")
->from($this->get_repository()[0], 'Types');
$QB->leftJoin("Types.ElementsPositions","ElementsPositions", \Doctrine\ORM\Query\Expr\Join::WITH, 'ElementsPositions.Positions = 1 OR ElementsPositions.Positions = 2');
$QB->leftJoin("ElementsPositions.Elements","Elements");
$QB->leftJoin("ElementsPositions.Positions","Positions");
$QB->leftJoin("Elements.Dichotomies","Dichotomies");
$QB->leftJoin("Types.Quadras","Quadras");
$QB->leftJoin("Types.TypesDescriptions","TypesDescriptions");
$QB->leftJoin("Types.Relations","Relations");
if(!empty($where['dichotomies'])){
foreach($where['dichotomies'] as $dichotomy){
$QB->andWhere('Dichotomies.id'.'=:dichotomy');
$QB->setParameter('dichotomy', $dichotomy['id']);
}
}
UPD.
Tables mapping - in JSON:
{
"table-name": "types",
"joins":[
{
"table-name":"elements_positions",
"type":"one-to-many"
},
{
"table-name":"quadras",
"type":"many-to-one"
},
{
"table-name":"types_descriptions",
"type":"one-to-one"
},
{
"table-name":"relations",
"type":"many-to-one"
}
]}
Elements Positions
{
"table-name": "elements_positions",
"joins":[
{
"table-name":"elements",
"type":"many-to-one"
},
{
"table-name":"positions",
"type":"many-to-one"
},
{
"table-name":"types",
"type":"many-to-one"
}
]
}
Elements
{
"table-name": "elements",
"joins":[
{
"table-name":"elements_positions",
"type":"one-to-many"
},
{
"table-name":"quadras",
"type":"many-to-many"
},
{
"table-name":"dichotomies",
"type":"many-to-many"
}
]
}
Positions
"table-name": "positions",
"joins":[
{
"table-name":"elements_positions",
"type":"one-to-many"
}
]
}
Dichotomies:
{
"table-name": "dichotomies",
"joins":[
{
"table-name":"elements",
"type":"many-to-many-inversed"
}
]
}
Your query has a two different problems.
First, multiple parameter values are bound with single parameter. Every next element of $where['dichotomies'] replaces previous value of parameter :dichotomy in the query. The method setParameters() don't really binds values to the prepared statement: it just stores them in QueryBuilder object. So, after the end of foreach-loop all conditions will be use the same value (the last of $where['dichotomies']). To avoid that you need to use different parameter names or numeric indexes.
Second, you add conditions that are contradictory: $QB->andWhere() will produce something like that:
Dichotomies.id = :dichotomy
AND Dichotomies.id = :dichotomy
AND Dichotomies.id = :dichotomy
...
One entity ID obviously cannot be equal to different values simultaneously. So, you need to replace AND by the OR operator.
But better way is to use IN clause:
Calling setParameter() automatically infers which type you are setting as value. This works for integers, arrays of strings/integers, DateTime instances and for managed entities.
Just replace the foreach-loop by the following lines:
$QB->andWhere('Dichotomies.id IN (:dichotomies)');
$QB->setParameters('dichotomies', array_column($where['dichotomies'], 'id'));
The array_column() function returns a list of IDs of all dichotomies. Doctrine generates IN expression and uses that list to generate query placeholders and bind the values.
Using jQuery 1.7.2 and jQuery UI 1.8.18. If I use local data for the source attribute, everything works as expected. According to the documentation, a source array can be an array of string values or an array of objects:
Array: An array can be used for local data. There are two supported
formats:
An array of strings: [ "Choice1", "Choice2" ]
An array of objects with label and value properties: [ { label: "Choice1", value:
"value1" }, ... ]
Additionally, the source attribute can be a URL that responds with JSON data formatted as shown above:
String: When a string is used, the Autocomplete plugin expects that
string to point to a URL resource that will return JSON data. It can
be on the same host or on a different one (must provide JSONP). The
Autocomplete plugin does not filter the results, instead a query
string is added with a term field, which the server-side script should
use for filtering the results. For example, if the source option is
set to "http://example.com" and the user types foo, a GET request
would be made to http://example.com?term=foo. The data itself can be
in the same format as the local data described above.
If my JSON responder returns a simple array of strings, autocomplete works exactly as it should. If, however, my JSON responder returns an array of objects formatted as above, the request is made to the URL but the dropdown list is never populated. The JavaScript console shows no errors.
The autocomplete invocation looks like this:
var source_url = '/json/codes.php?type=globalcode&cid=25';
$('.gcode').autocomplete({
minLength: 2,
source: source_url
});
The responder is written in PHP. It is just a stub until I get this problem solved:
header('Content-Type: application/json, charset=UTF-8');
...
if( !$_REQUEST['type'] || !$_REQUEST['cid'] ){
echo('[]');
return false;
}
if( $_REQUEST['type'] == 'globalcode' ){
$cid = sprintf("%d", $_REQUEST['cid']);
$stub = "[ { label: 'Label for 1234', value: '1234' }, { label: 'Label for 5678', value: '5678' } ]";
echo( $stub );
return false;
}
Again, it works with both kinds of arrays when the data is local and it works with an array of string values when the data is remote. When the data is a remote array of objects, the list is never populated and JavaScript throws no errors.
You have invalid JSON, this is never logged in the console.
JSON cannot have single quotes, use double quotes, also use JSONLint to check your JSON.
This is the valid version of your JSON:
[
{
"label": "Labelfor1234",
"value": "1234"
},
{
"label": "Labelfor5678",
"value": "5678"
}
]
You could use json_encode() instead
$stub = array(
array(
"label"=>"Labelfor1234",
"value"=>"1234"
),
array(
"label"=>"Labelfor5678",
"value"=>"5678"
)
);
echo json_encode($stub);