Hm, the route works for me…
What is in your authors.php?
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.
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…
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.txt
and 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.
Thank you very much, works wonderfully.
Hello,
I used the same principle and it works well for simple fields.
I can’t display a structure correctly.
I have an error:
Invalid structure data for "user" field on parent
How did you add the structure to your content array? Please post your code!
Hello,
I think I don’t know how to add the structure to the models members.php
My structure field is: social_events_listing
(and to make it more complex, I have a substructure).
<?php
class MembersPage extends Page
{
public function children()
{
$usersPages = [];
$users = kirby()->users();
foreach ($users as $key => $user) {
$userPages[] = [
'slug' => Str::slug($user->firstname() ." ". $user->namefamily()), // or username if unique
'num' => $user->indexOf($users),
'template' => 'member',
'model' => 'member',
'content' => [
'user' => $user,
'name' => $user->name(),
'title' => $user->firstname() ." ". $user->namefamily(),
'firstname' => $user->firstname(),
'namefamily' => $user->namefamily(),
'member' => $user->member(),
'sex' => $user->sex(),
'birthday' => $user->birthday(),
'street' => $user->street(),
'zip' => $user->zip(),
'city' => $user->city(),
'country' => $user->country(),
'phone' => $user->phone(),
'phonemobile' => $user->phonemobile(),
'licence_date' => $user->licence_date(),
'size' => $user->size(),
'weight' => $user->weight(),
'bio' => $user->bio(),
'url_strava' => $user->url_strava(),
'photo' => $user->file(),
'social_events_listing' => $user->social_events_listing(),
//'social_events_date' => $user->social_events_date(),
// more fields here
]
];
}
return Pages::factory($userPages, $this);
}
}
At the beginning I displayed all the data on a page which lists all the members with photo.
We click on the photo to display a modal with all the information.
But I preferred to create a page for each user.
Here is the part with the structure and substructure that works.
I thought it was enough to copy the same model and change something at first, but I don’t know how.
<?php if ($user->social_events_listing()->length() > 0): ?>
<h4 id="scrollspyHeading2-membre-<?= mb_strtolower(str_replace(' ', '', $user->name())) ?>">Participation
</h4>
<div class="accordion accordion-flush mb-5" id="accordionFlushExample">
<?php
$items = $user->social_events_listing()->toStructure()->flip();
foreach ($items as $item):
?>
<div class="accordion-item ps-0">
<h2 class="accordion-header" id="flush-headingOne">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target="#flush-collapse-<?= $item->id(); ?>" aria-expanded="false"
aria-controls="flush-collapseOne">
<b>Année <?php echo $item->social_events_date() ?></b>
</button>
</h2>
<div id="flush-collapse-<?= $item->id(); ?>" class="accordion-collapse collapse"
aria-labelledby="flush-headingOne" data-bs-parent="#accordionFlushExample">
<div class="accordion-body">
<div class="alert alert-light" role="alert">
<?= $item->social_events_description()->kirbytext() ?>
</div>
<div class="card">
<ul class="list-group list-group-flush">
<?php
//Sous-liste
$listings = $item->social_events_listing2()->toStructure();
foreach($listings as $listing):
?>
<li class="list-group-item">
<div class="row">
<div class="col-6">
<h3><?= $listing->social_events_listing2_title(); ?></h3>
</div>
<div class="col-6 ms-auto text-end">
<div class="d-none d-lg-inline-flex tag">
<span class="badge bg-light text-primary mx-1"><i class="far fa-calendar-alt"></i>
<?= $listing->social_events_listing2_date()->toDate('%A %e %B %Y'); ?></span>
<span class="badge bg-light text-primary mx-1"><i class="fas fa-map-marker-alt"></i>
<?= $listing->social_events_listing2_city(); ?></span>
</div>
</div>
<div class="col-12 fst-italic">
<?= $listing->social_events_listing2_text()->kirbytext(); ?>
</div>
<div class="col-12">
<!-- Actualités ou Séjours en relation -->
<?php foreach($listing->social_events_listing2_related()->toPages() as $storierelated): ?>
<a class="btn btn-secondary text-start" href="<?= $storierelated->url() ?>">Lire
<?= lcfirst($storierelated->title()) ?> <i class="fa-solid fa-chevron-right"></i></a>
<?php endforeach ?>
<!-- ./Actualités ou Séjours en relation -->
</div>
</div>
</li>
<?php endforeach ?>
</ul>
</div>
</div>
</div>
</div>
<?php endforeach ?>
</div>
<?php endif ?>
If it can help. This is what the file looks like: blueprints/users/client.yml
title: Membre
# Set page where you want to redirect the user to after login
#home: /
permissions:
access:
panel: false
tabs:
profil:
label: Mon profil
icon: text
columns:
- width: 1/3
sections:
downloads:
headline:
label: Photo
type: files
layout: cards
info: "{{ file.caption }}"
image:
ratio: 3/4
max: 1 #maximum 1
- width: 2/3
# Kirby has many different field types, from simple text fields to the more complex structure field that contains subfields
# All available field types: https://getkirby.com/docs/reference/panel/fields
fields:
firstname:
label: Prénom
type: text
width: 1/2
namefamily:
label: Nom
type: text
width: 1/2
member:
label: Membre du bureau (facultatif)
type: text
placeholder: Président, Secrétaire, Trésorier ...
width: 1/1
sex:
label: Sexe
type: select
default: sex_default
options:
sex_default: non défini
sex_man: homme
sex_woman: femme
width: 1/2
birthday:
label: Date de naissance
type: date
display: DD/MM/YYYY
width: 1/2
contactdetails:
label: Coordonnées
icon: text
sections:
contactdetails:
type: fields
fields:
street:
label: Adresse
type: text
zip:
label: Code postal
type: tel
icon: none
width: 1/4
city:
label: Ville
type: text
width: 3/4
country:
label: Pays
type: text
default: France
placeholder: France
phone:
label: Téléphone
type: tel
icon: phone
maxlength: 10
width: 1/4
phonemobile:
label: Téléphone portable
type: tel
icon: mobile
maxlength: 10
width: 1/4
licence:
label: Ma licence
icon: text
sections:
licence:
type: fields
fields:
licence_number:
label: Numéro de licence
type: tel
icon: account
width: 1/2
licence_date:
label: Date d'entrée au club
type: date
display: DD/MM/YYYY
width: 1/2
athlete:
label: L'athlète
icon: text
sections:
athlete:
type: fields
fields:
size:
label: Taille
type: number
after: cm
width: 1/4
weight:
label: Poids
type: number
after: kg
width: 1/4
bio:
label: Bio
type: textarea
width: 1/1
social:
label: Suivez-moi !
icon: text
sections:
social:
type: fields
fields:
url_strava:
label: Lien Strava
type: url
width: 1/2
# social_events:
# label: Suivez-moi sur un événement
# type: textarea
# width: 1/1
social_events_listing:
label: Historique
type: structure
fields:
social_events_date:
label: Date
type: number
max: 2050
width: 1/2
social_events_description:
label: Description
type: textarea
width: 1/1
social_events_listing2:
label: Sous-texte(s)
type: structure
fields:
social_events_listing2_title:
label: Titre
type: text
width: 1/1
social_events_listing2_date:
label: Date
type: date
display: D MMMM YYYY
width: 1/2
social_events_listing2_city:
label: Ville
type: text
size: small
width: 1/2
social_events_listing2_text:
label: Texte
type: textarea
size: small
width: 1/1
social_events_listing2_related:
label: Lien(s)
type: pages
query: site.find('sejours', 'actualites')
multiple: true
You need to convert the structure to an array:
'social_events_listing' => $user->social_events_listing()->toStructure()->toArray(),
should do the job.
Thanks @texnixe
I had tried something like that.
In any case when I do a var_dump the info is better!
This is what I get when I do:
array(3) {
[0]=>
array(4) {
["id"]=>
string(1) "0"
["social_events_date"]=>
int(2021)
["social_events_description"]=>
string(73) "Après avoir roulé depuis 2017 seul, je découvre le club."
["social_events_listing2"]=>
array(1) {
[0]=>
array(5) {
["social_events_listing2_title"]=>
string(21) "Adhésion au club ACM"
["social_events_listing2_date"]=>
string(10) "2021-06-11"
["social_events_listing2_city"]=>
string(26) "City"
["social_events_listing2_text"]=>
string(0) ""
["social_events_listing2_related"]=>
array(0) {
}
}
}
}
[1]=>
.... and more
}
In my template I have the foreach loop but when I do for example $item->social_events_date()
<?php
$items = $page->social_events_listing();
foreach ($items as $item):
?>
Error
Call to a member function social_events_date() on array
This is missing the toStructure field method!
Exactly !
Thanks a lot
$items = $page->social_events_listing()->toStructure()->flip();
Getting back to the model.
I recovered the slug to be able to make a link in my pages of the members.
I would like to know if my url is well optimized?
<a href="membres/<?= Str::slug($user->firstname() ." ". $user->namefamily()) ?>"><?= $user->firstname() ?> <?= $user->namefamily() ?></a></div>
the url of my page is of this type:
http://localhost/website.fr/starterkit-master/club/membres/mickael-durand
other solution:
<a href="<?= $site->url() ?>/club/membres/<?= Str::slug($user->firstname() ." ". $user->namefamily()) ?>"><?= $user->firstname() ?> <?= $user->namefamily() ?></a></div>
Can we do better to avoid having to write /club/members
?
I’m missing a bit of context here. Why do you want to create these links manually? All the subpage have a normal URL now.
foreach (page('membres')->children() as $member) {
echo $member->url();
}
Or if you want to fetch a particular memberpage
if ($member = page('membres')->children()->findBy('slug', 'john-doe')) {
echo $member->url();
}
Don’t know if that answers your question, otherwise maybe rephrase your question and provide more context. Thanks!