Building user profile pages in Kirby 3

Hi !
I’m trying to build automatic user pages with the new Kirby.
From what I understand, they don’t come out of the box.
I tried to add a route like so:

return [
  'routes' => [
    [
      'pattern' => 'profile/(:any)',
      'action'  => function($user) {
        $site = kirby()->site(); 	
        tpl::load(kirby()->roots()->templates() . DS . 'authors.php', array('user' => $user, 'site' => $site), false);
      }
    ]
  ]
];

And I made a authors.php template that goes with it.
But all I get is a 404 error…
Any help is appreciated.
Also, I think it would make a nice addition to the cookbook.
Because I can’t believe I’m the only one trying to do that :wink:
Thank you very much!

Think you have to return the template:

return [
  'routes' => [
    [
      'pattern' => 'profile/(:any)',
      'action'  => function($user) {
        $site = kirby()->site(); 	
        return tpl::load(kirby()->roots()->templates() . DS . 'authors.php', array('user' => $user, 'site' => $site), false);
      }
    ]
  ]
];

Thanks.
I tried but still no luck.
I’m still getting an error page :frowning:

Is that a single or multi-language Kirby installation?

No it’s single language (I started from the v3 starterkit).
But I might have to switch to multi at some point…

Hm, the route works for me…

What is in your authors.php?

Just that:
<?php snippet('header') ?>
<?= $user ?>
<?php snippet('footer') ?>

Returning a template from a route was never such a great deal, actually, with having to return all the data down to the snippets (your current setup would throw errors, even if it didn’t return the 404 page). For example, if your header contains the typical

<?= $page->title() ?>

you will get an error, because the Page object doesn’t exist.

I’d create a parent /profile page and then create the children as virtual pages of that parent.

It’s weird because I remember doing something similar in Kirby2…

So what you suggest is making a ‘real’ /profile page with a dedicated blueprint and all? And then launching a virtual page like shown here (https://getkirby.com/docs/guide/routing#virtual-pages)? How would you go about passing the user id?

Once the /profile page exists, I’m thinking I could just pass the user id through a param and then use it to find the user…

Yes, that would also be an option… Instead of using the parameter, you can use the the route as before, but instead of trying to load a template, return the parent page with the user as additional data for the template.

1 Like

OK I got it to work in the end by making a ‘real’ /profile page (with blueprint, but not listed in the panel) and passing the user id as a parameter. It’s not very ‘clean’ but it does the job… (if someone decides to erase the profile page through the panel, I’m toast…)

I’d be happy to find out if there’s a better way to do it at some point. Even though routing and stuff is a bit beyond my skillset…

Thanks a lot for bearing with me and trying to find a solution…

1 Like

@texnixe there is now an easier way to display the user pages ?

You can create them as virtual children of a parent as I suggested in one of the replies above. I think that’s a better option than working with routes.

See the docs: https://getkirby.com/docs/guide/virtual-pages

Only your virtual content wouldn’t be a database or csv files, but the users.

I tried that:

config.php

  'routes' => [
          [
            'pattern' => 'mitglied/(:any)',
            'action'  => function($user) {
              $site = kirby()->site(); 	
              return tpl::load(kirby()->roots()->templates() . DS . 'member.php', array('user' => $user, 'site' => $site), false);
            }
          ]
          ],

template collection of users

<?php foreach($kirby->users()->sortBy('name','asc') as $user):
		 
			if($user->member_type() == "member"): ?>
				<article class="grid-col-30">
				<a href="mitglied/"<? echo $user->id() ?> >
					<h2><?php echo $user->member_type() ?></h2>
					<h2><?php echo $user->name() ?></h2>
				</a>
				</article>
			<?php endif ?>

		<?php endforeach ?>

and added the dir content/member

what do I have to use the correct url to display a user page?
<a href=“mitglied/”<? echo $user->id() ?> >

maybe it’s simpler (with my knowledge) to switch between user collection and singel user with JS

I suggested to use a model instead of this template stuff…

Create a members page in /content with a members.txtand then this model members.php

<?php

class MembersPage extends Page
{
  public function children()
  {
    $usersPages = [];
    $users      = kirby()->users();
    foreach ($users as $key => $user) {
      $userPages[] = [
        'slug'     => Str::slug($user->id()), // or username if unique
        'num'      => $user->indexOf($users),
        'template' => 'member',
        'model'    => 'member',
        'content'  => [
          'title'    => $user->username(),
           // more fields here
        ]
      ];
    }
    return Pages::factory($userPages, $this);

  }
}

Then you can list them in your member.php template and the children work like a normal page with their own url.

3 Likes

Thank you very much, works wonderfully.