Virtual Pages, CSV, and blank rendering

I have a CSV file with about 100 rows and 8 columns. I want to create a “user” for each row. I am attempting to follow this virtual pages guide, and it seems to mostly be going OK aside from the students aren’t being listed.

content -> home -> home.txt
-> home.csv

/site/plugins/helpers/index.php

    <?php
        function csv(string $file, string $delimiter = ','): array
        {
        $lines = file($file);
    
        $lines[0] = str_replace("\xEF\xBB\xBF", '', $lines[0]);
    
         $csv = array_map(function($d) use($delimiter) {
            return str_getcsv($d, $delimiter);
             }, $lines);
    
         array_walk($csv, function(&$a) use ($csv) {
            $a = array_combine($csv[0], $a);
        });
     
        array_shift($csv);
    
        return $csv;
    }

/site/models/home.php

    <?php
    
    class StudentPage extends Page
    {
    
        public function children()
        {
            $csv      = csv($this->root() . '/home.csv', ';');
            $children = array_map(function ($student) {
                 return [
                    'slug'     => Str::slug($student['csenetid']),
                    'template' => 'home',
                    'model'    => 'home',
                    'num'      =>  $student->indexOf($students),
                    'content'  => [
                        'fname'     => $student['fname'],
                        'lname'     => $student['lname'],
                        'nickname'  => $student['nickname'],
                        'csenetid'  => $student['csenetid'],
                        'cohort_yr' => $student['cohort_yr'],
                    ]
                ];
            }, $csv);
    
            return Pages::factory($children, $this);
        }
    
    }

/site/templates/home.php

    <?php snippet('header') ?>
    
    <main>
      <h1><?= $page->title() ?></h1>
    
      <ul class="students">
        <?php foreach ($page->children() as $student): ?>
        <li>
          <a href="<?= $student->url() ?>">
            <?= $student->csenetid() ?>
          </a>
        </li>
        <?php endforeach ?>
      </ul>
    
    </main>
    
    <?php snippet('footer') ?>

/site/templates/student.php

    <?php snippet('header') ?>
    
    <article class="student">
      <h1 class="student-csenetid"><?= $page->title() ?></h1>
      <p class="student-fname">first name: <?= $page->fname() ?></p>
      <p class="student-lname">last name: <?= $page->lname() ?></p>
      <p class="student-nickname">nickname: <?= $page->nickname() ?></p>
      <p class="student-cohort_yr">cohort_yr: <?= $page->cohort_yr() ?></p>
    </article>
    
    <?php snippet('footer') ?>

I am just getting a blank home where the list of children pages should be. What do I have wrong?

If you want to create model for the home page witth a template called home, you model must also be called HomePage, not StudentPage. Note that the template and model for the children should be student not home.

1 Like

Thank you for your help!

I changed my model to:

class HomePage extends Page
{

    public function children()
    {
        $csv      = csv($this->root() . '/home.csv', ';');
        $children = array_map(function ($student) {
            return [
                'slug'     => Str::slug($student['csenetid']),
                'template' => 'student',
                'model'    => 'student',
                'num'      =>  0,
                'content'  => [
                    'fname'     => $student['fname'],
                    'lname'     => $student['lname'],
                    'nickname'  => $student['nickname'],
                    'csenetid'  => $student['csenetid'],
                    'cohort_yr' => $student['cohort_yr'],
                ]
            ];
        }, $csv);

        return Pages::factory($children, $this);
    }

}

I am still receiving a blank screen. :expressionless:

Your students don’t have a title field. Better try one of the fields you have defined in your model. Or do a

dump($page->children());

outside the loop to see if you get any results.

1 Like

I appreciate your patience. I keep trying to follow the logic to fix things, but I am not having any success.

templates/home.php

<main>
  <h1><?= $page->title() ?></h1>

  <ul class="students">
    <?php foreach ($page->children() as $student): ?>
    <li>
      <a href="<?= $student->url() ?>">
        <?= $student->csenetid() ?>
      </a>
    </li>
    <?php endforeach ?>
  </ul>

</main>

templates/student.php

<article class="student">
  <p class="student-csenetid">csenetid: <?= $page->csenetid() ?><p>
  <p class="student-fname">first name: <?= $page->fname() ?></p>
  <p class="student-lname">last name: <?= $page->lname() ?></p>
  <p class="student-nickname">nickname: <?= $page->nickname() ?></p>
  <p class="student-cohort_yr">cohort_yr: <?= $page->cohort_yr() ?></p>
</article>

Ia it the student-url()? I thought the slut item in the model home.php, but maybe not?

What do you get on the frontend home page if you put

dump($csv);

into your home.php page model directly after defining the $csv variable in the children() method?

1 Like

I tried the dump($page->children()); you suggested earlier. Thinking it very well could be my csv file isn’t being read correctly.

class HomePage extends Page
{

    public function children()
    {
        $csv      = csv($this->root() . '/home.csv', ';');
        $children = array_map(function ($student) {
            return [
                'slug'     => Str::slug($student['csenetid']),
                'template' => 'student',
                'model'    => 'student',
                'num'      =>  0,
                'content'  => [
                    'fname'     => $student['fname'],
                    'lname'     => $student['lname'],
                    'nickname'  => $student['nickname'],
                    'csenetid'  => $student['csenetid'],
                    'cohort_yr' => $student['cohort_yr'],
                ]
            ];
        }, $csv);

        dump($page->children());

        return Pages::factory($children, $this);
    }

}

I received the following error ‘Call to a member function children() on null’. To me, that says that yes the csv file is not being read right, would you agree?

You can’t use $page in this context (should be $this), as I said you should have put this in the home template, not inside the children method. What I said in my last post is to dump $csv to make sure it returns an array of items from the csv file.

My apologies for misunderstanding! On the homepage I get the following with a correct number of additional rows, edited to keep real info hidden:

Array
(
    [0] => Array
        (
            [fname,lname,nickname,csenetid,cohort_yr] => Fat,Mushroom,,fatmushroom,2019
        )

That’s what I thought, it is not the expected output. Looks like your csv file uses a comma as separator, while you tell the csv function you want to use a semi-colon.

$csv      = csv($this->root() . '/home.csv', ';');

Is debugging set to true in your config? Your model should actually throw an error.

1 Like

OMG! I tried to change that earlier, but it didn’t work so I changed it back. :rofl:

I so appreciate your help. I have the array list output, and then all the student-csenetid links.

I am sure you will see me around here often, as I am working on a project! :crossed_fingers: