0

I am very new to php and basically dont know what i'm doing. So I hope my problem has an easy solution.

Im trying to build a subpage on my website where I display and link to other cities on my website, and that entire subpage is supposed to be ordered by states. So all cities in state "x" will be bundled together, and all cities in state "y" and so on.

I am reading out a JSON file that is structured like this :

[{"id":"AA0","name":"Aalen","region":"Süden","state":"Baden-Württemberg","residents":"Aalener"},
{"id":"AB0","name":"Aschaffenburg","region":"Mitte","state":"Bayern","residents":"Aschaffenburger"},
{"id":"AC0","name":"Aachen","region":"Westen","state":"Nordrhein-Westfalen","residents":"Aachener"},
{"id":"B00","name":"Berlin","region":"Osten","state":"Brandenburg","residents":"Berliner"},
{"id":"BA0","name":"Bamberg","region":"Süden","state":"Bayern","residents":"Bamberger"},
{"id":"BB0","name":"Sindelfingen","region":"Süden","state":"Baden-Württemberg","residents":"Sindelfingener"},
{"id":"BI0","name":"Bielefeld","region":"Westen","state":"Nordrhein-Westfalen","residents":"Bielefelder"}]

My logic is supposed to be handled by a controller - this is what I got so far (and its not much, i tried a few things but nothing worked)

controller:

public function states() {
        $json = file_get_contents('https://api.cms.diebestenderstadt.de/cities/v1/');

        $data = json_decode($json, true);

foreach ($data as $result) {
                    if ($result['state'] == 'Sachsen')
                        echo($result['name'] . ", ");
                    elseif ($result['state'] == 'Nordrhein-Westfalen')
                        echo($result['name'] . ", ");
                    elseif ($result['state'] == 'Baden-Württemberg')
                        echo($result['name'] . ", ");
                    elseif ($result['state'] == 'Bayern')
                        echo($result['name'] . ", ");

return view("index.states")->with("states", $data);

In this way, I at least managed to only display all cities of a certain state, but now im lost as how to go on and how to "save" that state-filtered response for later.

I hope I provided all the info you need, the states subpage so far only really has some dummy code that wont help showing off.

If there is more info you need, please let me know and thanks in advance for your help.

ItsRay
  • 25
  • 4
  • Replace the `echo` line with `$x = $result['name'] ;` to store in a variable. But surely that's not your real question?(And it would be overwritten in each loop anyway). What do you actually want to achieve, really? Are you wanting to create a new JSON structure, or something? – ADyson Oct 18 '22 at 14:17
  • What **exactly** did you try? – Nico Haase Oct 18 '22 at 14:17
  • `Ive tried a few ways but I can't get it to work.`...can't help you much if you don't show your attempt, or explain the problem, or give a clear indication of what the final result should be. See also [ask]. – ADyson Oct 18 '22 at 14:18
  • I have updated my question to be more clear as to what im trying to accomplish – ItsRay Oct 19 '22 at 09:00
  • I see (I think!). If you want to save data for later, you can put it into the Session (if it only needs to be saved temporarily, for one user during their current visit to your site), or into a file or database (if it needs to be saved for longer, or shared between users). That way it will be available again in subsequent requests to your PHP code. So then, you could check the relevant storage area to see if a (recent?) saved value exists, before making another request to the external API. (I'm assuming the goal is to avoid having to repeatedly call the API and filter the data?) – ADyson Oct 19 '22 at 09:12
  • 1
    P.S. As an aside, why are you returning a view _and_ using `echo` in your controller action? If you're using an MVC framework here, `echo`ing in the controller function breaks one of the fundamental principles of that architecture. You're supposed to return data to the view, and let the view handle all the outputting. – ADyson Oct 19 '22 at 09:30
  • The echo was pretty much just testing, nothing that was supposed to stay. The JSON is going to update and all new entries should immidiately be visible on the state-subpage. The reason for why am I trying to create this subpage is basically for internal links on the website. When i was saying that i wanted to "save that data for later" I was more talking about being able to creating a dynamic variable (i guess?) for each state which will then be displayed on the subpage in form of links to these other cities - ordered by states. – ItsRay Oct 19 '22 at 09:40
  • Ok. That isn't what I thought you meant at all, sorry! It sounds like your first job then is to sort `$data` into order by state. Then you could pass that sorted data structure to your view, which can then output some links. Is that what you want? Demo of sorting: https://3v4l.org/oTvjH (with gratitude to https://stackoverflow.com/questions/2699086/how-to-sort-a-multi-dimensional-array-by-value and https://stackoverflow.com/questions/17364127/how-can-i-sort-arrays-and-data-in-php). – ADyson Oct 19 '22 at 09:52
  • What i really need is "splitting" the $data by each state, so each list of cities for a state can be exported/used seperately. Sorry for being so unclear and thanks for everything. – ItsRay Oct 19 '22 at 10:28
  • Ah so you want to group the data into separate lists by state? Something like this, maybe: https://3v4l.org/jsJGk ? (with credit to https://stackoverflow.com/questions/2189626/how-to-group-a-multidimensional-array-by-a-particular-subarray-value and others). – ADyson Oct 19 '22 at 10:59
  • 1
    @ItsRay As far as your question of how to store this type of data, I would using a caching mechanism and hold onto it for some time (weeks/months/up to a year?), depending on how frequently you anticipate needing to update it. You're probably using Laravel, [which has a caching layer](https://laravel.com/docs/9.x/cache). – Jared Farrish Oct 19 '22 at 11:35

2 Answers2

1

Here's some demonstrations of using array map/reduce/filter functions to take an array and transform it towards different ends. What you're trying to do would most likely fit into one of these forms.

(There's a link below the code to review what these produce.)

$townsJson = <<<JSON
[{"id":"AA0","name":"Aalen","region":"Süden","state":"Baden-Württemberg"},
{"id":"AB0","name":"Aschaffenburg","region":"Mitte","state":"Bayern"},
{"id":"AC0","name":"Aachen","region":"Westen","state":"Nordrhein-Westfalen"},
{"id":"WIT","name":"Witten","region":"Westen","state":"Nordrhein-Westfalen"},
{"id":"DN0","name":"Düren","region":"Westen","state":"Nordrhein-Westfalen"}]
JSON;

$towns = json_decode($townsJson, true);

// Add a description to each entry, e.g. map to each entry.
$towns = array_map(function(array $town) {
    $town['description'] = sprintf(
        '%s is a town in %s (%s).',
        $town['name'],
        $town['state'],
        $town['region']
    );
    
    return $town;
}, $towns);

// Filter the towns and only return those that start with A.
$ATowns = array_filter(
    $towns,
    fn(array $town) => strpos($town['name'], 'A') === 0
);

// Organize the array into regions. 
$townsByRegion = array_reduce($towns, function(array $found, array $town) {
    $found[$town['region']][] = $town;
    
    return $found;
}, []);

https://3v4l.org/HZJpG


Update

What it sounds like you want is to populate an additional key that combines other keys (a mapping operation, e.g. array_map()), and then to produce a new array with keys that group cities by state (a reduction that produces a wholly new data concept, e.g., array_reduce()).

$citiesJson = <<<JSON
[{"id":"AA0","name":"Aalen","region":"Süden","state":"Baden-Württemberg"},
{"id":"AB0","name":"Aschaffenburg","region":"Mitte","state":"Bayern"},
{"id":"AC0","name":"Aachen","region":"Westen","state":"Nordrhein-Westfalen"},
{"id":"WIT","name":"Witten","region":"Westen","state":"Nordrhein-Westfalen"},
{"id":"DN0","name":"Düren","region":"Westen","state":"Nordrhein-Westfalen"}]
JSON;

$cities = json_decode($citiesJson, true);

$cities = array_map(function(array $city) {
    $city['city_region_state'] = sprintf(
        '%s, %s, %s',
        $city['name'],
        $city['region'],
        $city['state']
    );
    
    return $city;
}, $cities);

$citiesByState = array_reduce($cities, function(array $found, array $city) {
    $found[$city['state']][] = $city;
    
    return $found;
}, []);

https://3v4l.org/skMWu

This produces:

{
    "Baden-W\u00fcrttemberg": [
        {
            "id": "AA0",
            "name": "Aalen",
            "region": "S\u00fcden",
            "state": "Baden-W\u00fcrttemberg",
            "city_region_state": "Aalen, S\u00fcden, Baden-W\u00fcrttemberg"
        }
    ],
    "Bayern": [
        {
            "id": "AB0",
            "name": "Aschaffenburg",
            "region": "Mitte",
            "state": "Bayern",
            "city_region_state": "Aschaffenburg, Mitte, Bayern"
        }
    ],
    "Nordrhein-Westfalen": [
        {
            "id": "AC0",
            "name": "Aachen",
            "region": "Westen",
            "state": "Nordrhein-Westfalen",
            "city_region_state": "Aachen, Westen, Nordrhein-Westfalen"
        },
        {
            "id": "WIT",
            "name": "Witten",
            "region": "Westen",
            "state": "Nordrhein-Westfalen",
            "city_region_state": "Witten, Westen, Nordrhein-Westfalen"
        },
        {
            "id": "DN0",
            "name": "D\u00fcren",
            "region": "Westen",
            "state": "Nordrhein-Westfalen",
            "city_region_state": "D\u00fcren, Westen, Nordrhein-Westfalen"
        }
    ]
}
Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
0

Check this

$data = json_decode($json, true);
$variable = [];
foreach ($data as $result)
   if ($result['state'] == 'Nordrhein-Westfalen')
      $variable[] = $result['name'];

or you can try with array_filter

$variable = array_filter($data, function($item) {
  return $item['state'] == 'Nordrhein-Westfalen';
});
Kamil
  • 31
  • 2
  • 7
  • ...because? You don't know what output or structure the OP actually wants (because the question is unclear). And you should always explain your answer, not just dump some code. – ADyson Oct 18 '22 at 14:27
  • I mean, since my question was so unclear I guess I deserve an unclear answer, so thats fine. Ill try to update my question with more information, I was just a little bit embarrassed because it seems to be such an easy problem – ItsRay Oct 18 '22 at 14:30
  • I have updated my question to be more clear as to what im trying to accomplish – ItsRay Oct 19 '22 at 09:00