Skip to content

Instantly share code, notes, and snippets.

@patrickcurl
Last active August 12, 2021 00:57
Show Gist options
  • Save patrickcurl/67ce7dd78604edeece3226b7b29aa902 to your computer and use it in GitHub Desktop.
Save patrickcurl/67ce7dd78604edeece3226b7b29aa902 to your computer and use it in GitHub Desktop.
Laravel Breeze Tutorial Register.vue
laravel new breezy
cd breezy
composer require laravel/breeze
php artisan breeze:install vue
# Or...
php artisan breeze:install react
npm install
npm run dev
php artisan migrate
# I also like to run vendor/publish and choose option 0 for publish all, this way I can override and control more in my application.
php artisan vendor:publish --all
<?php
// ...
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('username')->unique();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
<template>
<Head title="Log in" />
<BreezeValidationErrors class="mb-4" />
<div v-if="status" class="mb-4 text-sm font-medium text-green-600">
{{ status }}
</div>
<form @submit.prevent="submit">
<div>
<BreezeLabel for="login" value="Email / Username" />
<BreezeInput id="login" type="text" class="block w-full mt-1" v-model="form.login" required autofocus autocomplete="username" />
</div>
...
</template>
<script>
export default {
data() {
return {
form: this.$inertia.form({
login: '',
password: '',
remember: false
})
}
},
}
</script>
<?php
class LoginRequest extends FormRequest
{
protected $loginField;
protected $loginValue;
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->loginField = filter_var($this->input('login'),
FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
$this->loginValue = $this->input('login');
$this->merge([$this->loginField => $this->loginValue]);
}
<?php
// ...
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' =>
'required_without:username|string|email|exists:users,email',
'username' =>
'required_without:email|string|exists:users,username',
'password' => 'required|string',
];
}
<?php
/**
* Attempt to authenticate the request's credentials.
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
public function authenticate()
{
$this->ensureIsNotRateLimited();
if (!Auth::attempt(
$this->only($this->loginField, 'password'),
$this->boolean('remember')
))
{
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'login' => __('auth.failed')
]);
}
RateLimiter::clear($this->throttleKey());
}
<?php
public function store(Request $request)
{
$loginField = filter_var(
$request->input('login'), FILTER_VALIDATE_EMAIL)
? 'email'
: 'username';
$request->merge([$loginField => $request->input('login')]);
$request->validate([
'email' => 'required_without:username|email|exists:users,email',
'username' =>
'required_without:email|string|exists:users,username'
]);
$status = Password::sendResetLink(
$request->only($loginField)
);
if ($status == Password::RESET_LINK_SENT) {
return back()->with('status', __($status));
}
throw ValidationException::withMessages([
$loginField => [trans($status)],
]);
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutChangesToGlobalState="true"
beStrictAboutCoversAnnotation="true"
printerClass="Codedungeon\PHPUnitPrettyResultPrinter\Printer">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
<template>
<div>
<BreezeLabel for="username" value="Username" />
<BreezeInput id="username" type="text" class="mt-1 block w-full"
v-model="form.username" required autofocus autocomplete="username" />
</div>
...
</template>
<script>
export default {
data() {
return {
form: this.$inertia.form({
username: '',
email: '',
password: '',
password_confirmation: '',
terms: false,
})
}
},
}
</script>
<?php
public function store(Request $request){
$request->validate([
// 'name' => 'required|string|max:255',
'username' => 'required|string|max:255|unique:users',
'email' => 'required|string|email|max:255|unique:users',
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
// 'name' => $request->name,
'username' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
}
<?php
namespace Tests\Feature;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Inertia\Testing\Assert;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_registration_screen_can_be_rendered()
{
$response = $this->get('/register');
$response->assertStatus(200);
$response->assertInertia(fn (Assert $inertia) => $inertia->component('Auth/Register'));
}
<template>
<!-- Change THIS
<div>
<BreezeLabel for="email" value="Email" />
<BreezeInput id="email" type="email" class="mt-1 block w-full" v-model="form.email" required autofocus autocomplete="username" />
</div>
-->
<div>
<BreezeLabel for="login" value="Email / Username" />
<BreezeInput id="login" type="text" class="mt-1 block w-full" v-model="form.login" required autofocus autocomplete="username" />
</div>
</template>
<script>
export default {
props: {
login: String,
token: String,
},
data() {
return {
form: this.$inertia.form({
token: this.token,
login: this.login,
password: '',
password_confirmation: '',
})
}
},
}
</script>
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = User::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'username' => $this->faker->unique()->domainWord(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function unverified()
{
return $this->state(function (array $attributes) {
return [
'email_verified_at' => null,
];
});
}
}