Skip to content

Commit e1c1d81

Browse files
authored
refactor: improve docs structure (#81)
1 parent 4900fa2 commit e1c1d81

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2000
-2655
lines changed

src/Web/Documentation/Chapter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public function __construct(
1717
public string $body,
1818
public string $title,
1919
public string $path,
20+
public bool $hidden = false,
2021
public ?string $description = null,
2122
) {
2223
}

src/Web/Documentation/ChapterController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public function docsRedirect(string $path): Redirect
2727
#[Get('/docs')]
2828
#[Get('/documentation')]
2929
#[Get('/main/framework/getting-started')]
30-
#[Get('/main/getting-started/introduction')]
3130
public function index(): Redirect
3231
{
3332
$version = Version::default();
@@ -63,7 +62,7 @@ public function __invoke(string $version, string $category, string $slug, Chapte
6362

6463
$currentChapter = $chapterRepository->find($version, $category, $slug);
6564

66-
if (! $currentChapter) {
65+
if (! $currentChapter || $currentChapter->hidden) {
6766
return new NotFound();
6867
}
6968

src/Web/Documentation/ChapterRepository.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function find(Version $version, string $category, string $slug): ?Chapter
4545
$frontmatter = $markdown->getFrontMatter();
4646
$title = get_by_key($frontmatter, 'title');
4747
$description = get_by_key($frontmatter, 'description');
48+
$hidden = get_by_key($frontmatter, 'hidden');
4849

4950
return new Chapter(
5051
version: $version,
@@ -53,6 +54,7 @@ public function find(Version $version, string $category, string $slug): ?Chapter
5354
body: $markdown->getContent(),
5455
title: $title,
5556
path: to_relative_path(root_path(), $path),
57+
hidden: $hidden ?? false,
5658
description: $description ?? null,
5759
);
5860
}
@@ -78,6 +80,7 @@ public function all(Version $version, string $category = '*'): ImmutableArray
7880
...YamlFrontMatter::parse($content)->matter(),
7981
];
8082
})
83+
->filter(fn (array $chapter) => get_by_key($chapter, 'hidden') !== true)
8184
->mapTo(Chapter::class);
8285
}
8386
}

src/Web/Documentation/RedirectMiddleware.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use Tempest\Core\Priority;
66
use Tempest\Http\Request;
77
use Tempest\Http\Response;
8-
use Tempest\Http\Responses\NotFound;
98
use Tempest\Http\Responses\Redirect;
109
use Tempest\Router\HttpMiddleware;
1110
use Tempest\Router\HttpMiddlewareCallable;
@@ -16,7 +15,6 @@
1615
use function Tempest\Support\Arr\get_by_key;
1716
use function Tempest\Support\Regex\matches;
1817
use function Tempest\Support\str;
19-
use function Tempest\uri;
2018

2119
#[Priority(Priority::HIGHEST)]
2220
final readonly class RedirectMiddleware implements HttpMiddleware
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
title: Introduction
3+
description: "Tempest is a PHP framework for web and console applications, designed to get out of your way. Its core philosophy is to help developers focus on their application code, without being bothered with configuring or hand-holding the framework."
4+
---
5+
6+
Tempest makes writing PHP applications pleasant thanks to carefully crafted quality-of-life features that feel like a natural extension of vanilla PHP.
7+
8+
It embraces modern PHP syntax in its implementation of routing, ORM, console commands, messaging, logging, it takes inspiration from the best front-end frameworks for its templating engine syntax, and provides unique capabilities, such as [discovery](../3-internals/02-discovery), to improve developer experience.
9+
10+
You may be interested in reading how it has an [unfair advantage](/blog/unfair-advantage) over other frameworks—but code says more than words, so here are a few examples of code written on top of Tempest:
11+
12+
```php
13+
use Tempest\Router\Get;
14+
use Tempest\Router\Post;
15+
use Tempest\Router\Response;
16+
use Tempest\Router\Responses\Ok;
17+
use Tempest\Router\Responses\Redirect;
18+
use function Tempest\uri;
19+
20+
final readonly class BookController
21+
{
22+
#[Get('/books/{book}')]
23+
public function show(Book $book): Response
24+
{
25+
return new Ok($book);
26+
}
27+
28+
#[Post('/books')]
29+
public function store(CreateBookRequest $request): Response
30+
{
31+
$book = map($request)->to(Book::class)->save();
32+
33+
return new Redirect(uri([self::class, 'show'], book: $book->id));
34+
}
35+
36+
// …
37+
}
38+
```
39+
40+
The above snippet is an example of a controller. It features [attribute-based routes](../1-essentials/02-controllers), mapping a request to a data object using the [mapper](../2-tempest-in-depth/01-mapper), [URL generation](../1-essentials/02-controllers#generating-uris) and [dependency injection](../1-essentials/01-container#autowired-dependencies).
41+
42+
```php
43+
use Tempest\Console\Console;
44+
use Tempest\Console\ConsoleCommand;
45+
use Tempest\Console\Middleware\ForceMiddleware;
46+
use Tempest\Console\Middleware\CautionMiddleware;
47+
use Tempest\EventBus\EventHandler;
48+
49+
final readonly class MigrateUpCommand
50+
{
51+
public function __construct(
52+
private Console $console,
53+
private MigrationManager $migrationManager,
54+
) {}
55+
56+
#[ConsoleCommand(
57+
name: 'migrate:up',
58+
description: 'Run all new migrations',
59+
middleware: [ForceMiddleware::class, CautionMiddleware::class],
60+
)]
61+
public function __invoke(bool $fresh = false): void
62+
{
63+
if ($fresh) {
64+
$this->migrationManager->dropAll();
65+
$this->console->success("Database dropped.");
66+
}
67+
68+
$this->migrationManager->up();
69+
$this->console->success("Migrations applied.");
70+
}
71+
72+
#[EventHandler]
73+
public function onTableDropped(TableDropped $event): void
74+
{
75+
$this->console->writeln("- Dropped {$event->name}");
76+
}
77+
78+
#[EventHandler]
79+
public function onMigrationMigrated(MigrationMigrated $migrationMigrated): void
80+
{
81+
$this->console->writeln("- {$migrationMigrated->name}");
82+
}
83+
}
84+
```
85+
86+
This is a [console command](../3-console/02-building-console-commands). Console commands can be defined in any class, as long as the {b`#[Tempest\Console\ConsoleCommand]`} attribute is used on a method. Command arguments are defined as the method's arguments, effectively removing the need to learn some specific framework syntax.
87+
88+
This example also shows how to [register events globally](../2-tempest-in-depth/03-events) using the {b`#[Tempest\EventBus\EventHandler]`}.
89+
90+
---
91+
92+
:::info Ready to give it a try?
93+
Keep on reading and consider [**giving Tempest a star️ on GitHub**](https://github.com/tempestphp/tempest-framework). If you want to be part of the community, you can [**join our Discord server**](https://discord.gg/pPhpTGUMPQ), and if you feel like contributing, you can check out our [contributing guide](/docs/extra-topics/contributing)!
94+
:::

src/Web/Documentation/content/main/0-getting-started/01-getting-started.md renamed to src/Web/Documentation/content/main/0-getting-started/02-installation.md

Lines changed: 49 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,86 @@
11
---
2-
title: Getting started
3-
description: Tempest is a PHP framework for web and console applications, designed to get out of your way. Its core philosophy is to help developers focus on their application code, without being bothered with configuring or hand-holding the framework.
2+
title: Installation
3+
description: Tempest can be installed as a standalone PHP project, as well as a package within existing projects. The framework modules can also be installed individually, including in projects built on other frameworks.
44
---
55

6-
## Installation
6+
## Prerequisites
77

8-
Because of Tempest's design, you can install the whole framework or individual components, both in new projects and existing ones. It's even possible to use Tempest in existing projects, alongside other frameworks.
8+
Tempest requires PHP [8.4+](https://www.php.net/downloads.php) and [Composer](https://getcomposer.org/) to be installed. Optionally, you may install either [Bun](https://bun.sh) or [Node](https://nodejs.org) if you chose to bundle front-end assets.
99

10-
Start by creating a project from scratch:
10+
For a better experience, it is recommended to have a complete development environment, such as [ServBay](https://www.servbay.com), [Herd](https://herd.laravel.com/docs), or [Valet](https://laravel.com/docs/valet). However, Tempest can serve applications using PHP's built-in server just fine.
1111

12-
```shell
13-
{:hl-keyword:composer:} create-project tempest/app my-app --stability beta
14-
{:hl-keyword:cd:} my-app
15-
```
12+
Once the prerequisites are installed, you can chose your installation method. Tempest can be a [standalone application](#creating-a-tempest-application), or be added [in an existing project](#tempest-as-a-package)—even one built on top of another framework.
13+
14+
## Creating a Tempest application
1615

17-
Or by requiring tempest in an existing codebase:
16+
To get started with a new Tempest project, you may use {`tempest/app`} as the starting point. The `composer create-project` command will scaffold it for you:
1817

1918
```sh
20-
{:hl-keyword:composer:} require tempest/framework:1.0-beta.1
19+
{:hl-keyword:composer:} create-project tempest/app {:hl-type:my-app:} --stability beta
20+
{:hl-keyword:cd:} {:hl-type:my-app:}
2121
```
2222

23-
If you required `tempest/framework` into an existing project, you may optionally install framework-related files:
23+
If you have a dedicated development environment, you may then access your application by opening `{txt}https://my-app.test` in your browser. Otherwise, you may use PHP's built-in server:
2424

2525
```sh
26-
{:hl-keyword:php:} vendor/bin/tempest install framework
26+
{:hl-keyword:php:} tempest serve
27+
{:hl-comment:PHP 8.4.5 Development Server (http://localhost:8000) started:}
2728
```
2829

29-
:::info
30-
The `tempest` console is the entry point for many framework-related tasks, as well as your own console commands. In these docs, we'll always use `{:hl-keyword:php:} tempest` to access it. If you didn't publish the console file within your project though, you can still access it via `{:hl-keyword:php:} vendor/bin/tempest`
31-
:::
32-
33-
Using the `{txt}install framework` command will prompt you to install the following files into your project:
30+
### Scaffolding front-end assets
3431

35-
- `public/index.php` — the web application entry point
36-
- `tempest` – the console application entry point
37-
- `.env.example` – a clean example of a `.env` file
38-
- `.env` – the real environment file for your local installation
32+
Optionally, you may install a basic front-end scaffolding that includes [Vite](https://vite.dev/) and [Tailwind CSS](https://tailwindcss.com/). To do so, run the Vite installer and follow through the wizard:
3933

40-
You can choose which files you want to install, and you can always rerun the `install` command at a later point in time.
34+
```sh
35+
{:hl-keyword:php:} tempest install vite --tailwind
36+
```
4137

42-
:::warning
43-
Because Tempest is currently in beta, you will need to allow dev dependencies as your minimum stability in `composer.json`: `{json}"minimum-stability": "dev",`, you should also ensure that composer still prefers stable versions if they are available: `{json}"prefer-stable": true,`. These composer properties are only necessary as long as Tempest isn't stable yet.
44-
:::
38+
The assets created by this wizard, `main.entrypoint.ts` and `main.entrypoint.css`, are automatically discovered by Tempest. You can serve them using the [`<x-vite-tags />`](../1-essentials/03-views#x-vite-tags) component in your templates.
4539

46-
### Installation requirements
40+
You may then [run the front-end development server](../1-essentials/04-asset-bundling#running-the-development-server), which will serve your assets on-the-fly:
4741

48-
Tempest requires [PHP 8.4+](https://www.php.net/downloads.php) and [Composer](https://getcomposer.org/) to be installed. Optionally, you may install either [Bun](https://bun.sh) or [Node](https://nodejs.org) if you chose to bundle front-end assets.
42+
```bash
43+
{:hl-keyword:npm:} run dev
44+
```
4945

50-
For a better experience, it is recommended to have a complete development environment, such as [ServBay](https://www.servbay.com), [Herd](https://herd.laravel.com/docs), or [Valet](https://laravel.com/docs/valet). However, Tempest can serve applications using PHP's built-in server as well:
46+
## Tempest as a package
5147

48+
If you already have a project, you can opt to install {`tempest/framework`} as a standalone package. You could do this in any project; it could already contain code, or it could be an empty project.
5249

5350
```sh
54-
{:hl-keyword:php:} tempest serve
51+
{:hl-keyword:composer:} require tempest/framework:1.0-beta.1
5552
```
5653

54+
:::warning
55+
Because Tempest is currently in beta (and still has two dev dependencies), you will need to allow dev dependencies as your minimum stability in `composer.json`: `{json}"minimum-stability": "dev",`, you should also ensure that composer still prefers stable versions if they are available: `{json}"prefer-stable": true,`. These composer properties are only necessary as long as Tempest isn't stable yet.
56+
:::
5757

58-
### Scaffolding front-end assets
59-
60-
After having installed Tempest, you can optionally install a basic front-end scaffolding that includes [Vite](https://vite.dev/) and [Tailwind CSS](https://tailwindcss.com/). To do so, run the Vite installer and follow through the wizard:
58+
Installing Tempest this way will give you access to the Tempest console, `./vendor/bin/tempest`. Optionally, you can choose to install Tempest's entry points in your project. To do so, you may run the framework installer:
6159

62-
```sh
63-
{:hl-keyword:php:} tempest install vite
60+
```txt
61+
{:hl-keyword:./vendor/bin/tempest:} install framework
6462
```
6563

66-
The assets created by this wizard, `main.entrypoint.ts` and `main.entrypoint.css`, are automatically discovered by Tempest. You can serve them using the [`{html}<x-vite-tags />`](../1-essentials/03-views#x-vite-tags) component in your templates.
64+
This installer will prompt you to install the following files into your project:
6765

68-
You may then [run the front-end development server](../1-essentials/04-asset-bundling#running-the-development-server), which will serve your assets on-the-fly:
66+
- `public/index.php` — the web application entry point
67+
- `tempest` – the console application entry point
68+
- `.env.example` – a clean example of a `.env` file
69+
- `.env` – the real environment file for your local installation
6970

70-
```bash
71-
{:hl-keyword:npm:} run dev
72-
```
71+
You can choose which files you want to install, and you can always rerun the `install` command at a later point in time.
7372

7473
## Project structure
7574

76-
Tempest won't impose any fixed file structure on you: the framework gives you the freedom to design your project the way you and your team want. Tempest can give you this freedom without any configuration overhead thanks to one of its core features called [discovery](../4-internals/02-discovery).
75+
Tempest won't impose any file structure on you: one of its core features is that it will scan all project and package code for you, and will automatically discover any files the framework needs to know about.
7776

78-
For example, here are two different project structures side by side:
77+
For instance, Tempest is able to differentiate between a controller method and a console command by looking at the code, instead of relying on naming conventions or configuration files.
78+
79+
:::info
80+
This concept is called [discovery](../4-internals/02-discovery), and is one of Tempest's most powerful features.
81+
:::
82+
83+
The following projects structures work the same way in Tempest, without requiring any specific configuration:
7984

8085
```txt
8186
. .
@@ -92,12 +97,10 @@ For example, here are two different project structures side by side:
9297
├── Publishers └── Views
9398
│ └── PublisherGateway.php ├── authors.view.php
9499
└── Support ├── books.view.php
95-
└── x-base.view.php └── x-base.view.php
100+
└── x-base.view.php └── x-base.view.php
96101
```
97102

98-
From Tempest's perspective, your project structure doesn't make a difference.
99-
100-
### About Discovery
103+
## About discovery
101104

102105
Discovery works by scanning your project code, and looking at each file and method individually to determine what that code does. In production environments, [Tempest will cache the discovery process](../4-internals/02-discovery#discovery-in-production), avoiding any performance overhead.
103106

@@ -135,31 +138,3 @@ final readonly class RssSyncCommand
135138
{ /* … */ }
136139
}
137140
```
138-
139-
Or event listeners:
140-
141-
```php app/MigrationListeners.php
142-
use Tempest\Console\Console;
143-
use Tempest\EventBus\EventHandler;
144-
145-
final readonly class MigrationListeners
146-
{
147-
public function __construct(
148-
private Console $console,
149-
) {}
150-
151-
#[EventHandler]
152-
public function onTableDropped(TableDropped $event): void
153-
{
154-
$this->console->writeln("- Dropped {$event->name}");
155-
}
156-
157-
#[EventHandler]
158-
public function onMigrationMigrated(MigrationMigrated $migrationMigrated): void
159-
{
160-
$this->console->writeln("- {$migrationMigrated->name}");
161-
}
162-
}
163-
```
164-
165-
Discovery is one of Tempest's most powerful features, if you want to better understand the framework, you could read this article to learn about [discovery in depth](/blog/discovery-explained). You can also continue reading the docs to learn about Tempest's essential components next.

src/Web/Documentation/content/main/1-essentials/02-controllers.md renamed to src/Web/Documentation/content/main/1-essentials/01-routing.md

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
2-
title: "Controllers"
3-
description: "Controllers manage the flow of any web application. In Tempest, attributes are used to route an HTTP request to any class' method, which is responsible for returning a response."
2+
title: "Routing"
3+
description: "Learn how to route requests to controllers. In Tempest, this is done using attributes, which are automatically discovered by the framework."
44
---
55

66
## Overview
77

8-
In Tempest, a route may be associated to any class' method, although this is usually done in dedicated controller classes.
8+
In Tempest, you may associate a route to any class method. Usually, this is done in dedicated controller classes, but it could be any class of your choice.
99

1010
Tempest provides many attributes, named after HTTP verbs, to attach URIs to controller actions. These attributes implement the {`Tempest\Router\Route`} interface, so you can write your own if you need to.
1111

@@ -24,21 +24,11 @@ final readonly class HomeController
2424
}
2525
```
2626

27-
Out of the box, the following attributes are available:
28-
29-
- {`Tempest\Router\Get`}
30-
- {`Tempest\Router\Post`}
31-
- {`Tempest\Router\Delete`}
32-
- {`Tempest\Router\Put`}
33-
- {`Tempest\Router\Patch`}
34-
- {`Tempest\Router\Options`}
35-
- {`Tempest\Router\Connect`}
36-
- {`Tempest\Router\Trace`}
37-
- {`Tempest\Router\Head`}
27+
Out of the box, an attribute for every HTTP verb is available: {b`Tempest\Router\Get`}, {b`Tempest\Router\Post`}, {b`Tempest\Router\Delete`}, {b`Tempest\Router\Put`}, {b`Tempest\Router\Patch`}, {b`Tempest\Router\Options`}, {b`Tempest\Router\Connect`}, {b`Tempest\Router\Trace`} and {b`Tempest\Router\Head`}.
3828

3929
## Route parameters
4030

41-
You can define dynamic segments in your route URIs by wrapping them in curly braces `{}`. The segment name inside the braces will be passed as a parameter to your controller method.
31+
You may define dynamic segments in your route URIs by wrapping them in curly braces. The segment name inside the braces will be passed as a parameter to your controller method.
4232

4333
```php app/AircraftController.php
4434
use Tempest\Router\Get;

src/Web/Documentation/content/main/1-essentials/03-views.md renamed to src/Web/Documentation/content/main/1-essentials/02-views.md

File renamed without changes.

0 commit comments

Comments
 (0)