|
| 1 | +--- |
| 2 | +title: Getting Started |
| 3 | +--- |
| 4 | + |
| 5 | +Tempest is a PHP MVC framework that gets out of your way. Its design philosophy is that developers should write as little framework-related code as possible, so that they can focus on application code instead. |
| 6 | + |
| 7 | +## Installation |
| 8 | + |
| 9 | +You can install Tempest in two ways: as a web app with a basic frontend bootstrap, or by requiring the framework as a package in any project you'd like. |
| 10 | + |
| 11 | +### Tempest App |
| 12 | + |
| 13 | +If you want to start a new Tempest project, you can use `tempest/app` as the starting point. Use `composer create-project` to start: |
| 14 | + |
| 15 | +```txt |
| 16 | +composer create-project tempest/app my-app |
| 17 | +cd my-app |
| 18 | +``` |
| 19 | + |
| 20 | +This project scaffold includes a basic frontend setup including tailwind: |
| 21 | + |
| 22 | +```txt |
| 23 | +npm run dev |
| 24 | +``` |
| 25 | + |
| 26 | +You can access your app by using PHP's built-in server. |
| 27 | + |
| 28 | +```text |
| 29 | +./tempest serve |
| 30 | +<hljs comment>PHP 8.3.3 Development Server (http://localhost:8000) started</hljs> |
| 31 | +``` |
| 32 | + |
| 33 | +### Tempest as a package |
| 34 | + |
| 35 | +If you don't need an app scaffold, 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. |
| 36 | + |
| 37 | +```txt |
| 38 | +composer require tempest/framework |
| 39 | +``` |
| 40 | + |
| 41 | +Installing Tempest this way will give you access to the tempest console as a composer binary: |
| 42 | + |
| 43 | +```txt |
| 44 | +./vendor/bin/tempest |
| 45 | +``` |
| 46 | + |
| 47 | +Optionally, you can choose to install Tempest's entry points in your project: |
| 48 | + |
| 49 | +```txt |
| 50 | +./vendor/bin/tempest install |
| 51 | +``` |
| 52 | + |
| 53 | +Installing Tempest into a project means copying one or more of these files into that project: |
| 54 | + |
| 55 | +- `public/index.php` — the web application entry point |
| 56 | +- `tempest` – the console application entry point |
| 57 | +- `.env.example` – a clean example of a `.env` file |
| 58 | +- `.env` – the real environment file for your local installation |
| 59 | + |
| 60 | +You can choose which files you want to install, and you can always rerun the `install` command at a later point in time. |
| 61 | + |
| 62 | + |
| 63 | +## A basic Tempest project |
| 64 | + |
| 65 | +Tempest won't impose any fixed file structure on you: one of the core principles of Tempest is that it will scan you project code for you, and it will automatically discover any files it needs to. For example: Tempest is able to differentiate between a controller method and a console command by looking at the code, instead of relying on naming conventions. This is what's called **discovery**, and it's one of Tempest's most powerful features. |
| 66 | + |
| 67 | +You can make a project that looks like this: |
| 68 | + |
| 69 | +```txt |
| 70 | +app |
| 71 | +├── Console |
| 72 | +│ └── RssSyncCommand.php |
| 73 | +├── Controllers |
| 74 | +│ ├── BlogPostController.php |
| 75 | +│ └── HomeController.php |
| 76 | +└── Views |
| 77 | + ├── blog.view.php |
| 78 | + └── home.view.php |
| 79 | +``` |
| 80 | + |
| 81 | +Or a project that looks like this: |
| 82 | + |
| 83 | +```txt |
| 84 | +app |
| 85 | +├── Blog |
| 86 | +│ ├── BlogPostController.php |
| 87 | +│ ├── RssSyncCommand.php |
| 88 | +│ └── blog.view.php |
| 89 | +└── Home |
| 90 | + ├── HomeController.php |
| 91 | + └── home.view.php |
| 92 | +``` |
| 93 | + |
| 94 | +From Tempest's perspective, it's all the same. |
| 95 | + |
| 96 | +Discovery works by scanning you project code, and looking at each file and method individually to determine what that code does. For production apps, Tempest will cache these results as PHP code, so there's absolutely no performance overhead to doing so. |
| 97 | + |
| 98 | +As an example, Tempest is able to determine which methods are controller methods based on their route attributes: |
| 99 | + |
| 100 | +```php |
| 101 | +final <hljs keyword>readonly</hljs> class BlogPostController |
| 102 | +{ |
| 103 | + #[<hljs type>Get</hljs>(<hljs value>'/blog'</hljs>)] |
| 104 | + public function index(): <hljs type>View</hljs> |
| 105 | + { /* … */ } |
| 106 | + |
| 107 | + #[<hljs type>Get</hljs>(<hljs value>'/blog/{post}'</hljs>)] |
| 108 | + public function show(<hljs type>Post</hljs> $post): <hljs type>Response</hljs> |
| 109 | + { /* … */ } |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +And likewise, it's able to detect console commands based on their console command attribute: |
| 114 | + |
| 115 | +```php |
| 116 | +final <hljs keyword>readonly</hljs> class RssSyncCommand |
| 117 | +{ |
| 118 | + public function __construct(<hljs keyword>private</hljs> <hljs type>Console</hljs> $console) {} |
| 119 | + |
| 120 | + #[<hljs type>ConsoleCommand</hljs>('<hljs value>rss:sync</hljs>')] |
| 121 | + public function __invoke(<hljs type>bool</hljs> $force = <hljs keyword>false</hljs>): <hljs type>void</hljs> |
| 122 | + { /* … */ } |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +We'll cover controllers and console commands in depth in future chapters. |
0 commit comments