Skip to content

Commit a81438f

Browse files
authored
Merge pull request #207 from codeigniter4projects/view-objects
View Heroes and Dungeons
2 parents 3a7ec1e + b850228 commit a81438f

23 files changed

+312
-43
lines changed

README.md

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Playground
2+
23
A space to learn and experience CodeIgniter 4
34

45
[![](https://github.com/codeigniter4projects/playground/workflows/PHPUnit/badge.svg)](https://github.com/codeigniter4projects/playground/actions/workflows/test.yml)
@@ -8,78 +9,84 @@ A space to learn and experience CodeIgniter 4
89

910
This playground is here to help you learn CodeIgniter 4 by example. We try to cover use cases for the most
1011
common tasks you'll find yourself doing in web applications. Where there are multiple ways to do something,
11-
we've tried to give examples of doing things in each way.
12+
we've tried to give examples of doing things in each way.
1213

1314
This isn't meant to replace [the docs](https://codeigniter4.github.io/CodeIgniter4/index.html). This is just
14-
something to look at to get a deeper understanding, or to better see how something could be done in practice.
15+
something to look at to get a deeper understanding, or to better see how something could be done in practice.
1516

1617
## Resources
1718

18-
There are two primary ways to learn about what's going on here in the Playground. The first is the code itself.
19-
We've heaped a LOT of comments throughout the code. They're your best docs. So explore them in depth.
20-
Additionally, there's a small collection of docs in the conveniently named [docs](docs) folder.
19+
There are two primary ways to learn about what's going on here in the Playground. The first is the code itself.
20+
We've heaped a LOT of comments throughout the code. They're your best docs. So explore them in depth.
21+
Additionally, there's a small collection of docs in the conveniently named [docs](docs) folder.
2122

22-
To setup a working playground on your own local device, read through the next section.
23+
To setup a working playground on your own local device, read through the next section.
2324

24-
## Getting Started
25+
## Getting Started
2526

2627
In order to get the playground setup on your own computer, you'll need a few minimum requirements - all of which
2728
are listed on [CodeIgniter's repo](https://github.com/codeigniter4/CodeIgniter4#server-requirements). Basically,
28-
as long as you are running PHP 7.2 or later you'll meet most of them.
29+
as long as you are running PHP 7.2 or later you'll meet most of them.
2930

30-
While CodeIgniter does not require it, using this repo also requires the use of
31-
[Composer](https://getcomposer.org/) to install CodeIgniter as a dependency, and PHPUnit - the test framework.
31+
While CodeIgniter does not require it, using this repo also requires the use of
32+
[Composer](https://getcomposer.org/) to install CodeIgniter as a dependency, and PHPUnit - the test framework.
3233
You don't need that installed globally, and we actually recommend against it, since different projects likely
33-
require different versions of PHPUnit installed as time goes on and it can become tricky maintain a local
34-
environment that works with all of the different versions.
34+
require different versions of PHPUnit installed as time goes on and it can become tricky maintain a local
35+
environment that works with all of the different versions.
3536

3637
While it can be downloaded as a zip and extracted, we'll use [git](https://git-scm.com/) to manage things.
3738

38-
With those out of the way, it only takes a few small steps to get the project up and running locally.
39+
With those out of the way, it only takes a few small steps to get the project up and running locally.
3940

4041
1 - Clone the repo if you haven't already, from the CLI:
4142

42-
git clone https://github.com/codeigniter4projects/playground
43+
git clone https://github.com/codeigniter4projects/playground
4344

4445
That creates a new directory, `playground`, under your current directory.
4546

4647
2 - Enter the new directory and install the project dependencies with Composer. NOTE: The command shown
4748
here assumes that you have Composer loaded globally. If you don't, then pretend we're using `composer.phar`.
49+
4850
```
4951
cd playground
5052
composer install
5153
```
5254

5355
3 - Copy `.env.example` in the project directory and name it `.env`. Then open it up and verify the settings:
5456

55-
* First, `CI_ENVIRONMENT` is set to `development` as this enables error handling, the debug toolbar, and some other
56-
things handy while in development.
57+
- First, `CI_ENVIRONMENT` is set to `development` as this enables error handling, the debug toolbar, and some other
58+
things handy while in development.
59+
60+
- Next make sure that `app.baseURL` matches whatever you are currently running your site at. If you use `spark`,
61+
then it already matches the default. If this doesn't match, then generated links might not work, and your
62+
developer toolbar will never show up.
5763

58-
* Next make sure that `app.baseURL` matches whatever you are currently running your site at. If you use `spark`,
59-
then it already matches the default. If this doesn't match, then generated links might not work, and your
60-
developer toolbar will never show up.
64+
- Finally while you're in there, you can edit your database settings, though you can do that in `app/Config/Database.php`
65+
just as easily. Since we won't deploy this to multiple servers it's no big deal to edit the config files directly.
6166

62-
* Finally while you're in there, you can edit your database settings, though you can do that in `app/Config/Database.php`
63-
just as easily. Since we won't deploy this to multiple servers it's no big deal to edit the config files directly.
67+
4 - Back on the command line, we install all of the needed database tables and sample data.
6468

65-
4 - Back on the command line, we install all of the needed database tables and sample data.
6669
```
6770
php spark migrate
6871
php spark db:seed PlaygroundSeeder
6972
```
7073

7174
5 - That's it! If you're hosting through Apache, Nginx, etc, then head to your site. If you just want a quick
72-
way to work with your site locally, go back to the CLI and start up `spark`, CodeIgniter's small server.
75+
way to work with your site locally, go back to the CLI and start up `spark`, CodeIgniter's small server.
7376

74-
php spark serve
77+
php spark serve
7578

76-
If you get would like to change the port it's running on, that's no problem:
79+
If you get would like to change the port it's running on, that's no problem:
7780

78-
php spark serve --port 8081
81+
php spark serve --port 8081
7982

80-
Enjoy!
83+
Enjoy!
8184

8285
## Code Challenges
8386

84-
There are some portions of the code intentionally left for *you* to finish. Once you are familiar with
87+
There are some portions of the code intentionally left for _you_ to finish. Once you are familiar with
8588
the project and have read through the docs try searching the code for anything with the comment **Help!**.
89+
90+
## Images
91+
92+
All images in this repo were created by MidJourney and are can be used freely in non-commercial use cases.

app/Config/Routes.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
// where controller filters or CSRF protection are bypassed.
2626
// If you don't want to define all routes, please use the Auto Routing (Improved).
2727
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
28-
$routes->setAutoRoute(true);
28+
$routes->setAutoRoute(false);
2929

3030
/*
3131
* --------------------------------------------------------------------
@@ -37,6 +37,9 @@
3737
// route since we don't have to scan directories.
3838
$routes->get('/', 'Home::index');
3939

40+
$routes->get('heroes/(:num)', 'HeroController::show/$1');
41+
$routes->get('dungeons/(:num)', 'DungeonController::show/$1');
42+
4043
/*
4144
* --------------------------------------------------------------------
4245
* Additional Routing

app/Controllers/DungeonController.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace App\Controllers;
4+
5+
use App\Controllers\BaseController;
6+
use App\Models\DungeonModel;
7+
use App\Models\HeroModel;
8+
9+
class DungeonController extends BaseController
10+
{
11+
/**
12+
* HeroModel instance.
13+
*/
14+
protected $heroes;
15+
16+
public function __construct()
17+
{
18+
// Assign the model to $this->heroes
19+
// so that it's available throughout this class
20+
// Use the `model()` helper method to return
21+
// a single instance of the model no matter
22+
// how many times we call it
23+
$this->heroes = model(DungeonModel::class);
24+
}
25+
26+
/**
27+
* View a single hero's details.
28+
*
29+
* The $id parameter is the hero's ID, and is
30+
* passed in from the route definition as $1,
31+
* since it is the first placeholder in the route.
32+
*/
33+
public function show(int $id)
34+
{
35+
$dungeon = $this->heroes->find($id);
36+
37+
if ($dungeon === null) {
38+
return redirect()->back()->with('error', 'Dungeon not found');
39+
}
40+
41+
echo view('dungeon', [
42+
'dungeon' => $dungeon,
43+
'monsters' => $dungeon->monsters(3),
44+
]);
45+
}
46+
}

app/Controllers/HeroController.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace App\Controllers;
4+
5+
use App\Controllers\BaseController;
6+
use App\Models\HeroModel;
7+
use CodeIgniter\Exceptions\PageNotFoundException;
8+
9+
class HeroController extends BaseController
10+
{
11+
/**
12+
* View a single hero's details.
13+
*
14+
* The $id parameter is the hero's ID, and is
15+
* passed in from the route definition as $1,
16+
* since it is the first placeholder in the route.
17+
*/
18+
public function show(int $id)
19+
{
20+
// When you only need to use a model in a single place,
21+
// you can simply get a new instance here. It will use
22+
// the default database connection if none is passed in
23+
// during instantiation.
24+
$heroes = new HeroModel();
25+
26+
// Locate a single hero, by ID.
27+
$hero = $heroes->find($id);
28+
29+
// If the hero was not located, throw an exception.
30+
if ($hero === null) {
31+
throw new PageNotFoundException('Hero not found');
32+
}
33+
34+
// Display a view file, passing the variables
35+
// you want to access in the view within the
36+
// second parameter.
37+
echo view('hero', [
38+
'hero' => $hero,
39+
]);
40+
}
41+
}

app/Entities/Dungeon.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Entities;
44

5+
use App\Models\MonsterModel;
56
use CodeIgniter\Entity\Entity;
67

78
/**
@@ -34,4 +35,15 @@ public function link(): string
3435
{
3536
return site_url("dungeons/{$this->attributes['id']}");
3637
}
38+
39+
/**
40+
* Use another model to get some random data.
41+
*/
42+
public function monsters(int $limit=5)
43+
{
44+
return model(MonsterModel::class)
45+
->where('dungeon_id', $this->id)
46+
->orderBy('health', 'asc')
47+
->findAll();
48+
}
3749
}

app/Entities/Monster.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace App\Entities;
44

55
use CodeIgniter\Entity\Entity;
6+
use CodeIgniter\HTTP\Exceptions\HTTPException;
7+
use InvalidArgumentException;
68

79
/**
810
* Class Monster
@@ -20,6 +22,17 @@ class Monster extends Entity
2022
'dungeon_id' => 'integer',
2123
];
2224

25+
/**
26+
* Entities are the perfect place for
27+
* convenience methods made to clean up data.
28+
*/
29+
public function image(): string
30+
{
31+
$fileName = strtolower($this->name);
32+
33+
return base_url("images/{$fileName}.png");
34+
}
35+
2336
/**
2437
* Help! Monsters each have their own set of abilities (see Database/Seeds) but
2538
* our entity has no way of knowing what those are. Can you write it?

app/Views/_monster.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php if (! empty($monster)) : ?>
2+
<div class="card mb-3" style="max-width: 540px;">
3+
<div class="row g-0">
4+
<div class="col-md-5">
5+
<img src="<?= esc($monster->image(), 'attr') ?>"
6+
class="img-fluid rounded-start"
7+
alt="<?= esc($monster->name) ?>"
8+
>
9+
</div>
10+
<div class="col-md-7">
11+
<div class="card-body">
12+
<h5 class="card-title"><?= esc($monster->name) ?></h5>
13+
<p>Health: <?= $monster->health ?? 0 ?></p>
14+
</div>
15+
</div>
16+
</div>
17+
</div>
18+
<?php endif ?>

app/Views/dungeon.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<!--
2+
We are using View Layouts to provide a consistent
3+
look to the site. The `extend()` method tells the
4+
name of the view that this view will work with to
5+
display the final content. In this case, the view
6+
is at app/Views/layout.php
7+
-->
8+
<?= $this->extend('layout') ?>
9+
10+
<!--
11+
Everything between `section()` and `endSection()
12+
is inserted into the `layout` view where it calls
13+
`$this->renderSection('content')`.
14+
-->
15+
<?= $this->section('content') ?>
16+
<div class="">
17+
18+
<!-- While we should throw exception if the dungeon is not found,
19+
we'll add a check just in case. -->
20+
<?php if (empty($dungeon)) : ?>
21+
<div class="alert alert-warning">
22+
Dungeon not found.
23+
</div>
24+
<?php endif ?>
25+
26+
<!-- Dungeon Details -->
27+
<?php if ($dungeon) : ?>
28+
<div class="container text-center">
29+
<div class="col-6 mx-auto">
30+
31+
<div class="card shadow">
32+
<img src="<?= base_url('images/dungeon.png') ?>"
33+
alt="<?= esc($dungeon->name, 'attr') ?>"
34+
class="card-img-top"
35+
>
36+
<div class="card-body">
37+
<h5 class="card-title"><?= esc($dungeon->name) ?></h5>
38+
39+
<ul class="card-text list-unstyled">
40+
<li>Capacity: <?= esc($dungeon->capacity) ?></li>
41+
<li>Difficulty: <?= esc($dungeon->difficulty) ?></li>
42+
</ul>
43+
44+
<br>
45+
46+
<h6>Monsters in Residence</h6>
47+
48+
<?php foreach($monsters as $monster) : ?>
49+
<!-- It's nice to keep things simple.
50+
Don't be afraid to use view fragments
51+
to keep your code clean and readable.
52+
-->
53+
<?= view('_monster', ['monster' => $monster]) ?>
54+
<?php endforeach ?>
55+
</div>
56+
</div>
57+
58+
</div>
59+
</div>
60+
61+
<?php endif ?>
62+
</div>
63+
<?= $this->endSection() ?>

0 commit comments

Comments
 (0)