Posted 16th Dec 2017
#api #bootstrap4 #completeguide #fields #selector #urlsegments
So our page works for the segments we do want to use i.e.'/cats/burmese/' or /cats/tabby/'. But we need to show a 404 for invalid segments i.e. '/cats/wrong/' and '/cats/something-else/'.
Invaild would firstly be if there was a second URL segment which we can check for.
if ($input->urlSegment2) {
throw new Wire404Exception();
}
If there is a URL segment 1, we need to check if the URL segment string matches a page that exists under '/type/', if so, concatenate a new part to the selector, and if not, show a 404 page.
// get URL segment 1
$segment1 = $input->urlSegment1;
// if there is a URL segment 1
if ($segment1) {
// get cat type page - thanks to PW forum member Robin S
$catType = $pages->findOne("parent=/type/, name=$segment1");
// if cat type page exists
if ($catType->id) {
// add this to the selector
$selector .= ", catType=$segment1";
}
else {
// invalid URL segment 1
throw new Wire404Exception();
}
}
Once these checks have been done, we can loop over the results.
// find the pages based on our selector
$catPages = $pages->find($selector);
foreach ($catPages as $catPage):
And we could add a little menu to make finding the cats easier.
<div class="row">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="/cats/">Show all</a>
</li>
<?php
$catTypes = $pages->get("/type/")->children;
foreach ($catTypes as $catType):
?>
<li class="nav-item">
<a class="nav-link" href='<?php echo "/cats/{$catType->name}/"; ?>' ?>
<?php echo $catType->title; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
For completeness, here's the code for the entire template.
<?php namespace ProcessWire; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><?php echo $page->title; ?></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
</head>
<body>
<header>
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-3"><?php echo $page->title; ?></h1>
</div>
</div>
</header>
<div class="container">
<div class="row">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="/cats/">Show all</a>
</li>
<?php
$catTypes = $pages->get("/type/")->children;
foreach ($catTypes as $catType):
?>
<li class="nav-item">
<a class="nav-link" href='<?php echo "/cats/{$catType->name}/"; ?>' ?>
<?php echo $catType->title; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<div class="row py-5">
<?php
// only 1 URL segment should be allowed
if ($input->urlSegment2) {
throw new Wire404Exception();
}
// create a string that will be our selector
$selector = "template=cat-entry";
// get URL segment 1
$segment1 = $input->urlSegment1;
// if there is a URL segment 1
if ($segment1) {
// get cat type page
$catType = $pages->findOne("parent=/type/, name=$segment1");
// if cat type page exists
if ($catType->id) {
// add this to the selector
$selector .= ", catType=$segment1";
}
else {
// invalid URL segment 1
throw new Wire404Exception();
}
}
// find the pages based on our selector
$catPages = $pages->find($selector);
foreach ($catPages as $catPage):
?>
<div class="col-md-4 pb-3">
<div class="card">
<?php
// if the page object has a featured image
if ($catPage->featuredImage):
// https://processwire.com/api/fieldtypes/images/
// set some default image options
$options = array('quality' => 80, 'cropping' => 'center');
// create a new image on the fly 800px wide
$img = $catPage->featuredImage->width(400, $options);
// get the url to the image
$imgUrl = $img->url;
// get the description field
$imgDesc = $img->description;
?>
<a href="<?php echo $catPage->url; ?>">
<img src="<?php echo $imgUrl; ?>" alt="<?php echo $imgDesc; ?>" class="img-fluid card-img-top" />
</a>
<?php endif; ?>
<div class="card-body">
<h4 class="card-title">
<a href="<?php echo $catPage->url; ?>"><?php echo $catPage->title; ?></a>
</h4>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</body>
</html>
Try it out, add a few new cat pages and types. Try a few URLs, try and break it, try a second URL segment to see what happens. Extend this to have not only type but to have colour, or age, or whatever. What about '/cats/under-5/' where you could use an age field on the 'cat-entry' template, get the URL segment and use it to work out which age bracket cats to show.
Start thinking like this and your curiosity will lead to learning! Have fun :)