prismicio-community / php-kit

Community maintained development kit for Prismic and the PHP language
https://prismic.io
Other
109 stars 83 forks source link

custom data type predicates? #203

Closed diemildefreude closed 7 months ago

diemildefreude commented 7 months ago

I have two custom types, archive and event. Archive has event as a field. I want to group the archives by event. I was thinking of making a separate query for each event name, something like

$eventQ = $api->query
                        (
                            Predicates::at('my.archive.event', 'otosata'), //get archives that have the event of the name 'otosata'
                            [ 'pageSize' => 100, 'orderings' => '[my.event.date desc]']
                        );

but this doesn't work... maybe because the custom type is too complex? As you can see below, I have to type results[$i]->data->event->uid to get the archive's event id. The solution below works in a really ugly way by using php for loops and arrays to compare strings and group them into separate arrays, but it's a bit cumbersome. And I still have to add a check to not make a section for an event that has no archives.

<?php 
                        $eventQ = $api->query
                        (
                            Predicates::at('document.type', 'event'),
                            [ 'pageSize' => 100, 'orderings' => '[my.event.date desc]']
                        );
                        $archiveQ = $api->query
                        (
                            Predicates::at('document.type', 'archive'),
                            [ 'pageSize' => 100, 'orderings' => '[my.archive.date desc]']
                        );

                        $eventSecs = array();
                        for($i = 0; $i < sizeof($eventQ->results); ++$i)
                        {
                            $e = array();
                            array_push($eventSecs, $e);
                        }
                        echo 'event count: ' . sizeof($eventQ->results) . '<br>';
                        for($i = 0 ; $i < sizeof($archiveQ->results); ++$i)
                        {
                            for($j = 0; $j < sizeof($eventQ->results); ++$j)
                            {
                                if($archiveQ->results[$i]->data->event->uid 
                                == $eventQ->results[$j]->uid)
                                {
                                    array_push($eventSecs[$j], $archiveQ->results[$i]);
                                }
                            }
                        }
                    echo 'testA: ' . $eventQ->results[2]->data->name . '<br>';
                    echo 'testB: ' . $eventSecs[2][0]->data->title . '<br>';
c0nst4ntin commented 7 months ago

Hello @diemildefreude 👋🏼 I am sorry to hear about your Problems with the API. At this point, it is quite hard for me to tell, how your custom types are set up, and what you store in the event field on your Archive objects.

If you can rephrase the Question in a more language-agnostic way, somebody in the Forum who is more experienced with the API than me might be able to help you: https://community.prismic.io/

Based on what I was able to find there, you can query the relationship by ID but not by any other field: https://community.prismic.io/t/content-relationship-predicates-matching-a-specific-value/9592

If this does not work for you, maybe you can simplify your code by using array_filter()? Here is an example with some faked data:

<?php

// Define array to provide fake data
$archiveQuery = ["results" => [
        ["data" => ["name" => "archive_1_name", "event" => ["name" => "event_1_name"]]],
        ["data" => ["name" => "archive_2_name", "event" => ["name" => "event_2_name"]]],
        ["data" => ["name" => "archive_3_name", "event" => ["name" => "event_1_name"]]]
    ]
];

// Convert array to object (to mimic the response)
$archiveQuery = json_decode(json_encode($archiveQuery));

// Archives where the name is "event_1_name"
$results = \array_filter($archiveQuery->results, function($archive){
    return $archive->data->event->name === 'event_1_name';
});

var_dump($results);

Did this help you or at least answer your question?

diemildefreude commented 7 months ago

Hi @c0nst4ntin , thanks for your reply. I tried using your syntax as it seems a bit shorter, but am experiencing a strange bug as shown in the comments at the bottom of the code:

$eventSecs = array();
                            for($i = 0; $i < sizeof($eventQ->results); ++$i)
                            {
                                $eUid = $eventQ->results[$i]->uid;

                                $filtered = \array_filter($archiveQ->results, function($archive) use ($eUid)
                                {
                                    return $archive->data->event->uid === $eUid;
                                });
                                array_push($eventSecs, $filtered);
                            }
                            echo 'sec0 size: ' . sizeof($eventSecs[0]) . '<br>';  // sec0 size: 4                        
                            echo 'TEST: ' . $eventSecs[0][0]->data->featured_image->url . '<br>'; // [the correct url]
                            echo 'sec2 size: ' . sizeof($eventSecs[2]) . '<br>'; //sec2 size: 6
                            echo 'TEST: ' . $eventSecs[2][0]->data->featured_image->url . '<br>'; //Warning: Undefined array key 0 in C:\xampp\htdocs\website\hamtama\archiveList.php on line 62

Not sure what I did but only the info is being read correctly when using the filter method.... it feels like I've probably made a syntax error somewhere (I'm new to using array_filter) but I don't see it and I don't know why an array of size 6 would have an undefined array key 0.

c0nst4ntin commented 7 months ago

This comes from using array_filter() per definition "Array keys are preserved, and may result in gaps if the array was indexed."

In my example the count($results) is equal to 2 but the array looks something like this [0 => [...], 2 => [...]] So even though there are two elements in the array, the indices do not need to be consecutive.

This can be avoided by wrapping the statement in array_values() (documentation)

Feel free to let me know if this helped you. In that case, I would proceed to close this Issue.

diemildefreude commented 7 months ago

Thank you, c0nst4ntin. Yes, you can go ahead and close it.