Accessing data from a nested structure field within my HTML

Hi, I’m pretty stuck.

My desired functionality is an amazon-like question-and-answer section. I want users to be able to submit questions about a product via a <form> in the front end. I also want users to be able to submit answers to questions asked by other users, allowing multiple answers per question. I don’t want these to display automatically. I need to moderate them, and want to toggle them into view via the panel. This is why I have a ‘live’ field which must be explicitly set to “yes” in order for the questions and answers to display.

I am thinking the best way to do this is via a nested structure within my .yml file that looks like this:

fields:
  questions:
    type: structure
    fields:
      question:
        label: question
        type: text
      user:
        label: user
        type: text
      date:
        label: date
        type: text
      live:
        label: live
        type: radio
        options:
          yes: yes
          no: no
      answers:
        type: structure
        fields:
          answerer:
            type: text 
          answer: 
            type: text
          live:
            type: radio
            options:
              yes: yes
              no: no

Here is the code I use to retrieve the information from the <form> submit, and write it to the .txt file:

<?php $questionData = [
           'user'  => get('user'),
           'question'  => get('question'),
           'date' => get('date'),
           'answer' => get('answer'),
           'answerer' => get('answerer')
];

function addToQuestionStructure($page, $field, $questionData = array()){
               $fieldData = page($page)->$field()->yaml();
               $fieldData[] = $questionData;
               $fieldData = yaml::encode($fieldData);
               try {
                  page($page)->update(array($field => $fieldData));
               } catch(Exception $e) {
                  return $e->getMessage();
               }
            }
            if (isset($_POST['question'])) {
            addToQuestionStructure($page, 'questions', [
               'user' => esc($questionData['user']),
               'question'   => esc($questionData['question']),
               'date' => esc($questionData['date']),
               'answer' => esc($questionData['answer']),
               'answerer' => esc($questionData['answerer']),
            ]);
            }
   ?>

This is the code I am using to output the .txt data to my HTML.

              <?php $questions = $page->questions()->toStructure(); ?>
              <?php $liveCounter = 0 ?>
              <?php if ($questions->isNotEmpty()): ?>
                <?php foreach ($questions as $item): ?>
                  <!--this field allows me to toggle questions in and out of view-->
                  <?php if($item->live() == 'yes'): ?>
                    <?php $liveCounter = $liveCounter + 1 ?>
                    <div class='col-xs-12' style='margin-top:60px'>
                      <div class='review-top-container'>
                        <div class='review-container'>
                          <span class='review-title'><?= $item->question() ?></span>
                          <p class='review-author'><?= $item->user() ?></p>
                          <p class='review-body'><?= $item->date()?></p>
                          <hr class='border02'>
                        </div>
                      </div><br>
                    </div>
                    <br><br><br><br><br><br><br><br><br><br>
                    <?php if ($item->answers()->isNotEmpty()): ?>
                      <!--if the answers field is not empty, we want to display them-->
                      <?php foreach ($item->answers() as $test): ?>
                        <?php var_dump($test) ?>
                      <?php endforeach ?>
                    <?php elseif ($item->answers()->isEmpty()): ?>
                      <?php echo "nope" ?>
                    <?php endif ?>
                  <?php endif ?>
                <?php endforeach ?>
              <?php endif ?>

              <?php if ($liveCounter == 0): ?>
                <p style="color:white;">No questions yet. Ask the first one dawg!</p>
              <?php endif ?>

I believe I am targeting it correctly because var_dump() relays the correct information, except it is in an array within another array.

array(1) { [0]=> array(3) { ["answerer"]=> string(4) "Andy" ["answer"]=> string(69) "It holds up quite well. I have been using mine in the rain for years." ["live"]=> string(3) "yes" } }

However, when I try to go and target specific fields with the syntax I can use to target the question using the following syntax

 <?php if ($item->answers()->isNotEmpty()): ?>
     <?php foreach ($item->answers() as $test): ?>
          <?php $test->answer() ?>
      <?php endforeach ?>
 <?php endif ?>

I get the error:

Call to a member function answer() on array

I was thinking the problem may be in my addToQuestionStructure function. Maybe I need to create another function references the ‘answers’ sub field more directly, instead of referring to the ‘questions’ field?

I noticed the documentation briefly mentioned nested structures, saying:

If you nest structure fields inside a structure field, you have to call the toStructure() method on the nested fields as well and then loop through the nested items like above.

This might be my problem, because I haven’t called toStructure() twice, but don’t know what it looks like to ‘call the method on the nested fields’ but I can’t find any examples of the nested structures, and thus can’t figure out the correct syntax to get them working.

In summary, I want to be able to access the data from the answers structure that is a feild of my questions structure, with a syntax somewhat like the following: <?= $item->answerer() ?>

I hope my question is clear, and that this is possible. Please let me know if you need any clarification. Thank you.

Since answers is another structure field, you have to convert this into a structure object again:

<?php foreach ($item->answers()->toStructure() as $test): ?>
<?php echo $test->answerer() ?>
<?php endforeach ?>
1 Like

Thanks, it was indeed a simple fix. I appreciate the help.