-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
--- | ||
slug: livewire | ||
title: 'Livewire' | ||
description: "Laracord's HTTP server includes support for Laravel Livewire making simple web admin interfaces for your bot a breeze." | ||
priority: 1 | ||
group: Examples | ||
--- | ||
|
||
Laracord's HTTP server while implementing Laravel's routing also brings in the necessary requirements for Livewire. | ||
|
||
While Laracord has not been thoroughly tested with everything Livewire has to offer, it has been tested with full page components and can be a very quick and powerful way to create a basic web interface to interact with your bot instance in real-time without Javascript. | ||
|
||
> #### Note | ||
> | ||
> While this provides a great way to easily manage a personal bot, it is **strongly discouraged** to use the Laracord HTTP server to host any kind of user-facing application. | ||
In this example, we will install Livewire and create a simple **Message component** that is capable of showing every user visible to the bot in a select dropdown and firing off a message using the bot instance when clicking send. | ||
|
||
## Install Livewire | ||
|
||
Start by installing Livewire using Composer: | ||
|
||
```sh | ||
$ composer require livewire/livewire | ||
``` | ||
|
||
Once installed, you will need to generate an application key (`APP_KEY`) using the `laracord` binary: | ||
|
||
```sh | ||
$ php laracord key:generate | ||
``` | ||
|
||
The final step is to add the Livewire service provider to `providers` in `config/app.php`: | ||
|
||
```php | ||
'providers' => [ | ||
App\Providers\BotServiceProvider::class, | ||
Livewire\LivewireServiceProvider::class, | ||
], | ||
``` | ||
|
||
## Creating a Layout | ||
|
||
Before creating a component, you will need to create an `app.blade.php` layout for Livewire to use. You can create this using `livewire:layout`: | ||
|
||
```sh | ||
$ php laracord livewire:layout | ||
``` | ||
|
||
Once `app.blade.php` has been created, you will need to add the `@livewireStyles` and `@livewireScripts` Blade directives to the layout. | ||
|
||
Here is a full example including Tailwind's CDN since Laracord does not use node out of the box: | ||
|
||
```php | ||
<!DOCTYPE html> | ||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>{{ $title ?? 'Laracord' }}</title> | ||
|
||
<script src="https://cdn.tailwindcss.com"></script> | ||
@livewireStyles | ||
</head> | ||
<body> | ||
{{ $slot }} | ||
@livewireScripts | ||
</body> | ||
</html> | ||
``` | ||
|
||
## Message Component | ||
|
||
For this example, we will create a simple full page component. We can start by using the `make:livewire` console command: | ||
|
||
```sh | ||
$ php laracord make:livewire Message | ||
``` | ||
|
||
### Creating a Route | ||
|
||
After the component is created, we can create a route for it in `app/Bot.php`: | ||
|
||
```php | ||
<?php | ||
|
||
namespace App; | ||
|
||
use App\Livewire\Message; | ||
use Illuminate\Support\Facades\Route; | ||
use Laracord\Laracord; | ||
|
||
class Bot extends Laracord | ||
{ | ||
/** | ||
* The HTTP routes. | ||
*/ | ||
public function routes(): void | ||
{ | ||
Route::middleware('auth')->group(function () { | ||
Route::get('/message', Message::class); | ||
}); | ||
} | ||
} | ||
``` | ||
|
||
> #### Note | ||
> | ||
> It is strongly recommended to put routes behind the **auth** middleware if the bot is publicly accessible. See [HTTP Server Security](/docs/http-server#content-security) to learn more. | ||
### Creating the Component | ||
|
||
Once our route is configured, we can switch over to the Message component that was generated by `make:livewire` and add in the logic for the component: | ||
|
||
```php | ||
<?php | ||
|
||
namespace App\Livewire; | ||
|
||
use Laracord\HasLaracord; | ||
use Livewire\Attributes\Locked; | ||
use Livewire\Component; | ||
|
||
class Message extends Component | ||
{ | ||
use HasLaracord; | ||
|
||
/** | ||
* The selected user. | ||
* | ||
* @var string | ||
*/ | ||
public $user; | ||
|
||
/** | ||
* The message to send. | ||
* | ||
* @var string | ||
*/ | ||
public $message; | ||
|
||
/** | ||
* The Discord users. | ||
* | ||
* @var array | ||
*/ | ||
#[Locked] | ||
public $members; | ||
|
||
/** | ||
* Render the component. | ||
* | ||
* @return \Illuminate\View\View | ||
*/ | ||
public function render() | ||
{ | ||
$this->members = collect($this->discord()->users->map(fn ($user) => [ | ||
'id' => $user->id, | ||
'username' => $user->username, | ||
]))->keyBy('id'); | ||
|
||
return view('livewire.message'); | ||
} | ||
|
||
/** | ||
* Send a message to the selected user. | ||
* | ||
* @return void | ||
*/ | ||
public function sendMessage() | ||
{ | ||
$this->validate([ | ||
'user' => 'required', | ||
'message' => 'required|min:3|max:150', | ||
]); | ||
|
||
if (! $this->members->has($this->user)) { | ||
$this->addError('user', 'The selected user does not exist.'); | ||
|
||
return; | ||
} | ||
|
||
$this | ||
->message($this->message) | ||
->sendTo($this->user); | ||
|
||
$this->reset('message'); | ||
|
||
session()->flash('success', 'The message has been sent.'); | ||
} | ||
} | ||
``` | ||
|
||
Thanks to the `WithLaracord` trait, the methods we are used to using when writing commands are available in the Livewire component such as `bot()`, `discord()`, `console()`, and `message()`. | ||
|
||
Let's break down the above component. To start, we create our properties: | ||
|
||
- A **$user** property to wire to our **user** select. | ||
- A **$message** property to wire to our **message** textarea. | ||
- A [locked](https://livewire.laravel.com/docs/locked) **$members** property to hold the array of user's in the bot repository. | ||
|
||
In the `render()` method, we set our `members` property by mapping the Discord users by `id` and `username` and then keying them by `id`. Keying them by `id` will be convenient for validation. | ||
|
||
In the `sendMessage()` method, we start by using basic Laravel validation to check that the `user` and `message` are filled out and the `message` meets a generic minimum/maximum length. | ||
|
||
Once `validate()` passes, we do our own quick validation to ensure that the user attempting to be messaged is in the users list and hasn't been tampered with. | ||
|
||
Once validation is complete, we can send the message using the `message()` method similar to how we would in a command, reset the `message` textarea, and flash a `success` message. | ||
|
||
### Creating a View | ||
|
||
The component view is located in `resources/views/livewire/message.blade.php` and will be composed of a simple select dropdown, a textarea, and a send message button. I won't go into specifics for this one: | ||
|
||
```php | ||
<div class="max-w-2xl p-8 mx-auto"> | ||
<h1 class="mb-6 text-3xl">Send a Message</h1> | ||
|
||
<div class="grid gap-8"> | ||
<div> | ||
<select wire:model="user" class="w-full px-3 py-2 border"> | ||
<option value="">Select a member...</option> | ||
@foreach ($members as $member) | ||
<option value="{{ $member['id'] }}">{{ $member['username'] }}</option> | ||
@endforeach | ||
</select> | ||
|
||
@error('user') | ||
<div class="mt-1 text-red-500">{{ $message }}</div> | ||
@enderror | ||
</div> | ||
|
||
<div> | ||
<textarea | ||
class="w-full px-3 py-2 border" | ||
wire:model="message" | ||
rows="5" | ||
placeholder="Enter a message..." | ||
></textarea> | ||
|
||
@error('message') | ||
<div class="mt-1 text-red-500">{{ $message }}</div> | ||
@enderror | ||
</div> | ||
|
||
<button class="px-4 py-2 text-white bg-blue-500" wire:click="sendMessage"> | ||
Send Message | ||
</button> | ||
|
||
@session('success') | ||
<div class="px-4 py-3 text-green-700 bg-green-100 rounded"> | ||
<b>Success</b> | ||
<p>{{ session('success') }}</p> | ||
</div> | ||
@endsession | ||
</div> | ||
</div> | ||
``` | ||
|
||
Once your component is created, it should be ready and accessible at `localhost:8080/messages` by default once booting your bot. | ||
|
||
![Screenshot](/images/livewire-example.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.