Skip to content

Commit e0ebb95

Browse files
committed
wip
1 parent fe56994 commit e0ebb95

File tree

2 files changed

+149
-56
lines changed

2 files changed

+149
-56
lines changed
Lines changed: 148 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,187 @@
11
---
22
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."
3+
description: "Tempest is a framework for PHP development, designed to get out of your way. Its core philosophy is to help you focus on your application code, without being bothered hand-holding the framework."
44
---
55

6-
Tempest makes writing PHP applications pleasant thanks to carefully crafted quality-of-life features that feel like a natural extension of vanilla PHP.
6+
Tempest's goal is to make you more productive when building web and console apps in PHP. It handles all the boilerplate parts of such projects for you, so that you can focus on what matters the most: writing application code.
77

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.
8+
People using Tempest say it's the sweet spot between the robustness of Symfony and the eloquence of Laravel. It feels lightweight and close to vanilla PHP; and yet powerful and feature-rich. On this page, you'll read what sets Tempest apart as a framework for modern PHP development. If you're already convinced, you can head over to the [installation page](../0-getting-started/02-installation.md) and get started with Tempest.
99

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:
10+
## Vision
1111

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;
12+
Tempest's vision can be summarized like this: **it's a community-driven, modern PHP framework that gets out of your way and dares to think outside the box**. Let's dissect that vision in depth.
1913

20-
final readonly class BookController
14+
### Community driven
15+
16+
Tempest started out as an educational project, without the intention for it to be something real. People picked up on it, though, and it was only after a strong community had formed that we considered making it something real.
17+
18+
Currently, there are three core members dedicating a lot of their time to Tempest, as well as over [50 additional contributors](https://github.com/tempestphp/tempest-framework). We have an active [Discord server](/discord) with close to 400 members.
19+
20+
Tempest isn't a solo project and never has been. It is a new framework and has a way to go compared to Symfony or Laravel, but there already is significant momentum and will only keep growing.
21+
22+
### Embracing modern PHP
23+
24+
The benefit of starting from scratch like Tempest did is having a clean slate. Tempest embraced modern PHP features from the start, and its goal is to keep doing this in the future by shipping built-in upgraders whenever breaking changes happen (think of it as Laravel Shift, but built into the framework).
25+
26+
Just to name a couple of examples, Tempest uses property hooks:
27+
28+
```php
29+
interface DatabaseMigration
2130
{
22-
#[Get('/books/{book}')]
23-
public function show(Book $book): Response
24-
{
25-
return new Ok($book);
31+
public string $name {
32+
get;
2633
}
2734

28-
#[Post('/books')]
29-
public function store(CreateBookRequest $request): Response
30-
{
31-
$book = map($request)->to(Book::class)->save();
35+
public function up(): ?QueryStatement;
3236

33-
return new Redirect(uri([self::class, 'show'], book: $book->id));
34-
}
37+
public function down(): ?QueryStatement;
38+
}
39+
```
3540

36-
// …
41+
Attributes:
42+
43+
```php
44+
final class BookController
45+
{
46+
#[Get('/books/{book}')]
47+
public function show(Book $book): Response { /* … */ }
3748
}
3849
```
3950

40-
The above snippet is an example of a controller. It features [attribute-based routes](../1-essentials/01-routing.md), mapping a request to a data object using the [mapper](../2-features/01-mapper.md), [URL generation](../1-essentials/01-routing.md#generating-uris) and [dependency injection](../1-essentials/05-container.md#autowired-dependencies).
51+
Proxy objects:
4152

4253
```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;
54+
use Tempest\Container\Proxy;
4855

49-
final readonly class MigrateUpCommand
56+
final readonly class BookController
5057
{
5158
public function __construct(
52-
private Console $console,
53-
private MigrationManager $migrationManager,
59+
#[Proxy] private SlowDependency $slowDependency,
60+
) { /* … */ }
61+
}
62+
```
63+
64+
And a lot more.
65+
66+
### Getting out of your way
67+
68+
A core part of Tempest's philosophy is that it wants to "get out of your way" as best as possible. For starters, Tempest is designed to structure your project code however you want, without making any assumptions or forcing conventions on you. You can prefer a classic MVC applications, DDD or hexagonal design, microservices, or something else; Tempest works with any project structure out of the box without any configuration.
69+
70+
Behind Tempest's flexibility is one of its most powerful features: [discovery](../internals/discovery). Discovery gives Tempest a great number of insights into your codebase, without any handholding. Discovery handles routing, console commands, view components, event listeners, command handlers, middleware, schedules, migrations, and more.
71+
72+
```php
73+
final class ConsoleCommandDiscovery implements Discovery
74+
{
75+
use IsDiscovery;
76+
77+
public function __construct(
78+
private readonly ConsoleConfig $consoleConfig,
5479
) {}
5580

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
81+
public function discover(DiscoveryLocation $location, ClassReflector $class): void
6282
{
63-
if ($fresh) {
64-
$this->migrationManager->dropAll();
65-
$this->console->success("Database dropped.");
83+
foreach ($class->getPublicMethods() as $method) {
84+
if ($consoleCommand = $method->getAttribute(ConsoleCommand::class)) {
85+
$this->discoveryItems->add($location, [$method, $consoleCommand]);
86+
}
6687
}
88+
}
6789

68-
$this->migrationManager->up();
69-
$this->console->success("Migrations applied.");
90+
public function apply(): void
91+
{
92+
foreach ($this->discoveryItems as [$method, $consoleCommand]) {
93+
$this->consoleConfig->addCommand($method, $consoleCommand);
94+
}
7095
}
96+
}
97+
```
98+
99+
Discovery makes Tempest truly understand your codebase so that you don't have to explain the framework how to use it. Of course, discovery is heavily optimized for local development and entirely cached in production, so there's no performance overhead. Even better: discovery isn't just a core framework feature, you're encouraged to write your own project-specific discovery classes wherever they make sense. That's the Tempest way.
100+
101+
Besides Discovery, Tempest is designed to be extensible. You'll find that any part of the framework can be replaced and hooked into by implementing an interface and plugging it into the container. No fighting the framework, Tempest gets out of your way.
71102

72-
#[EventHandler]
73-
public function onTableDropped(TableDropped $event): void
103+
### Thinking outside the box
104+
105+
Finally, since Tempest originated as an educational project, many Tempest features dare to rethink the things we've gotten used to. For example, [console commands](../1-essentials/04-console-commands), which in Tempest are designed to be very similar to controller actions:
106+
107+
```php
108+
final readonly class BooksCommand
109+
{
110+
use HasConsole;
111+
112+
public function __construct(
113+
private BookRepository $repository,
114+
) {}
115+
116+
#[ConsoleCommand]
117+
public function find(?string $initial = null): void
74118
{
75-
$this->console->writeln("- Dropped {$event->name}");
119+
$book = $this->search(
120+
'Find your book',
121+
$this->repository->find(...),
122+
);
76123
}
77124

78-
#[EventHandler]
79-
public function onMigrationMigrated(MigrationMigrated $migrationMigrated): void
125+
#[ConsoleCommand(middleware: [CautionMiddleware::class])]
126+
public function delete(string $title, bool $verbose = false): void
127+
{ /* … */ }
128+
}
129+
```
130+
131+
Or what about [Tempest's ORM](../1-essentials/03-database), which aims to have truly decoupled models:
132+
133+
```php
134+
use Tempest\Validation\Rules\Length;
135+
use App\Author;
136+
137+
final class Book
138+
{
139+
#[Length(min: 1, max: 120)]
140+
public string $title;
141+
142+
public ?Author $author = null;
143+
144+
/** @var \App\Chapter[] */
145+
public array $chapters = [];
146+
}
147+
```
148+
149+
```php
150+
final class BookRepository
151+
{
152+
public function findById(int $id): Book
80153
{
81-
$this->console->writeln("- {$migrationMigrated->name}");
154+
return query(Book::class)
155+
->select()
156+
->with('chapters', 'author')
157+
->where('id = ?', $id)
158+
->first();
82159
}
83160
}
84161
```
85162

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.
163+
Then there's our view engine, which embraces the most original template engine of all time: HTML;
164+
165+
```html
166+
<x-base :title="$this->seo->title">
167+
<ul>
168+
<li :foreach="$this->books as $book">
169+
{{ $book->title }}
170+
171+
<span :if="$this->showDate($book)">
172+
<x-tag>
173+
{{ $book->publishedAt }}
174+
</x-tag>
175+
</span>
176+
</li>
177+
</ul>
178+
</x-base>
179+
```
87180

88-
This example also shows how to [register events globally](../2-features/08-events.md) using the {b`#[Tempest\EventBus\EventHandler]`}.
181+
## Getting started
89182

90-
---
183+
Are you intrigued? Want to give Tempest a try? Head over to [the next chapter](../0-getting-started/02-installation.md) to learn about how to get started with Tempest.
184+
185+
If you want to become part of our community, you're more than welcome to [join our Discord server](/discord), and to check out [Tempest on GitHub](https://github.com/tempestphp/tempest-framework).
91186

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-
:::
187+
Enjoy!

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ For instance, Tempest is able to differentiate between a controller method and a
8080
This concept is called [discovery](../4-internals/02-discovery), and is one of Tempest's most powerful features.
8181
:::
8282

83-
The following projects structures work the same way in Tempest, without requiring any specific configuration:
83+
The following project structures work the same way in Tempest, without requiring any specific configuration:
8484

8585
```txt
8686
. .

0 commit comments

Comments
 (0)