https://codeexperts.com.br/curso/laravel-mastery
- Boas Vindas
- Ambiente
- Primeiros Passos Visão Geral
- Migrations, Seeders e Factories
- Eloquent
- Factories com Relacionamentos
- View: Laravel Blade
- View: Manipulação de Formulários
- Laravel Router
- Manipulando Validações
- Controllers como Recurso
- Primeiro Starter Point: Laravel UI
- Melhorias Projeto Eventos
- Upload de Arquivos
- Melhorias & Encerramento Bloco 1
- ACL & Autorização
01 - Seja Bem-Vindo
02 - Quem Sou Eu
03 - Ferramentas
-
PHP Storm Para estudantes, solicite em https://www.jetbrains.com/student/
-
Para open source, caso você contribua, solicite em https://www.jetbrains.com/community/opensource/
-
Visual Studio Code: https://code.visualstudio.com/
04 - Formas de Iniciar Projeto
- php 7.3+
$ php -m
[PHP Modules]
bcmath
ctype
fileinfo
json
mbstring
openssl
PDO
tokenizer
xml
05 - Laravel Installer OS X
06 - Laravel Installer Linux
07 - Laravel Installer Windows
$ composer global require laravel/installer
add PATH Composer e /laravel/bin/
laravel new projeto01
php artisan serve
- Choosing Your Sail Services
https://laravel.com/docs/11.x#choosing-your-sail-services
-
08 - Iniciando Projeto
-
Sail Services
$ curl -s "https://laravel.build/app3meuseventos?with=mysql" | bash
~/workspaces/Laravel-Mastery-CodeExperts/app3meuseventos on master!
$ sail up -d
[+] Running 4/4
✔ Network app3meuseventos_sail Created 0.1s
✔ Volume "app3meuseventos_sail-mysql" Created 0.1s
✔ Container app3meuseventos-mysql-1 Started 1.7s
✔ Container app3meuseventos-laravel.test-1 Started
- 09 - Diretórios Projeto
IA BING:
Aqui está um resumo das funções de cada pasta na estrutura de pastas do Laravel 10:
- app: Contém o código principal do seu aplicativo, incluindo controladores, middleware, solicitações e provedores¹.
- bootstrap: Contém o arquivo app.php que inicializa o framework. Este diretório também contém um diretório de cache que contém arquivos gerados pelo framework para otimização de desempenho¹.
- config: Como o nome indica, contém todos os arquivos de configuração do seu aplicativo¹.
- database: Contém suas migrações de banco de dados, fábricas de modelos e sementes¹.
- public: Contém o arquivo index.php, que é o ponto de entrada para todas as solicitações que entram no seu aplicativo e configura a autocarga. Este diretório também contém seus ativos, como imagens, JavaScript e CSS¹.
- resources: Contém suas visualizações, bem como seus ativos brutos e não compilados, como CSS ou JavaScript¹.
- routes: Contém todas as definições de rota para o seu aplicativo¹.
- storage: Contém seus logs, templates Blade compilados, sessões baseadas em arquivos, caches de arquivos e outros arquivos gerados pelo framework. Este diretório é segregado em diretórios de aplicativos, estrutura e logs¹.
- tests: (Não mencionado nos resultados da pesquisa)
- vendor: (Não mencionado nos resultados da pesquisa)
Origem: conversa com o Bing, 18/10/2023 (1) Directory Structure - Laravel 10.x - The PHP Framework For Web Artisans. https://laravel.com/docs/10.x/structure. (2) File Storage - Laravel 10.x - The PHP Framework For Web Artisans. https://laravel.com/docs/10.x/filesystem. (3) Laravel 10 Directory Structure in 2 minutes - AK. https://ashutosh.dev/laravel-10-directory-structure-in-2-minutes/.
A pasta App
no Laravel é onde são armazenados os arquivos e classes que compõem a aplicação Laravel, que segue o padrão MVC (Model-View-Controller). Ou seja, nela estarão os modelos, views (layouts) e controles que darão forma ao projeto². Em grande parte do desenvolvimentos estaremos trabalhando em tais arquivos, que representam a maior parcela de nosso código².
Infelizmente, não consegui encontrar informações específicas sobre a estrutura da pasta App
no Laravel 10. No entanto, a estrutura geralmente inclui as seguintes pastas e arquivos:
Http
: Esta pasta contém os controladores, middleware e solicitações de formulário. É um componente essencial na manipulação de solicitações HTTP e respostas no Laravel.Providers
: Esta pasta contém todos os provedores de serviços do aplicativo. Os provedores de serviços são a configuração central do aplicativo Laravel.Console
: Esta pasta contém todos os comandos Artisan gerados pelo usuário.Exceptions
: Esta pasta contém o manipulador de exceções do aplicativo.Jobs
: Esta pasta contém as filas do aplicativo.Listeners
: Esta pasta contém os manipuladores de eventos do aplicativo.Policies
: Esta pasta contém as políticas de autorização do aplicativo.
Por favor, verifique a documentação oficial do Laravel para obter informações mais detalhadas sobre a estrutura da pasta App
.
Origem: conversa com o Bing, 18/10/2023 (1) Laravel – Estrutura de Pastas (Projeto) - MGC Consulting. https://mgcconsulting.com.br/laravel-estrutura-de-pastas-projeto/. (2) O que faz a pasta storage no laravel? - Stack Overflow em Português. https://pt.stackoverflow.com/questions/462537/o-que-faz-a-pasta-storage-no-laravel. (3) Laravel Tutorial: Introdução ao Laravel Framework PHP - DevMedia. https://www.devmedia.com.br/laravel-tutorial/33173. (4) undefined. http://laravel.com/docs/structure.
- 10 - Panorama Inicial do Laravel
03-PrimeirosPassosVisaoGeral/proj-meuseventos-03-01/routes/web.php
Route::get('/', function () {
return view('welcome');
});
Route::get('/ola-mundo', function () {
return view('ola-mundo');
});
// Verbos HTTP: GET, POST, PUT, PATCH, DELETE e Options
03-PrimeirosPassosVisaoGeral/proj-meuseventos-03-01/resources/views/ola-mundo.blade.php
- 11 - Parâmetros Dinâmicos Rota
Route::get('/ola/{name?}', function ($name = 'Fulano...') {
return 'Olá, ' . $name;
});
- 12 - Rotas & Controllers
$ sail php artisan make:controller HellowWordController
INFO Controller [app/Http/Controllers/HellowWordController.php] created successfully.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HelloWorldController extends Controller
{
public function helloWorld()
{
return view('ola-mundo');
}
public function hello($name = 'Fulano')
{
return 'Olá, ' . $name;
}
}
Route::get('/ola-mundo', [\App\Http\Controllers\HelloWorldController::class, 'helloWorld']);
// Verbos HTTP: GET, POST, PUT, PATCH, DELETE e Options
Route::get('/ola/{name?}', [\App\Http\Controllers\HelloWorldController::class, 'hello']);
- 13 - O Artisan
$ sail php artisan list
Laravel Framework 10.28.0
Usage:
command [options] [arguments]
Options:
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
--env[=ENV] The environment the command should run under
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
about Display basic information about your application
clear-compiled Remove the compiled class file
completion Dump the shell completion script
db Start a new database CLI session
docs Access the Laravel documentation
down Put the application into maintenance / demo mode
env Display the current framework environment
help Display help for a command
inspire Display an inspiring quote
list List commands
migrate Run the database migrations
optimize Cache the framework bootstrap files
serve Serve the application on the PHP development server
test Run the application tests
tinker Interact with your application
up Bring the application out of maintenance mode
auth
auth:clear-resets Flush expired password reset tokens
cache
cache:clear Flush the application cache
cache:forget Remove an item from the cache
cache:prune-stale-tags Prune stale cache tags from the cache (Redis only)
cache:table Create a migration for the cache database table
channel
channel:list List all registered private broadcast channels
config
config:cache Create a cache file for faster configuration loading
config:clear Remove the configuration cache file
config:show Display all of the values for a given configuration file
db
db:monitor Monitor the number of connections on the specified database
db:seed Seed the database with records
db:show Display information about the given database
db:table Display information about the given database table
db:wipe Drop all tables, views, and types
env
env:decrypt Decrypt an environment file
env:encrypt Encrypt an environment file
event
event:cache Discover and cache the application's events and listeners
event:clear Clear all cached events and listeners
event:generate Generate the missing events and listeners based on registration
event:list List the application's events and listeners
key
key:generate Set the application key
lang
lang:publish Publish all language files that are available for customization
make
make:cast Create a new custom Eloquent cast class
make:channel Create a new channel class
make:command Create a new Artisan command
make:component Create a new view component class
make:controller Create a new controller class
make:event Create a new event class
make:exception Create a new custom exception class
make:factory Create a new model factory
make:job Create a new job class
make:listener Create a new event listener class
make:mail Create a new email class
make:middleware Create a new middleware class
make:migration Create a new migration file
make:model Create a new Eloquent model class
make:notification Create a new notification class
make:observer Create a new observer class
make:policy Create a new policy class
make:provider Create a new service provider class
make:request Create a new form request class
make:resource Create a new resource
make:rule Create a new validation rule
make:scope Create a new scope class
make:seeder Create a new seeder class
make:test Create a new test class
make:view Create a new view
migrate
migrate:fresh Drop all tables and re-run all migrations
migrate:install Create the migration repository
migrate:refresh Reset and re-run all migrations
migrate:reset Rollback all database migrations
migrate:rollback Rollback the last database migration
migrate:status Show the status of each migration
model
model:prune Prune models that are no longer needed
model:show Show information about an Eloquent model
notifications
notifications:table Create a migration for the notifications table
optimize
optimize:clear Remove the cached bootstrap files
package
package:discover Rebuild the cached package manifest
queue
queue:batches-table Create a migration for the batches database table
queue:clear Delete all of the jobs from the specified queue
queue:failed List all of the failed queue jobs
queue:failed-table Create a migration for the failed queue jobs database table
queue:flush Flush all of the failed queue jobs
queue:forget Delete a failed queue job
queue:listen Listen to a given queue
queue:monitor Monitor the size of the specified queues
queue:prune-batches Prune stale entries from the batches database
queue:prune-failed Prune stale entries from the failed jobs table
queue:restart Restart queue worker daemons after their current job
queue:retry Retry a failed queue job
queue:retry-batch Retry the failed jobs for a batch
queue:table Create a migration for the queue jobs database table
queue:work Start processing jobs on the queue as a daemon
route
route:cache Create a route cache file for faster route registration
route:clear Remove the route cache file
route:list List all registered routes
sail
sail:add Add a service to an existing Sail installation
sail:install Install Laravel Sail's default Docker Compose file
sail:publish Publish the Laravel Sail Docker files
sanctum
sanctum:prune-expired Prune tokens expired for more than specified number of hours
schedule
schedule:clear-cache Delete the cached mutex files created by scheduler
schedule:interrupt Interrupt the current schedule run
schedule:list List all scheduled tasks
schedule:run Run the scheduled commands
schedule:test Run a scheduled command
schedule:work Start the schedule worker
schema
schema:dump Dump the given database schema
session
session:table Create a migration for the session database table
storage
storage:link Create the symbolic links configured for the application
stub
stub:publish Publish all stubs that are available for customization
vendor
vendor:publish Publish any publishable assets from vendor packages
view
view:cache Compile all of the application's Blade templates
view:clear Clear all compiled view files
$ sail php artisan make:controller --help
Description:
Create a new controller class
Usage:
make:controller [options] [--] <name>
Arguments:
name The name of the controller
Options:
--api Exclude the create and edit methods from the controller
--type=TYPE Manually specify the controller stub file to use
--force Create the class even if the controller already exists
-i, --invokable Generate a single method, invokable controller class
-m, --model[=MODEL] Generate a resource controller for the given model
-p, --parent[=PARENT] Generate a nested resource controller class
-r, --resource Generate a resource controller class
-R, --requests Generate FormRequest classes for store and update
-s, --singleton Generate a singleton resource controller class
--creatable Indicate that a singleton resource should be creatable
--test Generate an accompanying PHPUnit test for the Controller
--pest Generate an accompanying Pest test for the Controller
-h, --help Display help for the given command. When no command is given display help for the list command
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi|--no-ansi Force (or disable --no-ansi) ANSI output
-n, --no-interaction Do not ask any interactive question
--env[=ENV] The environment the command should run under
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
-
14 - Entendendo as Configurações
-
15 - Migrations
-
16 - Executando Migrations
$ sail php artisan migrate:install
INFO Migration table created successfully.
$ sail php artisan migrate
INFO Running migrations.
2014_10_12_000000_create_users_table ........................... 49ms DONE
2014_10_12_100000_create_password_reset_tokens_table ........... 52ms DONE
2019_08_19_000000_create_failed_jobs_table ..................... 36ms DONE
2019_12_14_000001_create_personal_access_tokens_table .......... 57ms DONE
- 17 - Criando Primeira Migração
$ sail php artisan make:migration create_events_table
INFO Migration [database/migrations/2024_01_05_212259_create_events_table.php] created successfully.
public function up()
{
Schema::create('events', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('description');
$table->timestamps();
});
}
$ sail php artisan migrate
INFO Running migrations.
2024_01_05_212259_create_events_table ...................... 27ms DONE
-
18 - Os Models
-
app2meuseventos/app/Models/User.php
class User extends Authenticatable
{
// protected $table = 'usuarios'; // Caso use outro nome na tabela
$ sail php artisan make:model Event
INFO Model [app/Models/Event.php] created successfully.
-03-PrimeirosPassosVisaoGeral/proj-meuseventos-03-01/app/Models/Event.php
- 19 - O Eloquent e Queries
Route::get('/queries/{id}', function ($id) {
// $events = \App\Models\Event::all(); // select * from events
// $events = \App\Models\Event::all(['title', 'description']); // select title, description from events
// $events = \App\Models\Event::where('id', 1)->get(); // select * from events WHERE id = 1
// $events = \App\Models\Event::where('id', 1)->first(); // select * from events WHERE id = 1
$events = \App\Models\Event::find($id); // select * from events WHERE id = 1
return $events;
});
- 20 - O Tinker
$ sail php artisan tinker
Psy Shell v0.10.12 (PHP 7.4.19 — cli) by Justin Hileman
>>>
$ php artisan tinker
Psy Shell v0.10.12 (PHP 7.4.19 — cli) by Justin Hileman
>>> \App\Models\Event::all();
=> Illuminate\Database\Eloquent\Collection {#4263
all: [
App\Models\Event {#4265
id: 1,
title: "Evento Teste",
description: "Descrição de Teste do evento",
created_at: "2021-12-08 21:29:23",
updated_at: "2021-12-08 21:29:25",
},
App\Models\Event {#4264
id: 2,
title: "Evento Teste 2",
description: "Descrição 2 de Teste do evento",
created_at: "2021-12-07 21:29:23",
updated_at: "2021-12-08 21:29:25",
},
],
}
>>> \App\Models\Event::where('id', 1)->first();
=> App\Models\Event {#3533
id: 1,
title: "Evento Teste",
description: "Descrição de Teste do evento",
created_at: "2021-12-08 21:29:23",
updated_at: "2021-12-08 21:29:25",
}
>>>
-
21 - Assets Frontend
$ sail npm i
$ sail npm run dev
-
22 - Conclusões
-
23 Introdução
-
24 Seeders e Factories
-
25 Executando Seeds e Factories
https://github.com/fzaninotto/Faker
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
-03-PrimeirosPassosVisaoGeral/projMeusEventos/database/seeders/DatabaseSeeder.php
public function run()
{
\App\Models\User::factory(10)->create();
}
$ sail php artisan db:seed
INFO Seeding database.
- 26 Primeira Factory e Seeds
$ sail php artisan make:factory EventFactory
Factory created successfully.
public function definition()
{
return [
'title' => $this->faker->sentence,
'description' => $this->faker->words(7, true),
];
}
public function run()
{
// \App\Models\User::factory(10)->create();
\App\Models\Event::factory(30)->create();
}
}
$ sail php artisan db:seed
INFO Seeding database.
$ sail php artisan make:seeder UsersTableSeeder
INFO Seeder [database/seeders/UsersTableSeeder.php] created successfully.
$ sail php artisan make:seeder EventsTableSeeder
INFO Seeder [database/seeders/EventsTableSeeder.php] created successfully.
- app2meuseventos/database/seeders/EventsTableSeeder.php
- app2meuseventos/database/seeders/UsersTableSeeder.php
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// \App\Models\User::factory(10)->create();
// \App\Models\Event::factory(30)->create();
$this->call(UsersTableSeeder::class);
$this->call(EventsTableSeeder::class);
}
}
class EventsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
\App\Models\Event::factory(30)->create();
}
}
$ sail php artisan db:seed
INFO Seeding database.
Database\Seeders\UsersTableSeeder ...................... RUNNING
Database\Seeders\UsersTableSeeder ................ 83.20 ms DONE
Database\Seeders\EventsTableSeeder ..................... RUNNING
Database\Seeders\EventsTableSeeder .............. 122.09 ms DONE
- 27 Comandos Fresh e Refresh
$ sail php artisan migrate:status
Migration name ........................................................ Batch / Status
2014_10_12_000000_create_users_table ......................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table ......................... [1] Ran
2019_08_19_000000_create_failed_jobs_table ................................... [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ........................ [1] Ran
2024_01_05_212259_create_events_table ........................................ [2] Ran
$ sail php artisan migrate:refresh
INFO Rolling back migrations.
2024_01_05_212259_create_events_table ...................................... 19ms DONE
2019_12_14_000001_create_personal_access_tokens_table ...................... 14ms DONE
2019_08_19_000000_create_failed_jobs_table ................................. 10ms DONE
2014_10_12_100000_create_password_reset_tokens_table ....................... 11ms DONE
2014_10_12_000000_create_users_table ....................................... 11ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table ........................................... 36ms DONE
2014_10_12_100000_create_password_reset_tokens_table ........................... 50ms DONE
2019_08_19_000000_create_failed_jobs_table ..................................... 37ms DONE
2019_12_14_000001_create_personal_access_tokens_table .......................... 54ms DONE
2024_01_05_212259_create_events_table .......................................... 23ms DONE
$ sail php artisan migrate:status
Migration name .................................................... Batch / Status
2014_10_12_000000_create_users_table ..................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table ..................... [1] Ran
2019_08_19_000000_create_failed_jobs_table ............................... [1] Ran
2019_12_14_000001_create_personal_access_tokens_table .................... [1] Ran
2024_01_05_212259_create_events_table .................................... [1] Ran
migrate:refresh - Desfaz tudo que está descrito nas migrations
$ sail php artisan migrate:refresh --seed
INFO Rolling back migrations.
2024_01_05_212259_create_events_table .................................... 15ms DONE
2019_12_14_000001_create_personal_access_tokens_table .................... 15ms DONE
2019_08_19_000000_create_failed_jobs_table ............................... 11ms DONE
2014_10_12_100000_create_password_reset_tokens_table ..................... 14ms DONE
2014_10_12_000000_create_users_table ..................................... 12ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table ................................. 38ms DONE
2014_10_12_100000_create_password_reset_tokens_table ................. 50ms DONE
2019_08_19_000000_create_failed_jobs_table ........................... 35ms DONE
2019_12_14_000001_create_personal_access_tokens_table ................ 48ms DONE
2024_01_05_212259_create_events_table ................................ 21ms DONE
INFO Seeding database.
Database\Seeders\UsersTableSeeder .............................. RUNNING
Database\Seeders\UsersTableSeeder ........................ 80.81 ms DONE
Database\Seeders\EventsTableSeeder ........................ RUNNING
Database\Seeders\EventsTableSeeder ................. 118.96 ms DONE
- migrate:fresh - Apaga todo o banco e refaz. Apaga outras tabelas que não estão na migrations.
$ sail php artisan migrate:fresh --seed
Dropping all tables ................................... 56ms DONE
INFO Preparing database.
Creating migration table .................................. 37ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table .................................... 40ms DONE
2014_10_12_100000_create_password_reset_tokens_table .................... 51ms DONE
2019_08_19_000000_create_failed_jobs_table .............................. 39ms DONE
2019_12_14_000001_create_personal_access_tokens_table ................... 55ms DONE
2024_01_05_212259_create_events_table ................................... 23ms DONE
INFO Seeding database.
Database\Seeders\UsersTableSeeder .................................... RUNNING
Database\Seeders\UsersTableSeeder .............................. 57.50 ms DONE
Database\Seeders\EventsTableSeeder .................... RUNNING
Database\Seeders\EventsTableSeeder ............. 109.59 ms DONE
- 28 Comando Rollback e Reset
$ sail php artisan migrate:status
Migration name ........................................................... Batch / Status
2014_10_12_000000_create_users_table ............................................ [1] Ran
2014_10_12_100000_create_password_reset_tokens_table ............................ [1] Ran
2019_08_19_000000_create_failed_jobs_table ...................................... [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ........................... [1] Ran
2024_01_05_212259_create_events_table ........................................... [1] Ran
$ sail php artisan migrate:rollback
INFO Rolling back migrations.
2024_01_05_212259_create_events_table .................................... 17ms DONE
2019_12_14_000001_create_personal_access_tokens_table .................... 12ms DONE
2019_08_19_000000_create_failed_jobs_table ............................... 12ms DONE
2014_10_12_100000_create_password_reset_tokens_table ..................... 12ms DONE
2014_10_12_000000_create_users_table ..................................... 13ms DONE
$ sail php artisan migrate:status
Migration name ...................................................... Batch / Status
2014_10_12_000000_create_users_table ....................................... Pending
2014_10_12_100000_create_password_reset_tokens_table ....................... Pending
2019_08_19_000000_create_failed_jobs_table ................................. Pending
2019_12_14_000001_create_personal_access_tokens_table ...................... Pending
2024_01_05_212259_create_events_table ...................................... Pending
$ sail php artisan migrate
(...)
$ sail php artisan migrate:status
Migration name ......................................................... Batch / Status
2014_10_12_000000_create_users_table .......................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table .......................... [1] Ran
2019_08_19_000000_create_failed_jobs_table .................................... [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ......................... [1] Ran
2024_01_05_212259_create_events_table ......................................... [2] Ran
$ sail php artisan migrate:rollback
INFO Rolling back migrations.
2024_01_05_212259_create_events_table ............ 16ms DONE
$ sail php artisan migrate:status
Migration name ...................................................... Batch / Status
2014_10_12_000000_create_users_table ....................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table ....................... [1] Ran
2019_08_19_000000_create_failed_jobs_table ................................. [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ...................... [1] Ran
2024_01_05_212259_create_events_table ...................................... Pending
$ sail php artisan migrate
INFO Running migrations.
2024_01_05_212259_create_events_table ......................... 22ms DONE
$ sail php artisan migrate:status
Migration name ...................................................... Batch / Status
2014_10_12_000000_create_users_table ....................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table ....................... [1] Ran
2019_08_19_000000_create_failed_jobs_table ................................. [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ...................... [1] Ran
2024_01_05_212259_create_events_table ...................................... [2] Ran
$ sail php artisan migrate:rollback --step=2
INFO Rolling back migrations.
2024_01_05_212259_create_events_table .................................................................................................. 14ms DONE
2019_12_14_000001_create_personal_access_tokens_table .................................................................................. 10ms DONE
$ sail php artisan migrate:status
Migration name ................................................. Batch / Status
2014_10_12_000000_create_users_table .................................. [1] Ran
2014_10_12_100000_create_password_reset_tokens_table .................. [1] Ran
2019_08_19_000000_create_failed_jobs_table ............................ [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ................. Pending
2024_01_05_212259_create_events_table ................................. Pending
$ sail php artisan migrate:reset
INFO Rolling back migrations.
2019_08_19_000000_create_failed_jobs_table .................................. 16ms DONE
2014_10_12_100000_create_password_reset_tokens_table ......................... 9ms DONE
2014_10_12_000000_create_users_table ........................................ 12ms DONE
$ sail php artisan migrate:status
Migration name ......................................................... Batch / Status
2014_10_12_000000_create_users_table .......................................... Pending
2014_10_12_100000_create_password_reset_tokens_table .......................... Pending
2019_08_19_000000_create_failed_jobs_table .................................... Pending
2019_12_14_000001_create_personal_access_tokens_table ......................... Pending
2024_01_05_212259_create_events_table ......................................... Pending
-
29 Falando Sobre Migrações
-
30 Uma Migração de Edição
$ sail php artisan make:migration alter_events_table_add_columnslug --table=events
INFO Migration [database/migrations/2024_02_01_144727_alter_events_table_add_columnslug.php] created successfully.
public function up()
{
Schema::table('events', function (Blueprint $table) {
$table->string('slug')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('events', function (Blueprint $table) {
$table->dropColumn('slug');
});
}
-https://laravel.com/docs/8.x/migrations#available-column-types
$ sail php artisan migrate:status
Migration name .................................................. Batch / Status
2014_10_12_000000_create_users_table ................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table ................... [1] Ran
2019_08_19_000000_create_failed_jobs_table ............................. [1] Ran
2019_12_14_000001_create_personal_access_tokens_table .................. [1] Ran
2024_01_05_212259_create_events_table .................................. [1] Ran
2024_02_01_144727_alter_events_table_add_columnslug .................... Pending
$ sail php artisan migrate
INFO Running migrations.
2024_02_01_144727_alter_events_table_add_columnslug ................. 18ms DONE
$ sail php artisan migrate:status
Migration name ................................................... Batch / Status
2014_10_12_000000_create_users_table .................................... [1] Ran
2014_10_12_100000_create_password_reset_tokens_table .................... [1] Ran
2019_08_19_000000_create_failed_jobs_table .............................. [1] Ran
2019_12_14_000001_create_personal_access_tokens_table ................... [1] Ran
2024_01_05_212259_create_events_table ................................... [1] Ran
2024_02_01_144727_alter_events_table_add_columnslug ..................... [2] Ran
- 31 Schema Dump
Carrega primeiro o Dump, depois ele parte para migrations.
$ sail php artisan schema:dump
mysqldump: [Warning] Using a password on the command line interface can be insecure.
INFO Database schema dumped successfully.
REMOVER todas as migrações:
$ sail php artisan schema:dump --prune
Preferencialmente o Laravel usa o schema para montar o banco:
$ sail php artisan migrate:refresh --seed
INFO Rolling back migrations.
2024_02_01_144727_alter_events_table_add_columnslug .............. 17ms DONE
2024_01_05_212259_create_events_table ............................ 11ms DONE
2019_12_14_000001_create_personal_access_tokens_table ............ 13ms DONE
2019_08_19_000000_create_failed_jobs_table ....................... 11ms DONE
2014_10_12_100000_create_password_reset_tokens_table ............. 11ms DONE
2014_10_12_000000_create_users_table ............................. 10ms DONE
INFO Loading stored database schemas.
database/schema/mysql-schema.sql .................................... 203ms DONE
INFO Nothing to migrate.
INFO Seeding database.
Database\Seeders\UsersTableSeeder ............................................. RUNNING
Database\Seeders\UsersTableSeeder ....................................... 58.65 ms DONE
Database\Seeders\EventsTableSeeder .............................. RUNNING
Database\Seeders\EventsTableSeeder ....................... 118.02 ms DONE
- 32 Conclusões
- 33 Introdução
- 34 Relembrando Models
- 35 Active Record Inserção
Route::get('/queries/{event?}', function ($event = null){
$event = new \App\Models\Event();
$event->title = 'Evento TESTE via Eloquent e AR';
$event->description = 'Evento teste';
$event->body = 'corpo do evento';
$event->start_event = date('Y-m-d H:i:s');
$event->slug = \Illuminate\Support\Str::slug($event->title);
return $event->save();
});
- 36 Active Record Atualização
Route::get('/queries/{event?}', function ($event = null){
$event = \App\Models\Event::find(8);
$event->title = 'Evento ATUALIZADO';
$event->slug = \Illuminate\Support\Str::slug($event->title);
return $event->save();
});
- 37 Mass Assignment Criação
Route::get('/queries/{event?}', function ($event = null){
// Atribuição Massa ou Mass Assingnment
$event = [
'title' => 'Evento Atribuição em Massa',
'description' => 'Descrição',
'body' => 'Conteudo do Evento',
'slug' => 'evento-atribuicao-em-massa',
'start_event' => date('Y-m-d H:i:s')
];
return \App\Models\Event::create($event);
});
class Event extends Model
{
use HasFactory;
protected $fillable = [
'title',
'description',
'body',
'slug',
'start_event'
];
}
- 38 Update em Massa
Route::get('/queries/{event?}', function ($event = null){
$eventDATA = [
// 'title' => 'Evento Atribuição em Massa',
'description' => 'Descrição ATUALIZADA',
// 'body' => 'Conteudo do Evento',
// 'slug' => 'evento-atribuicao-em-massa',
// 'start_event' => date('Y-m-d H:i:s')
];
$event = \App\Models\Event::find(9);
$event->update($eventDATA);
return $event;
});
- 39 Removendo Dados
$event = \App\Models\Event::findOrFail(9);
return $event->delete(); // 1
return \App\Models\Event::destroy([8,7,6]); // 3
- 40 Organizando CRUD
visão geral!
$ sail php artisan make:controller EventController
INFO Controller [app/Http/Controllers/EventController.php] created successfully.
- 41 Prelúdio Relacionamentos
- 42 Migração Tabela Perfil
$ sail php artisan make:model Profile -m
INFO Model [app/Models/Profile.php] created successfully.
INFO Migration [database/migrations/2024_02_11_204449_create_profiles_table.php] created successfully.
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
// user_id (conter a chave estrangeira) && a chave estrangeira ela tem um padrão:
// profiles_user_id_foreign
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->text('about')->nullable();
$table->string('phone', 15)->nullable();
$table->text('social_networks')->nullable();
$table->timestamps();
// Definindo chave estrangeira anterior ao laravel 7
// $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
$ sail php artisan migrate
INFO Running migrations.
2024_02_11_204449_create_profiles_table ............... 115ms DONE
- 43 Mapeando 1:1 Models
lass User extends Authenticatable
{
// (...)
// Representa a ligação entre o Model User E Model Profile
// e indica que USER tem um Profile
public function profile()
{
// automaticamente procura por esta coluna: user_id em profiles
return $this->hasOne(Profile::class);
// return $this->hasOne(Profile::class, 'usuario_id'); // outro parametro
}
class Profile extends Model
{
use HasFactory;
public function user()
{
// por conta do nome do método que a coluna é user_id
return $this->belongsTo(User::class);
// return $this->belongsTo(User::class, 'usuario_id', 'codigo');
}
}
- 44 Salvando 1:1
>>> $profile2 = new \App\Models\Profile();
=> App\Models\Profile {#4458}
>>> $profile2->about = 'Sobre Mim'
=> "Sobre Mim"
>>> $profile2->social_networks = 'faceboo';
=> "faceboo"
>>> $profile2->phone = '9999999';
=> "9999999"
>>> $user = \App\Models\User::find(2);
=> App\Models\User {#3535
id: 2,
name: "Lizeth Rodriguez",
email: "[email protected]",
email_verified_at: "2022-07-01 02:06:50",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "2Pr0peZR1v",
created_at: "2022-07-01 02:06:50",
updated_at: "2022-07-01 02:06:50",
}
>>> $user->profile()->save($profile2)
=> App\Models\Profile {#4458
about: "Sobre Mim",
social_networks: "faceboo",
phone: "9999999",
user_id: 2,
updated_at: "2022-07-02 01:47:02",
created_at: "2022-07-02 01:47:02",
id: 2,
}
>>> $user = \App\Models\User::find(3)
=> App\Models\User {#3847
id: 3,
name: "Miss Dessie Green DVM",
email: "[email protected]",
email_verified_at: "2022-07-01 02:06:50",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "5RHM4dp9Q8",
created_at: "2022-07-01 02:06:50",
updated_at: "2022-07-01 02:06:50",
}
>>> $p = [ 'about'=>'sobre mim', 'phone'=>'8888', 'social_networks'=>'twitter' ];
=> [
"about" => "sobre mim",
"phone" => "8888",
"social_networks" => "twitter",
]
(cont...)
class Profile extends Model
{
use HasFactory;
protected $fillable = ['about', 'phone' , 'social_networks'];
public function user()
{
// por conta do nome do método que a coluna é user_id
return $this->belongsTo(User::class);
// return $this->belongsTo(User::class, 'usuario_id', 'codigo');
}
}
> $user->profile()->create($p);
= App\Models\Profile {#7224
about: "sobre mim",
phone: "8888",
social_networks: "twitter",
user_id: 2,
updated_at: "2024-02-11 21:35:42",
created_at: "2024-02-11 21:35:42",
id: 2,
}
- 45 Recuperando 1:1
>>> $u = \App\Models\User::find(1);
=> App\Models\User {#3849
id: 1,
name: "Sibyl Runolfsson",
email: "[email protected]",
email_verified_at: "2022-07-01 02:06:50",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "0YP0lcIM4e",
created_at: "2022-07-01 02:06:50",
updated_at: "2022-07-01 02:06:50",
}
>>> $u->profile();
=> Illuminate\Database\Eloquent\Relations\HasOne {#3525}
>>> $u->profile;
=> App\Models\Profile {#4209
id: 1,
user_id: 1,
about: "Sobre Mim",
phone: "9999999",
social_networks: "facebook, google, twitter",
created_at: "2022-07-02 01:43:02",
updated_at: "2022-07-02 01:43:02",
}
>>> $u->profile()->get();
=> Illuminate\Database\Eloquent\Collection {#4457
all: [
App\Models\Profile {#4458
id: 1,
user_id: 1,
about: "Sobre Mim",
phone: "9999999",
social_networks: "facebook, google, twitter",
created_at: "2022-07-02 01:43:02",
updated_at: "2022-07-02 01:43:02",
},
],
}
>>> $unot = \App\Models\User::find(4);
=> App\Models\User {#4461
id: 4,
name: "Dr. Brisa Pacocha",
email: "[email protected]",
email_verified_at: "2022-07-01 02:06:50",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "nhEcg5geys",
created_at: "2022-07-01 02:06:50",
updated_at: "2022-07-01 02:06:50",
}
>>> $unot->profile;
=> null
>>> $unot->profile()->exists();
=> false
>>> $p = \App\Models\Profile::find(1)
=> App\Models\Profile {#3530
id: 1,
user_id: 1,
about: "Sobre Mim",
phone: "9999999",
social_networks: "facebook, google, twitter",
created_at: "2022-07-02 01:43:02",
updated_at: "2022-07-02 01:43:02",
}
>>> $p->user()->first();
=> App\Models\User {#4466
id: 1,
name: "Sibyl Runolfsson",
email: "[email protected]",
email_verified_at: "2022-07-01 02:06:50",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "0YP0lcIM4e",
created_at: "2022-07-01 02:06:50",
updated_at: "2022-07-01 02:06:50",
}
>>> $p->user
=> App\Models\User {#4468
id: 1,
name: "Sibyl Runolfsson",
email: "[email protected]",
email_verified_at: "2022-07-01 02:06:50",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "0YP0lcIM4e",
created_at: "2022-07-01 02:06:50",
updated_at: "2022-07-01 02:06:50",
}
>>> $p->user->name
=> "Sibyl Runolfsson"
- 46 Migração 1:N
$ sail php artisan make:model Photo -m
INFO Model [app/Models/Photo.php] created successfully.
INFO Migration [database/migrations/2024_02_11_215818_create_photos_table.php] created successfully.
public function up()
{
Schema::create('photos', function (Blueprint $table) {
$table->id();
$table->foreignId('event_id')->constrained()->cascadeOnDelete();
$table->string('photo');
$table->timestamps();
});
}
- 47 Mapeando 1:N Models
class Photo extends Model
{
use HasFactory;
protected $fillable = ['photo'];
public function event()
{
return $this->belongsTo(Event::class);
}
}
class Event extends Model
{
use HasFactory;
protected $fillable = [
'title',
'description',
'body',
'slug',
'start_event'
];
public function photos()
{
return $this->hasMany(Photo::class);// event_id
}
}
- 48 Salvando 1:N
>>> $photo = ['photo'=> 'imagem.jpg'];
=> [
"photo" => "imagem.jpg",
]
>>> \App\Models\Event::find(1);
=> App\Models\Event {#3847
id: 1,
title: "Nisi error quia voluptas modi.",
description: "quibusdam a voluptates animi vel consequatur expedita",
body: "Sunt nam magnam tempora dicta iure enim. Soluta harum qui expedita sed repellendus. Repellat veniam hic qui asperiores ratione voluptas sint et.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "nisi-error-quia-voluptas-modi",
}
>>> \App\Models\Event::find(1)->photos()->create($photo);
=> App\Models\Photo {#4454
photo: "imagem.jpg",
event_id: 1,
updated_at: "2022-07-02 20:51:54",
created_at: "2022-07-02 20:51:54",
id: 1,
}
>>> $photo = new \App\Models\Photo();
=> App\Models\Photo {#4457}
>>> $photo->photo = 'imagem2.jpg';
=> "imagem2.jpg"
>>> \App\Models\Event::find(1)->photos()->save($photo);
=> App\Models\Photo {#4457
photo: "imagem2.jpg",
event_id: 1,
updated_at: "2022-07-02 20:55:52",
created_at: "2022-07-02 20:55:52",
id: 2,
}
>>> namespace App\Models
>>> $photo1 = new Photo();
=> App\Models\Photo {#4458}
>>> $photo1->photo = 'exemplo-1.jpg'
=> "exemplo-1.jpg"
>>> $photo2 = new Photo();
=> App\Models\Photo {#4456}
>>> $photo2->photo = 'exemplo-2.jpg'
=> "exemplo-2.jpg"
>>> $photos = [$photo1, $photo2];
=> [
App\Models\Photo {#4458
photo: "exemplo-1.jpg",
},
App\Models\Photo {#4456
photo: "exemplo-2.jpg",
},
]
>>> Event::find(2)->photos()->saveMany($photos);
=> [
App\Models\Photo {#4458
photo: "exemplo-1.jpg",
event_id: 2,
updated_at: "2022-07-02 21:00:57",
created_at: "2022-07-02 21:00:57",
id: 3,
},
App\Models\Photo {#4456
photo: "exemplo-2.jpg",
event_id: 2,
updated_at: "2022-07-02 21:00:57",
created_at: "2022-07-02 21:00:57",
id: 4,
},
]
>>> $photo1 = ['photo' => 'foto-ok-01.jpg'];
=> [
"photo" => "foto-ok-01.jpg",
]
>>> $photo2 = ['photo' => 'foto-ok-02.jpg'];
=> [
"photo" => "foto-ok-02.jpg",
]
>>> $photos = [$photo1, $photo2];
=> [
[
"photo" => "foto-ok-01.jpg",
],
[
"photo" => "foto-ok-02.jpg",
],
]
>>> Event::find(3)->photos()->createMany($photos);
=> Illuminate\Database\Eloquent\Collection {#4459
all: [
App\Models\Photo {#4466
photo: "foto-ok-01.jpg",
event_id: 3,
updated_at: "2022-07-02 21:18:22",
created_at: "2022-07-02 21:18:22",
id: 5,
},
App\Models\Photo {#4462
photo: "foto-ok-02.jpg",
event_id: 3,
updated_at: "2022-07-02 21:18:22",
created_at: "2022-07-02 21:18:22",
id: 6,
},
],
}
- 49 Recuperando 1:N
>>> $event = Event::find(1);
=> App\Models\Event {#4458
id: 1,
title: "Nisi error quia voluptas modi.",
description: "quibusdam a voluptates animi vel consequatur expedita",
body: "Sunt nam magnam tempora dicta iure enim. Soluta harum qui expedita sed repellendus. Repellat veniam hic qui asperiores ratione voluptas sint et.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "nisi-error-quia-voluptas-modi",
}
>>> $event->photos
=> Illuminate\Database\Eloquent\Collection {#4462
all: [
App\Models\Photo {#4468
id: 1,
event_id: 1,
photo: "imagem.jpg",
created_at: "2022-07-02 20:51:54",
updated_at: "2022-07-02 20:51:54",
},
App\Models\Photo {#4473
id: 2,
event_id: 1,
photo: "imagem2.jpg",
created_at: "2022-07-02 20:55:52",
updated_at: "2022-07-02 20:55:52",
},
],
}
>>> $event->photos()
=> Illuminate\Database\Eloquent\Relations\HasMany {#4459}
>>> $event->photos()->get();
=> Illuminate\Database\Eloquent\Collection {#4472
all: [
App\Models\Photo {#4478
id: 1,
event_id: 1,
photo: "imagem.jpg",
created_at: "2022-07-02 20:51:54",
updated_at: "2022-07-02 20:51:54",
},
App\Models\Photo {#4481
id: 2,
event_id: 1,
photo: "imagem2.jpg",
created_at: "2022-07-02 20:55:52",
updated_at: "2022-07-02 20:55:52",
},
],
}
>>> $event->photos()->limit(1)->get();
=> Illuminate\Database\Eloquent\Collection {#4474
all: [
App\Models\Photo {#4476
id: 1,
event_id: 1,
photo: "imagem.jpg",
created_at: "2022-07-02 20:51:54",
updated_at: "2022-07-02 20:51:54",
},
],
}
>>> $event->photos()->orderBy('id', 'desc')->get();
=> Illuminate\Database\Eloquent\Collection {#3525
all: [
App\Models\Photo {#4472
id: 2,
event_id: 1,
photo: "imagem2.jpg",
created_at: "2022-07-02 20:55:52",
updated_at: "2022-07-02 20:55:52",
},
App\Models\Photo {#4456
id: 1,
event_id: 1,
photo: "imagem.jpg",
created_at: "2022-07-02 20:51:54",
updated_at: "2022-07-02 20:51:54",
},
],
}
>>>
>>> $photos = $event->photos;
=> Illuminate\Database\Eloquent\Collection {#4462
all: [
App\Models\Photo {#4468
id: 1,
event_id: 1,
photo: "imagem.jpg",
created_at: "2022-07-02 20:51:54",
updated_at: "2022-07-02 20:51:54",
},
App\Models\Photo {#4473
id: 2,
event_id: 1,
photo: "imagem2.jpg",
created_at: "2022-07-02 20:55:52",
updated_at: "2022-07-02 20:55:52",
},
],
}
>>> $photos->count();
=> 2
>>> $photos->map(function($model) {return $model->photo;})
=> Illuminate\Support\Collection {#4459
all: [
"imagem.jpg",
"imagem2.jpg",
],
}
>>> Photo::find(1)
=> App\Models\Photo {#4481
id: 1,
event_id: 1,
photo: "imagem.jpg",
created_at: "2022-07-02 20:51:54",
updated_at: "2022-07-02 20:51:54",
}
>>> Photo::find(1)->event;
=> App\Models\Event {#4476
id: 1,
title: "Nisi error quia voluptas modi.",
description: "quibusdam a voluptates animi vel consequatur expedita",
body: "Sunt nam magnam tempora dicta iure enim. Soluta harum qui expedita sed repellendus. Repellat veniam hic qui asperiores ratione voluptas sint et.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "nisi-error-quia-voluptas-modi",
}
- 50 Migração N:N
$ sail php artisan make:model Category -m
INFO Model [app/Models/Category.php] created successfully.
INFO Migration [database/migrations/2024_02_14_182632_create_categories_table.php] created successfully.
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('nome');
$table->string('description')->nullable();
$table->string('slug');
$table->timestamps();
});
}
$ sail php artisan make:migration create_category_event_table
INFO Migration [database/migrations/2024_02_14_182945_create_category_event_table.php] created successfully.
public function up()
{
Schema::create('category_event', function (Blueprint $table) {
// $table->id();
// $table->timestamps();
$table->foreignId('event_id')->constrained()->cascadeOnDelete();
$table->foreignId('category_id')->constrained()->cascadeOnDelete();
});
}
$ sail php artisan migrate
INFO Running migrations.
2024_02_14_182632_create_categories_table ................ 25ms DONE
2024_02_14_182945_create_category_event_table ........... 122ms DONE
- 51 Gerando Algumas Categories
$ sail php artisan make:factory CategoryFactory
Factory created successfully.
public function definition()
{
$categoryName = $this->faker->word;
return [
'name' => $categoryName,
'description' => $this->faker->sentence,
'slug' => Str::slug($categoryName),
];
}
>>> \App\Models\Category::factory(5)->create();
=> Illuminate\Database\Eloquent\Collection {#3557
all: [
App\Models\Category {#3560
nome: "ipsum",
description: "Commodi mollitia voluptatem nihil sit est nihil perferendis id.",
slug: "ipsum",
updated_at: "2022-07-02 22:05:23",
created_at: "2022-07-02 22:05:23",
id: 1,
},
App\Models\Category {#3561
nome: "alias",
description: "Similique ducimus neque at suscipit aut.",
slug: "alias",
updated_at: "2022-07-02 22:05:23",
created_at: "2022-07-02 22:05:23",
id: 2,
},
App\Models\Category {#3562
nome: "error",
description: "Quam ex vitae commodi quia accusantium.",
slug: "error",
updated_at: "2022-07-02 22:05:23",
created_at: "2022-07-02 22:05:23",
id: 3,
},
App\Models\Category {#3563
nome: "cum",
description: "Sed ut eius ut velit nemo sapiente ut autem.",
slug: "cum",
updated_at: "2022-07-02 22:05:23",
created_at: "2022-07-02 22:05:23",
id: 4,
},
App\Models\Category {#3564
nome: "ipsa",
description: "Eum et non quam ex blanditiis.",
slug: "ipsa",
updated_at: "2022-07-02 22:05:23",
created_at: "2022-07-02 22:05:23",
id: 5,
},
],
}
- 52 Mapeando N:N Models
class Category extends Model
{
// (...)
public function events()
{
return $this->belongsToMany(Event::class);
}
}
class Event extends Model
{
// (...)
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
- 53 Salvando N:N
>>> namespace App\Models;
>>> $e = Event::find(1);
=> App\Models\Event {#3850
id: 1,
title: "Nisi error quia voluptas modi.",
description: "quibusdam a voluptates animi vel consequatur expedita",
body: "Sunt nam magnam tempora dicta iure enim. Soluta harum qui expedita sed repellendus. Repellat veniam hic qui asperiores ratione voluptas sint et.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "nisi-error-quia-voluptas-modi",
}
>>> $e->categories()->attach([1,2,3]);
=> null
>>> $e->categories()->attach([4]);
=> null
>>> $e->categories()->detach([1,3]);
=> 2
>>> $e->categories()->sync([2]);
=> [
"attached" => [],
"detached" => [
1 => 4,
],
"updated" => [],
]
>>> $e->categories()->sync([1,3,5]);
=> [
"attached" => [
5,
],
"detached" => [],
"updated" => [],
]
>>> $e->categories()->toggle([1,3,5]);
=> [
"attached" => [],
"detached" => [
1,
3,
5,
],
]
>>> $e->categories()->toggle([1,3,5]);
=> [
"attached" => [
1,
3,
5,
],
"detached" => [],
]
>>> $e->categories()->toggle([2]);
=> [
"attached" => [
2,
],
"detached" => [],
]
>>> $e->categories()->toggle([2]);
=> [
"attached" => [],
"detached" => [
2,
],
]
>>> $e->categories()->sync([4]);
=> [
"attached" => [
4,
],
"detached" => [
1,
3,
5,
],
"updated" => [],
]
- 54 Recuperando N:N
>>> $e->categories
=> Illuminate\Database\Eloquent\Collection {#4475
all: [
App\Models\Category {#4477
id: 4,
nome: "cum",
description: "Sed ut eius ut velit nemo sapiente ut autem.",
slug: "cum",
created_at: "2022-07-02 22:05:23",
updated_at: "2022-07-02 22:05:23",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3521
event_id: 1,
category_id: 4,
},
},
],
}
>>> $e->categories->count();
=> 1
>>> $e->categories();
=> Illuminate\Database\Eloquent\Relations\BelongsToMany {#4492
+withTimestamps: false,
}
>>> $cat = Category::find(4);
=> App\Models\Category {#4314
id: 4,
nome: "cum",
description: "Sed ut eius ut velit nemo sapiente ut autem.",
slug: "cum",
created_at: "2022-07-02 22:05:23",
updated_at: "2022-07-02 22:05:23",
}
>>> $cat->events
=> Illuminate\Database\Eloquent\Collection {#4488
all: [
App\Models\Event {#4480
id: 1,
title: "Nisi error quia voluptas modi.",
description: "quibusdam a voluptates animi vel consequatur expedita",
body: "Sunt nam magnam tempora dicta iure enim. Soluta harum qui expedita sed repellendus. Repellat veniam hic qui asperiores ratione voluptas sint et.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "nisi-error-quia-voluptas-modi",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4470
category_id: 4,
event_id: 1,
},
},
],
}
>>> $cat->events()->toggle([1,2,3,4]);
=> [
"attached" => [
2,
3,
4,
],
"detached" => [
1,
],
]
>>> $cat->events()->count();
=> 3
>>> $cat = Category::find(4);
=> App\Models\Category {#4498
id: 4,
nome: "cum",
description: "Sed ut eius ut velit nemo sapiente ut autem.",
slug: "cum",
created_at: "2022-07-02 22:05:23",
updated_at: "2022-07-02 22:05:23",
}
>>> $cat->events
=> Illuminate\Database\Eloquent\Collection {#4500
all: [
App\Models\Event {#3533
id: 2,
title: "A consequatur laboriosam numquam doloribus harum molestiae.",
description: "quam quidem quasi provident rem ea animi",
body: "Magni vel amet nam dolorem. Molestiae autem laudantium illum et nihil odio. Cumque rem sed expedita dignissimos aliquam distinctio. Minus consectetur minima quisquam dicta amet ut.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "a-consequatur-laboriosam-numquam-doloribus-harum-molestiae",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4491
category_id: 4,
event_id: 2,
},
},
App\Models\Event {#4478
id: 3,
title: "Similique porro modi dolorem qui quia quibusdam molestias officia.",
description: "laudantium enim esse et cupiditate ex fugit",
body: "Similique sed occaecati quasi aut sit illo incidunt qui. Aliquam ea et neque dolor ut accusamus nulla hic. Natus reprehenderit quia sed tempore optio quo pariatur.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "similique-porro-modi-dolorem-qui-quia-quibusdam-molestias-officia",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4492
category_id: 4,
event_id: 3,
},
},
App\Models\Event {#4503
id: 4,
title: "Dicta id nulla aut omnis ut praesentium aspernatur.",
description: "ipsum qui ut optio rerum possimus voluptate",
body: "Velit debitis quae aut iure harum ut. Atque temporibus minima velit dolorem velit. Cum enim cumque et distinctio sequi. Atque quia qui asperiores natus vel accusamus fugiat.",
start_event: "2022-07-02 20:35:49",
created_at: "2022-07-02 20:35:49",
updated_at: "2022-07-02 20:35:49",
slug: "dicta-id-nulla-aut-omnis-ut-praesentium-aspernatur",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3520
category_id: 4,
event_id: 4,
},
},
],
}
>>> $e->categories()->count()
=> 0
>>> $cat->events()->count();
=> 3
- 55 Manipulando BelongsTo
>>> $profile = \App\Models\Profile::find(1)
=> App\Models\Profile {#4468
id: 1,
user_id: 2,
about: "Sobre Mim",
phone: "9999999",
social_networks: "faceboo",
created_at: "2022-07-03 11:50:54",
updated_at: "2022-07-03 11:50:54",
}
>>> $profile->user()->dissociate()
=> App\Models\Profile {#4468
id: 1,
user_id: null,
about: "Sobre Mim",
phone: "9999999",
social_networks: "faceboo",
created_at: "2022-07-03 11:50:54",
updated_at: "2022-07-03 11:50:54",
user: null,
}
>>> $profile->save();
Illuminate\Database\QueryException with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null (SQL: update `profiles` set `user_id` = ?, `profiles`.`updated_at` = 2022-07-03 11:55:44 where `id` = 1)'
>>> $profile->user()->associate(3)
=> App\Models\Profile {#4468
id: 1,
user_id: 3,
about: "Sobre Mim",
phone: "9999999",
social_networks: "faceboo",
created_at: "2022-07-03 11:50:54",
updated_at: "2022-07-03 11:55:44",
}
>>> $profile->save();
=> true
- 56 Conclusão
- 57 Iniciando Factories: Profile e Photo
$ sail php artisan make:factory PhotoFactory
INFO Factory [database/factories/PhotoFactory.php] created successfully.
$ sail php artisan make:factory ProfileFactory
INFO Factory [database/factories/ProfileFactory.php] created successfully.
- 58 Factories com Relacionamento HasMany
Model Populado não executado:
>>> \App\Models\Event::factory(5)->make()
=> Illuminate\Database\Eloquent\Collection {#3557
all: [
App\Models\Event {#3561
title: "Nesciunt et doloribus temporibus iure qui soluta fugiat.",
description: "facere laudantium et quos fugiat corrupti omnis",
body: "Voluptatem eos unde dolor. Ab ut omnis doloribus eos officiis tenetur omnis. Hic quo officia dolore qui. Doloribus eius rerum non. Sed non odit cumque omnis eos quam.",
start_event: Illuminate\Support\Carbon @1656959674 {#3560
date: 2022-07-04 18:34:34.271960 UTC (+00:00),
},
slug: "nesciunt-et-doloribus-temporibus-iure-qui-soluta-fugiat",
},
>>> namespace App\Models;
>>> Photo::factory()->make();
=> App\Models\Photo {#3555
photo: "https://via.placeholder.com/640x480.png/0088ff?text=sint",
}
>>> Event::factory()->has(Photo::factory(3))->create();
=> App\Models\Event {#4287
title: "Aut quos delectus cupiditate qui sed et omnis.",
description: "temporibus accusantium ex magni expedita enim velit",
body: "Rerum culpa qui blanditiis et iure culpa. Distinctio placeat nihil est nihil atque et eius et.",
start_event: Illuminate\Support\Carbon @1656959996 {#4288
date: 2022-07-04 18:39:56.615143 UTC (+00:00),
},
slug: "aut-quos-delectus-cupiditate-qui-sed-et-omnis",
updated_at: "2022-07-04 18:39:56",
created_at: "2022-07-04 18:39:56",
id: 7,
}
>>> Event::factory(3)->hasPhotos(3)->create();
=> Illuminate\Database\Eloquent\Collection {#3560
all: [
App\Models\Event {#4509
title: "Voluptatibus mollitia aspernatur omnis ut dicta velit expedita.",
description: "ut repellat sapiente doloremque dicta error itaque",
body: "Aspernatur quas assumenda at molestias eaque occaecati ex eius. Ipsa ab numquam aspernatur ducimus excepturi totam aspernatur. Unde laborum et dolorum quis soluta et.",
start_event: Illuminate\Support\Carbon @1656960134 {#4504
date: 2022-07-04 18:42:14.627647 UTC (+00:00),
},
- 59 Factories com Relacionamento HasOne
>>> User::factory()->has(Profile::factory())->create();
=> App\Models\User {#3889
name: "Ms. Anais Ankunding MD",
email: "[email protected]",
email_verified_at: "2022-07-04 19:02:47",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "ZbEtne4DrJ",
updated_at: "2022-07-04 19:02:47",
created_at: "2022-07-04 19:02:47",
id: 11,
}
>>> User::factory(3)->has(Profile::factory())->create();
=> Illuminate\Database\Eloquent\Collection {#3524
all: [
App\Models\User {#4286
name: "Destinee Bahringer",
email: "[email protected]",
email_verified_at: "2022-07-04 19:09:21",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "uo45KbLosf",
updated_at: "2022-07-04 19:09:21",
created_at: "2022-07-04 19:09:21",
id: 12,
},
// (....)
>>> User::factory(3)->hasProfile()->create();
=> Illuminate\Database\Eloquent\Collection {#4511
all: [
App\Models\User {#4520
name: "Kianna Ankunding",
email: "[email protected]",
email_verified_at: "2022-07-04 19:10:58",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "6N7z6RBXWa",
updated_at: "2022-07-04 19:10:58",
created_at: "2022-07-04 19:10:58",
id: 15,
},
/ (....)
- 60 Factories com BelongsTo
>>> Profile::factory()->for(user::factory())->create();
=> App\Models\Profile {#3577
about: "Reiciendis eos sapiente praesentium optio debitis sunt hic. Neque suscipit excepturi quia iusto tenetur officia excepturi. Error sit neque corrupti quia impedit.",
phone: "(44) 32964-1512",
social_networks: "facebook-twitter",
user_id: 18,
updated_at: "2022-07-04 19:49:46",
created_at: "2022-07-04 19:49:46",
id: 10,
}
>>> Profile::factory()->forUser()->create();
=> App\Models\Profile {#3575
about: "Ut quod consequatur nostrum. Earum exercitationem quibusdam et vel rerum. Ducimus voluptatum inventore asperiores sunt qui modi velit. Quis facilis dicta molestiae dolores.",
phone: "(76) 88288-7048",
social_networks: "facebook-twitter",
user_id: 19,
updated_at: "2022-07-04 19:50:30",
created_at: "2022-07-04 19:50:30",
id: 11,
}
- 61 Executando as Factories via Seed
class UsersTableSeeder extends Seeder
{
public function run()
{
User::factory(10)
->hasProfile()
->create();
}
}
class EventsTableSeeder extends Seeder
{
public function run()
{
Event::factory(6)
->hasPhotos(4)
->hasCategories(3)
->create();
}
}
$ sail php artisan migrate:fresh
Dropped all tables successfully.
$ sail php artisan db:seed
INFO Seeding database.
Database\Seeders\UsersTableSeeder .......................... RUNNING
Database\Seeders\UsersTableSeeder ................... 136.16 ms DONE
Database\Seeders\EventsTableSeeder ........................... RUNNING
Database\Seeders\EventsTableSeeder .................... 228.61 ms DONE
- 62 Introdução
- 63 Relembrando as Views
- 64 Loop e Passagem de Dados View
Route::get('/', function () {
$events = \App\Models\Event::all();
//return view('welcome', ['events'=> $events]);
return view('welcome', compact('events'));
});
<ul>
@foreach($events as $event)
<li>{{$event->title}}</li>
@endforeach
</ul>
- 65 Diretiva ForElse
<ul>
@forelse($events as $event)
<li>{{$event->title}}</li>
@empty
<h3>Nenhum evento encontrado neste site....</h3>
@endforelse
</ul>
<hr>
@if(count($events))
<ul>
@foreach($events as $event)
<li>{{$event->title}}</li>
@endforeach
@else
<h3>Nenhum evento cadastrado</h3>
</ul>
@endif
- 66 O print do Blade
{!! //sem escape !!}
{{ //com escape }}
- 67 Herança de Templates
<title>@yield('title') Eventos Event</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
@yield('content'){{--Todas as views que extender, colocaram seu conteudo nestas área--}}
@extends('layouts.site')
@section('title')
Principais Eventos
@endsection
@section('content')
<h2>Eventos</h2>
<hr>
<ul>
@forelse($events as $event)
<li>{{$event->title}}</li>
@empty
<h3>Nenhum evento encontrado neste site....</h3>
@endforelse
</ul>
<hr>
@if(count($events))
<ul>
@foreach($events as $event)
<li>{{$event->title}}</li>
@endforeach
@else
<h3>Nenhum evento cadastrado</h3>
</ul>
@endif
@endsection
- 68 Incrementando Views de Eventos
@extends('layouts.site')
@section('title')
Principais Eventos
@endsection
@section('content')
<div class="row">
<div class="col-12">
<h2>Eventos</h2>
<hr>
</div>
</div>
<div class="row mb-4">
@forelse($events as $event)
<div class="col-4">
<div class="card">
<img src="https://via.placeholder.com/640x480.png/00dd99?text=omnis" alt="" class="card-img-top">
<div class="card-body">
<h5 class="card-title">{{$event->title}}</h5>
<strong>Acontece em {{ $event->start_event }}</strong>
<p class="card-text">{{$event->description}}</p>
</div>
</div>
</div>
@if(( $loop->iteration % 3) == 0 ) </div> <div class="row mb-4"> @endif
@empty
<div class="col-12">
<div class="alert alert-warning">Nenhum evento encontrado neste site....</div>
</div>
@endforelse
</div>
@endsection
- 69 Melhorias Home e Inicio de Single
<strong>Acontece em: {{$event->start_event->format('d/m/Y H:i:s')}}</strong>
// protected $dates = ['start_event']; // Descontinuado
protected $casts = [
'start_event' => 'date',
];
Route::get('/eventos/{slug}', function ($slug){
// $event = \App\Models\Event::where('slug', $slug)->first();
$event = \App\Models\Event::whereSlug($slug)->first();
return view('event', compact('event'));
});
// 03-PrimeirosPassosVisaoGeral/projMeusEventos/resources/views/event.blade.php
@extends('layouts.site')
@section('title')
Evento - {{$event->title}}
@endsection
@section('content')
<div class="row">
<div class="col-12">
Evento: {{$event->title}}
</div>
</div>
@endsection
- 70 Compondo View Single Evento
- 71 Exibindo Fotos Evento se Existirem
- 72 Organizando com HomeController
$ sail php artisan make:controller HomeController
INFO Controller [app/Http/Controllers/HomeController.php] created successfully.
class HomeController extends Controller
{
public function index()
{
$events = Event::all();
return view('welcome', compact('events'));
}
public function show($slug)
{
$event = Event::where('slug', $slug)->first();
return view('event', compact('event'));
}
}
- 73 Conclusões
- 74 Introdução
- 75 Organizando Rotas Painel Eventos
- 76 Listagem de Eventos
- 77 Paginando Dados
public function index()
{
$events = Event::paginate(3);
return view('admin.events.index', compact('events'));
}
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Paginator::useBootstrap();
}
</table>
{{$events->links()}}
</div>
- 78 Tela de Criação de Evento
- 79 Entendendo CSRF no Laravel
- 80 Manipulando Dados da Request
// Recuperar uma instancia do request
request()
// Recuperar todo conteudo do form enviado como arrau associativo
dd(\request()->all());
// Recuperar uma chave especifica do envio do form
request('title') || request()->get('title')
// E recuperar uma chave especifica do envio como propriedade
dd(request()->title())
- 81 Editando Eventos
- 82 Linkando Edição e Remoção de Evento
- 83 Melhorias Manipulação de Request
- 84 Conclusões
- 85 Introdução
- 86 Relembrando Rotas
// GET | POST | PUT | DELETE | OPTIONS | HEAD
// Route::get(), ...
// any a qualquer verbo ou match
Route::any('/teste-any', fn()=> 'Rota Any'); // Match com qualquer verbo, sendo um dos verbos permitidos acima
// para fazer match com post ou put
Route::match(['post', 'put'], '/teste-match', fn() => 'Rota Match');
- 87 Organizando Rotas com Prefixo e Grupo
Route::prefix('/admin')->group(function () {
Route::prefix('/events')->group(function () {
Route::get('/index', [\App\Http\Controllers\Admin\EventController::class, 'index']);
Route::get('/create', [\App\Http\Controllers\Admin\EventController::class, 'create']);
Route::post('/store', [\App\Http\Controllers\Admin\EventController::class, 'store']);
Route::get('/{event}/edit', [\App\Http\Controllers\Admin\EventController::class, 'edit']);
Route::post('/update/{event}', [\App\Http\Controllers\Admin\EventController::class, 'update']);
Route::get('/destroy/{event}', [\App\Http\Controllers\Admin\EventController::class, 'destroy']);
});
});
- 88 Usando Apelido de Rotas
Route::prefix('/admin')->name('admin.')->group(function () {
Route::prefix('/events')->name('events')->group(function () {
Route::get('/index', [\App\Http\Controllers\Admin\EventController::class, 'index'])->name('index');
Route::get('/create', [\App\Http\Controllers\Admin\EventController::class, 'create'])->name('create');
Route::post('/store', [\App\Http\Controllers\Admin\EventController::class, 'store'])->name('store');
Route::get('/{event}/edit', [\App\Http\Controllers\Admin\EventController::class, 'edit'])->name('edit');
Route::post('/update/{event}', [\App\Http\Controllers\Admin\EventController::class, 'update'])->name('update');
Route::get('/destroy/{event}', [\App\Http\Controllers\Admin\EventController::class, 'destroy'])->name('destroy');
});
});
- 89 Refatorando Links nas Views
<a href="{{route('admin.events.create')}}" class="btn btn-success">Criar Evento</a>
</div>
<div class="col-12">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Evento</th>
<th scope="col">Criando em</th>
<th scope="col">Ações</th>
</tr>
</thead>
<tbody>
@forelse($events as $event)
<tr>
<th scope="row">{{$event->id}}</th>
<td>{{$event->title}}</td>
<td>{{$event->created_at->format('d/m/Y H:i:s')}}</td>
<td>
<a href="{{ route('admin.events.edit', ['event'=> $event->id]) }}" class="btn btn-info">Editar</a>
<a href="{{ route('admin.events.destroy', ['event'=> $event->id]) }}" class="btn btn-danger">Remover</a>
</td>
- 90 Refatorando Redirecionamentos
- 91 Dando um Tapa no Painel de Eventos
- 92 Conclusões
-
93 Introdução
-
94 Usando Validação Controller
public function store(Request $request)
{
$request->validate([
'title' => 'required|min:30',
'description' => 'required',
'body' => 'required',
'start_event' => 'required',
]);
- 95 Exibindo Todas as Validações na View
@dump($errors->all())
@if($errors->any())
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $erro)
<li>{{$erro}}</li>
@endforeach
</ul>
</div>
@endif
- 96 Exibindo Validações POr Input
<form action="{{ route('admin.events.store')}}" method="post">
@csrf
<div class="form-group">
<label>Título Evento</label>
<input type="text" class="form-control @if($errors->has('title')) is-invalid @endif" name="title">
@if($errors->has('title'))
<div class="invalid-feedback">
@foreach($errors->get('title') as $error)
{{$error}}
@endforeach
</div>
@endif
</div>
- 97 Diretiva @error
<form action="{{ route('admin.events.store')}}" method="post">
@csrf
<div class="form-group">
<label>Título Evento</label>
<input type="text" class="form-control @error('title') is-invalid @enderror" name="title">
@error('title')
<div class="invalid-feedback">
{{$message}}
</div>
@enderror
</div>
<div class="form-group">
<label>Descrição Rápida Evento</label>
<input type="text" class="form-control @error('description') is-invalid @enderror" name="description">
@error('description')
<div class="invalid-feedback">
{{$message}}
</div>
@enderror
</div>
- 98 Traduzindo Mensagens de Validação
$request->validate([
'title' => 'required|min:30',
'description' => 'required',
'body' => 'required',
'start_event' => 'required',
],
[
'title.required' => 'Este campo de Títuilo é obrigatório',
'required' => 'Este campo é obrigatório',
'min' => 'Este campo requer mais caracteres. Mínimo é de :min'
]);
- 99 Melhorando Para Form Requests
$ php artisan make:request EventRequest
Request created successfully.
class EventRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required|min:30',
'description' => 'required',
'body' => 'required',
'start_event' => 'required',
];
}
public function messages()
{
return [
'title.required' => 'Este campo de Títuilo é obrigatório',
'required' => 'Este campo é obrigatório',
'min' => 'Este campo requer mais caracteres. Mínimo é de :min'
];
}
}
public function store(EventRequest $request)
{
$event = $request->all();
$event['slug'] = Str::slug($event['title']);
Event::create($event);
return redirect()->route('admin.events.index');
}
- 100 Validação na Edição do Evento
- 101 Conclusões
- 102 Introdução
- 104 Criando Controllers como Recurso
$ php artisan make:controller ResController --resource
Controller created successfully.
// OU
$ php artisan make:controller ResController -r
Route::resource('res', \App\Http\Controllers\ResController::class);
$ php artisan route:list
GET|HEAD / .......................... HomerController@index
POST _ignition/execute-solution .......... ignition.executeSolution › Spatie\LaravelIgnition › ExecuteSolutionController
GET|HEAD _ignition/health-check .......... ignition.healthCheck › Spatie\LaravelIgnition › HealthCheckController
POST _ignition/update-config ......... ignition.updateConfig › Spatie\LaravelIgnition › UpdateConfigController
GET|HEAD admin/events ........................ admin.events.index › Admin\EventController@index
GET|HEAD admin/events/create ................. admin.events.create › Admin\EventController@create
GET|HEAD admin/events/destroy/{event} ........ admin.events.destroy › Admin\EventController@destroy........................... admin.events.store › Admin\EventController@store
POST admin/events/update/{event} ................ admin.events.update › Admin\EventController@update
GET|HEAD admin/events/{event}/edit .......................... admin.events.edit › Admin\EventController@edit
GET|HEAD api/user ....................
GET|HEAD eventos/{slug} ......................................... event.single › HomerController@show
GET|HEAD ola-mundo ...................
GET|HEAD ola/{name?} ....................................
GET|HEAD queries/{event?} ...............................................
GET|HEAD res ............................. res.index › ResController@index
POST res ................................. res.store › ResController@store
GET|HEAD res/create ............................. res.create › ResController@create
GET|HEAD res/{re} ............................... res.show › ResController@show
PUT|PATCH res/{re} ....................................... res.update › ResController@update
DELETE res/{re} ................... res.destroy › ResController@destroy
GET|HEAD res/{re}/edit .............................. res.edit › ResController@edit
GET|HEAD sanctum/csrf-cookie .................. Laravel\Sanctum › CsrfCookieController@show
ANY teste-any ......................................
POST|PUT teste-match ................................................
$ php artisan route:list --name=events
GET|HEAD admin/events ....................... admin.events.index › Admin\EventController@index
GET|HEAD admin/events/create ................ admin.events.create › Admin\EventController@create
GET|HEAD admin/events/destroy/{event} ....... admin.events.destroy › Admin\EventController@destroy
POST admin/events/store ................. admin.events.store › Admin\EventController@store
POST admin/events/update/{event} ........ admin.events.update › Admin\EventController@update
GET|HEAD admin/events/{event}/edit .......... admin.events.edit › Admin\EventController@edit
Route::prefix('/admin')->name('admin.')->group(function () {
/* Route::prefix('/events')->name('events.')->group(function () {
Route::get('/', [\App\Http\Controllers\Admin\EventController::class, 'index'])->name('index');
Route::get('/create', [\App\Http\Controllers\Admin\EventController::class, 'create'])->name('create');
Route::post('/store', [\App\Http\Controllers\Admin\EventController::class, 'store'])->name('store');
Route::get('/{event}/edit', [\App\Http\Controllers\Admin\EventController::class, 'edit'])->name('edit');
Route::post('/update/{event}', [\App\Http\Controllers\Admin\EventController::class, 'update'])->name('update');
Route::get('/destroy/{event}', [\App\Http\Controllers\Admin\EventController::class, 'destroy'])->name('destroy');
});*/
Route::resource('events', \App\Http\Controllers\Admin\EventController::class);
});
$ php artisan route:list --name=events
GET|HEAD admin/events ....................... admin.events.index › Admin\EventController@index
POST admin/events ....................... admin.events.store › Admin\EventController@store
GET|HEAD admin/events/create .............. admin.events.create › Admin\EventController@create
GET|HEAD admin/events/{event} ................. admin.events.show › Admin\EventController@show
PUT|PATCH admin/events/{event} ............. admin.events.update › Admin\EventController@update
DELETE admin/events/{event} ........... admin.events.destroy › Admin\EventController@destroy
GET|HEAD admin/events/{event}/edit ............ admin.events.edit › Admin\EventController@edit
<form action="{{route('admin.events.update', ['event' => $event->id])}}" method="post">
@csrf
@method('PUT')
@forelse($events as $event)
<tr>
<th scope="row">{{$event->id}}</th>
<td>{{$event->title}}</td>
<td>{{$event->created_at->format('d/m/Y H:i:s')}}</td>
<td class="d-flex justify-content-between">
<a href="{{ route('admin.events.edit', ['event'=> $event->id]) }}" class="btn btn-info">Editar</a>
<form action="{{ route('admin.events.destroy', ['event'=> $event->id]) }}" method="post">
@csrf
@method('DELETE')
<button class="btn btn-danger">Remover</button>
</form>
</td>
</tr>
@empty
- 106 Tomando Nota dos Ganhos
- 107 Recursos Aninhados
- 108 Recursos Aninhados no Projeto e Mais
Route::prefix('/admin')->name('admin.')->group(function () {
Route::resource('events', \App\Http\Controllers\Admin\EventController::class);
Route::resource('events.photos', \App\Http\Controllers\Admin\EventPhotoController::class);
});
$ php artisan make:controller Admin/EventPhotoController -r
Controller created successfully.
$ php artisan route:list --name=events.photos
GET|HEAD admin/events/{event}/photos ............. admin.events.photos.index › Admin\EventPhotoController@index
POST admin/events/{event}/photos ............. admin.events.photos.store › Admin\EventPhotoController@store
GET|HEAD admin/events/{event}/photos/create ...... admin.events.photos.create › Admin\EventPhotoController@create
GET|HEAD admin/events/{event}/photos/{photo} ..... admin.events.photos.show › Admin\EventPhotoController@show
PUT|PATCH admin/events/{event}/photos/{photo} ..... admin.events.photos.update › Admin\EventPhotoController@update
DELETE admin/events/{event}/photos/{photo} ..... admin.events.photos.destroy › Admin\EventPhotoController@destroy
GET|HEAD admin/events/{event}/photos/{photo}/edit .. admin.events.photos.edit › Admin\EventPhotoController@edit
Route::resource('events', \App\Http\Controllers\Admin\EventController::class)
->except('destroy');
Route::resource('events.photos', \App\Http\Controllers\Admin\EventPhotoController::class)
->only('index', 'show');
$ php artisan route:list --name=events.photos
GET|HEAD admin/events/{event}/photos ........... admin.events.photos.index › Admin\EventPhotoController@index
GET|HEAD admin/events/{event}/photos/{photo} ..... admin.events.photos.show › Admin\EventPhotoController@show
- 109 Registrando Vários Recursos
Route::resources([
'events' => \App\Http\Controllers\Admin\EventController::class,
'events.photos' => \App\Http\Controllers\Admin\EventPhotoController::class
],
[
'except' => ['destroy']
]);
- 110 DI nos Controllers
class EventController extends Controller
{
private $event;
public function __construct(Event $event)
{
$this->event = $event;
}
public function index()
{
$events = $this->event->paginate(3);
return view('admin.events.index', compact('events'));
}
- 111 Conclusões
- 112 Intro e Obtendo Laravel UI
$ composer require laravel/ui:^3.2
./composer.json has been updated
Running composer update laravel/ui
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
- Locking laravel/ui (v3.4.6)
$ php artisan | grep -i "ui"
-q, --quiet Do not output any message
ui Swap the front-end scaffolding for the application
package:discover Rebuild the cached package manifest
ui
ui:auth Scaffold basic login and registration views and routes
ui:controllers Scaffold the authentication controllers
- 113 Gerando Autenticação
$ php artisan ui bootstrap --auth
Bootstrap scaffolding installed successfully.
Please run "npm install && npm run dev" to compile your fresh scaffolding.
The [layouts/app.blade.php] view already exists. Do you want to replace it? (yes/no) [no]:
> no
The [HomeController.php] file already exists. Do you want to replace it? (yes/no) [no]:
> no
Authentication scaffolding generated successfully.
$ npm i
....
added 741 packages, and audited 742 packages in 41s
77 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
$ npm run dev
> dev
> npm run development
> development
> mix
Additional dependencies must be installed. This will only take a moment.
Running: npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
Finished. Please run Mix again.
josem@josemalcher MINGW64 ~/Documents/workspaces/Laravel-Mastery-CodeExperts/appMeusEventos (master)
$ npm run dev
> dev
> npm run development
> development
> mix
● Mix █████████████████████████ building (10%) 0/2 entries 3/3 dependencies 0/3 modules 3 active
babel-loader › res
- 114 Conhecendo os Arquivos do Auth
- 116 O Btn de Logout
- 117 Arquivo de Configurações Auth
- 118 Configurações para Dono de Evento
$ php artisan make:migration alter_table_events_add_column_owner_id --table=events
Created Migration: 2023_03_09_190205_alter_table_events_add_column_owner_id
class AlterTableEventsAddColumnOwnerId extends Migration
{
public function up()
{
Schema::table('events', function (Blueprint $table) {
$table->foreignId('owner_id')
->nullable()
->constrained('users')
->cascadeOnDelete();
});
}
public function down()
{
Schema::table('events', function (Blueprint $table) {
$table->dropForeign('events_owner_id_foreign');
$table->dropColumn('owner_id');
});
}
$ php artisan migrate
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
User::factory(50)
->has(
Event::factory(30)
->hasPhotos(4)
->hasCategories(3)
)
->hasProfile()
->create();
}
}
$ php artisan migrate:refresh --seed
- 119 Eventos por Usuário Logado
public function index()
{
// dd(auth()->user()->events);
$events = auth()->user()->events()->paginate(10);
return view('admin.events.index', compact('events'));
}
public function store(EventRequest $request)
{
$event = $request->all();
$event['slug'] = Str::slug($event['title']);
$event = $this->event->create($event);
$event->owner()->associate(auth()->user());
$event->save();
return redirect()->route('admin.events.index');
}
- 120 O Middleware Authenticate
- 121 Conclusões
- 122 Introdução
- 123 Entendendo Eloquent Accessors
class Event extends Model
{
public function getTitleAttribute()
{
return 'Evento: ' . $this->attributes['title'];
}
// public function getStartEventAttribute() // coluna: start_event
// {
// // return 'Evento: ' . $this->attributes['title'];
// }
public function getOwnerNameAttribute()
{
return !$this->owner() ? 'Organizador Não encontrado' : $this->owner->name;
}
@forelse($events as $event)
<p>Organizado por: {{ $event->owner_name }}</p>
- 124 Entendendo Eloquent Mutators
class Event extends Model
{
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
$this->attributes['slug'] = Str::slug($value);
}
public function store(EventRequest $request)
{
$event = $request->all();
// $event['slug'] = Str::slug($event['title']);
$event = $this->event->create($event);
$event->owner()->associate(auth()->user());
$event->save();
return redirect()->route('admin.events.index');
}
- 125 Máscara de Data Evento
$ npm i inputmask -D
$ npm run dev
var Inputmask = require('inputmask');
@section('scripts')
<script>
let el = document.querySelector('input[name=start_event]');
console.log(el);
let im = new Inputmask('99/99/9999 99:99:99');
console.log(im);
im.mask(el);
</script>
@endsection
- 126 Formatando Data para o Banco
public function setStartEventAttribute($value)
{
$this->attributes['start_event'] = (\DateTime::createFromFormat('d/m/Y H:i', $value)
->format('Y-m-d H:i'));
}
- 127 Nosso primeiro Middleware
$ php artisan make:middleware CheckUserHasCanAccessEventToEditMiddleware
Middleware created successfully.
// appMeusEventos/app/Http/Kernel.php
protected $routeMiddleware = [
'user.can.edit.event' => \App\Http\Middleware\CheckUserHasCanAccessEventToEditMiddleware::class,
];
// "MALABARISMO"
Route::resource('events', EventController::class)
->except(['edit', 'updade']);
Route::resource('events', EventController::class)
->only(['edit', 'update'])
->middleware('user.can.edit.event');
// ->middleware(App\Http\Middleware\CheckUserHasCanAccessEventToEditMiddleware::class);
class EventController extends Controller
{
private $event;
public function __construct(Event $event)
{
$this->event = $event;
$this->middleware('user.can.edit.event') // Edit e Update
->only('edit', 'update');
}
- 128 Usuário: Bloqueando Acesso A Outros Eventos
class CheckUserHasCanAccessEventToEditMiddleware
{
public function handle(Request $request, Closure $next)
{
$event = Event::find($request->route()->parameter('event'));
if( !auth()->user()->events->contains($event)){
abort(403);
}
return $next($request);
}
- 129 Melhorias Home de Eventos
- 130 Busca de Eventos
class HomeController extends Controller
{
public function index()
{
$events = $this->event->orderBy('start_event', 'DESC');
// if( $query = request()->query('s')){
// $events->where('title', 'LIKE', '%' . $query . '%');
// }
$events->when($search = request()->query('s'), function ($queryBuilder) use ($search){
return $queryBuilder->where('title', 'LIKE', '%' . $search . '%');
});
$events = $events->paginate(12);
return view('home', compact('events'));
}
<form class="my-2 form-inline my-lg-0">
<input class="form-control mr-sm-2" type="search"
placeholder="Buscar Evento" aria-label="Search"
name="s"
value="{{ request()->query('s') }}"
>
<button class="my-2 btn btn-outline-success my-sm-0" type="submit">Buscar</button>
</form>
- 131 Filtro Por Categorias
class Event extends Model
{
/* Outros methods */
public function getEventsHome($byCategory = null)
{
$events = $byCategory ? $byCategory : $this->orderBy('start_event', 'DESC');
$events->when($search = request()->query('s'), function ($queryBuilder) use ($search){
return $queryBuilder->where('title', 'LIKE', '%' . $search . '%');
});
return $events;
}
}
class HomeController extends Controller
{
public function index()
{
$byCategory = request()->has('category')
? Category::whereSlug(request()->get('category'))->first()->events()
: null ;
$events = $this->event->getEventsHome($byCategory)->paginate(12);
$categories = Category::all(['nome', 'slug']);
return view('home', compact('events', 'categories'));
}
<div class="dropdown-menu">
@foreach($categories as $category)
<a class="dropdown-item" href="{{ route('home', ['category'=> $category->slug]) }}">
{{ $category->nome }}
</a>
@endforeach
</div>
- 132 View Share e Composer
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// view()->share('categories', \App\Models\Category::all(['name', 'slug']));
view()->composer('layouts.site', function ($view) {
$view->with('categories', \App\Models\Category::all(['nome', 'slug']));
});
}
}
- 133 Melhorando View Composer
class CategoiesViewComposer
{
private $category;
public function __construct(Category $category)
{
$this->category = $category;
}
public function composer($view)
{
return $view->with('categories', $this->category->all(['nome', 'slug']));
}
}
$ php artisan make:provider ViewComposerServiceProvider
Provider created successfully.
class ViewComposerServiceProvider extends ServiceProvider
{
public function boot()
{
view()->composer('layouts.site', 'App\Http\Views\Composer\CategoiesViewComposer@composer');
}
}
// appMeusEventos/config/app.php
'providers' => [
/*
* Laravel Framework Service Providers...
*/
App\Providers\ViewComposerServiceProvider::class,
],
- 134 Eventos Que Vão Acontecer e Concluindo
class Event extends Model
{
/* Outros methods */
public function getEventsHome($byCategory = null)
{
$events = $byCategory ? $byCategory : $this->orderBy('start_event', 'DESC');
$events->when($search = request()->query('s'), function ($queryBuilder) use ($search){
return $queryBuilder->where('title', 'LIKE', '%' . $search . '%');
});
// $events->whereRaw('DATE(start_event) >= DATE(NOW())'); // pode dar problemas com outros bancos..etc!
$events->whereDate('start_event', '>=', now());
return $events;
}
}
- 135 Introdução
$ php artisan make:migration alter_events_table_add_banner_collumn --table=events
Created Migration: 2023_03_11_201925_alter_events_table_add_banner_collumn
class AlterEventsTableAddBannerCollumn extends Migration
{
public function up()
{
Schema::table('events', function (Blueprint $table) {
$table->string('banner')->nullable();
});
}
public function down()
{
Schema::table('events', function (Blueprint $table) {
$table->dropColumn('banner');
});
}
- 136 Iniciando Upload
public function store(EventRequest $request)
{
$banner = $request->file('banner');
dd($banner->store('banner')); // "banner/5bK9S46MkV4m6ImHJEOP9G1sh1S9Wq0PjSA7p71V.jpg"
- 137 Configurações de Upload
public function store(EventRequest $request)
{
$banner = $request->file('banner');
dd($banner->store('banner', 'public'));
- 138 Upload e Save no Banco
public function store(EventRequest $request)
{
// $banner = $request->file('banner');
$event = $request->all();
$event['banner'] = ($request->file('banner'))->store('banner', 'public');
- 139 Validando Upload de Imagens
public function store(EventRequest $request)
{
// $banner = $request->file('banner');
$event = $request->all();
if ($banner = $request->file('banner')) {
$event['banner'] = $banner->store('banner', 'public');
}
public function rules()
{
return [
'title' => 'required|min:30',
'description' => 'required',
'body' => 'required',
'start_event' => 'required',
'banner' => 'required|image'
];
}
public function messages()
{
return [
'title.required' => 'Este campo de Títuilo é obrigatório',
'required' => 'Este campo é obrigatório',
'min' => 'Este campo requer mais caracteres. Mínimo é de :min',
'image' => 'Arquivo de Imagem invalido'
];
}
- 140 Iniciando Upload na Edição
<div class="col-4">
<img src="{{ asset('storage/'. $event->banner) }}" alt="Banner do Evento {{$event->title}}"
class="img-fluid">
</div>
$ php artisan storage:link
The [......\workspaces\Laravel-Mastery-CodeExperts\appMeusEventos\public\storage]
link has been connected to [......\workspaces\Laravel-Mastery-CodeExperts\appMeusEventos\storage\app/public].
The links have been created.
- 141 Concluindo Upload na Edição
public function update($event, EventRequest $request)
{
$event = $this->event->findOrFail($event);
$eventData = $request->all();
if ($banner = $request->file('banner')) {
if(Storage::disk('public')->exists($event->banner)){
Storage::disk('public')->delete($event->banner);
}
$eventData['banner'] = $banner->store('banner', 'public');
}
$event->update($eventData);
return redirect()->back();
}
- 142 Upload de Múltiplos Arquivos
Route::resource('events.photos', EventPhotoController::class)
->only(['index', 'store', 'destroy']);
class EventPhotoController extends Controller
{
public function index($event)
{
return view('admin.events.photos', compact('event'));
}
@section('content')
<div class="mt-5 row">
<div class="col-12">
<form action="{{ route('admin.events.photos.store', $event) }}" method="post" enctype="multipart/form-data">
@csrf
<div class="form-group">
<label>Enviar Fotos do Evento</label>
<input type="file" class="form-control" multiple name="photos[]">
</div>
<button class="btn btn-success">Enviar fotos do Evento</button>
</form>
<hr>
</div>
</div>
@endsection
- 143 Salvando Referencias no Banco Upload Múltiplo
public function store(Request $request, $event)
{
$uploadPhotos = [];
// iterar nestas fotos e realizar o upload
foreach ($request->file('photos') as $photo) {
$uploadPhotos[] = ['photo'=> $photo->store('events/photos', 'public')];
}
// salvar as referencias para o evento em questão
$event = \App\Models\Event::find($event);
$event->photos()->createMany($uploadPhotos);
return redirect()->back();
}
- 144 Validando Múltiplos Arquivos
$ php artisan make:request EventPhotoRequest
Request created successfully.
class EventPhotoRequest extends FormRequest
{
public function rules()
{
return [
'photos.*' => 'image'
];
}
public function messages()
{
return [
'image' => 'Um ou mais arquivos de imagem inválidos'
];
}
public function store(EventPhotoRequest $request, $event)
{
$uploadPhotos = [];
// iterar nestas fotos e realizar o upload
foreach ($request->file('photos') as $photo) {
$uploadPhotos[] = ['photo'=> $photo->store('events/photos', 'public')];
}
// salvar as referências para o evento em questão
$event = \App\Models\Event::find($event);
$event->photos()->createMany($uploadPhotos);
return redirect()->back();
}
<input type="file"
class="form-control @error('photos.*') is-invalid @enderror"
multiple name="photos[]">
@error('photos.*')
<div class="invalid-feedback">
{{$message}}
</div>
@enderror
- 145 Deletando Fotos do Evento
public function destroy(Event $event, $photo)
{
$photo = $event->photos()->find($photo);
if (!$photo) {
return redirect()->route('admin.events.index');
}
if (Storage::disk('public')->exists($photo->photo)){
Storage::disk('public')->delete($photo->photo);
}
// Remover da base e remover do diretorio
$photo->delete();
return redirect()->back();
}
<div class="row">
@forelse($event->photos as $photo)
<div class="mb-4 text-center col-4">
<img src="{{ asset('storage/'.$photo->photo) }}" alt="Fotos do evento {{ $event->title }}" class="img-fluid">
<form action="{{ route('admin.events.photos.destroy', [$event, $photo]) }}" method="post">
@csrf
@method('DELETE')
<button class="mt-1 btn btn-danger">Deletar Foto</button>
</form>
</div>
@empty
<div class="col-12">
<div class="alert alert-warning">
Nenhuma Fotos Postada
</div>
</div>
@endforelse
</div>
- 146 Falando Mais Sobre Route Model Bind
class HomeController extends Controller
{
public function show(Event $event)
{
// $event = $this->event->where('slug', $event)->first();
return view('event', compact('event'));
}
Route::get('/eventos/{event:slug}', [HomeController::class, 'show'])->name('event.single');
- 147 Jogando o Upload para Trait
trait UploadTrait
{
public function multipleFilesUpload(array $files, string $folder, string $column)
{
$uploadFiles = [];
foreach ($files as $file) {
$uploadFiles[] = [$column => $this->upload($file, $folder)];
}
return $uploadFiles;
}
public function upload(UploadedFile $file, string $folder)
{
return $file->store($folder, 'public');
}
}
public function store(EventRequest $request)
{
// $banner = $request->file('banner');
$event = $request->all();
if ($banner = $request->file('banner')) {
//$event['banner'] = $banner->store('banner', 'public');
$event['banner'] = $this->upload($banner, 'events/banner');
}
// $event['slug'] = Str::slug($event['title']);
$event = $this->event->create($event);
$event->owner()->associate(auth()->user());
$event->save();
return redirect()->route('admin.events.index');
}
public function store(EventPhotoRequest $request, Event $event)
{
// $uploadPhotos = [];
// iterar nestas fotos e realizar o upload
// foreach ($request->file('photos') as $photo) {
// $uploadPhotos[] = ['photo'=> $photo->store('events/photos', 'public')];
// }
$uploadPhotos = $this->multipleFilesUpload($request->file('photos'), 'events/photos','photo');
// salvar as referências para o evento em questão
// $event = \App\Models\Event::find($event);
$event->photos()->createMany($uploadPhotos);
return redirect()->back();
}
- 148 Conclusões
- 149 Introdução
- 150 Mapeando Relação Inscrição
$ php artisan make:migration create_event_user_table
Created Migration: 2023_03_14_000351_create_event_user_table
public function up()
{
Schema::create('event_user', function (Blueprint $table) {
$table->foreignId('event_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('reference');
$table->string('status');
});
}
$ php artisan migrate
class Event extends Model
{
public function enrolleds() // Users
{
return $this->belongsToMany(User::class);
}
class User extends Authenticatable
{
public function tickets()
{
return $this->belongsToMany(Event::class);
}
- 151 Entendendo M-M com Dados Extras
> $e = \App\Models\Event::first();
= App\Models\Event {#4589
id: 1,
title: "editado Hic adipisci consequatur nostrum voluptas est sapiente ratione.",
description: "excepturi",
body: "Et necessitatibus impedit saepe quas. Officia deleniti aut iusto quidem non. ",
start_event: "2023-03-09 19:27:00",
created_at: "2023-03-09 19:27:43",
updated_at: "2023-03-13 23:55:49",
slug: "editado-hic-adipisci-consequatur-nostrum-voluptas-est-sapiente-ratione",
owner_id: 1,
banner: "events/banner/q0zdPf2U2yFkdPjBn5fUOTmyh1tBxHsYma4rY3EW.jpg",
}
> $e->enrolleds;
= Illuminate\Database\Eloquent\Collection {#4594
all: [],
}
> $e->enrolleds()->sync([1,2]);
Illuminate\Database\QueryException SQLSTATE[HY000]: General error:
1364 Field 'reference' doesn't have a default value (SQL: insert into `event_user` (`event_id`, `user_id`) values (1, 1)).
> $e->enrolleds()->sync([
1 => ['reference'=>'blablabla', 'status'=>'ACTIVE'],
2 => ['reference'=> 'bla', 'status'=>'CANCELED']]);
= [
"attached" => [
1,
2,
],
"detached" => [],
"updated" => [],
]
> $e->enrolleds
= Illuminate\Database\Eloquent\Collection {#4594
all: [
App\Models\User {#4593
id: 1,
name: "Janet Conn",
email: "[email protected]",
email_verified_at: "2023-03-09 19:27:43",
#password: "$2y$10$92IXUNpkjO0byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "tBdASC3wGEMLktrJy9uHG5Ps16LAupvgEZDlvqigMeZDz8yZThwl5Z",
created_at: "2023-03-09 19:27:43",
updated_at: "2023-03-09 19:27:43",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4582
event_id: 1,
user_id: 1,
},
},
App\Models\User {#4584
id: 2,
name: "Annetta Lueilwitz",
email: "[email protected]",
email_verified_at: "2023-03-09 19:27:43",
#password: "$2y$10$92IXUNpkjO0rOQ5bi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "WlrlOkkT",
created_at: "2023-03-09 19:27:43",
updated_at: "2023-03-09 19:27:43",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4598
event_id: 1,
user_id: 2,
},
},
],
}
public function tickets()
{
return $this->belongsToMany(Event::class)
->withPivot('reference', 'status');
}
public function enrolleds() // Users
{
return $this->belongsToMany(User::class)
->withPivot('reference', 'status');
}
> $e->enrolleds
= Illuminate\Database\Eloquent\Collection {#4593
all: [
App\Models\User {#4582
id: 1,
name: "Janet Conn",
email: "[email protected]",
email_verified_at: "2023-03-09 19:27:43",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "tBdASC3wGEMLZ6IktrJy9uHG5Ps16LrQ2AupvgEZDlvqigMeZDz8yZThwl5Z",
created_at: "2023-03-09 19:27:43",
updated_at: "2023-03-09 19:27:43",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4594
event_id: 1,
user_id: 1,
reference: "blablabla",
status: "ACTIVE",
},
},
App\Models\User {#4590
id: 2,
name: "Annetta Lueilwitz",
email: "[email protected]",
email_verified_at: "2023-03-09 19:27:43",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "WlrlOkMVkT",
created_at: "2023-03-09 19:27:43",
updated_at: "2023-03-09 19:27:43",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4595
event_id: 1,
user_id: 2,
reference: "bla",
status: "CANCELED",
},
},
],
}
> $e->enrolleds->first()->pivot
= Illuminate\Database\Eloquent\Relations\Pivot {#4594
event_id: 1,
user_id: 1,
reference: "blablabla",
status: "ACTIVE",
}
public function tickets()
{
return $this->belongsToMany(Event::class)
// ->as('tickets') // mudar o nome da chave pivot - Representa a tabela intermediaria
->withPivot('reference', 'status');
}
- 152 Iniciando Processo de Inscrição
$ php artisan make:controller EnrollmentController
Controller created successfully.
class EnrollmentController extends Controller
{
public function start(Event $event)
{
session()->put('enrollement', $event->id);
return redirect()->route('enrollement.confirm');
}
public function confirm()
{
// se o ususário não estiver autenticado...
}
}
- 153 Tela de Confirmação de Inscrição
Route::prefix('/enrollment')->name('enrollment.')->group(function (){
Route::get('/start/{event:slug}', [App\Http\Controllers\EnrollmentController::class, 'start'])
->name('start');
Route::get('/confirm', [App\Http\Controllers\EnrollmentController::class, 'confirm'])
->name('confirm')->middleware('auth');
Route::get('/process', [App\Http\Controllers\EnrollmentController::class, 'proccess'])->name('proccess')
->middleware('auth');
});
class EnrollmentController extends Controller
{
public function start(Event $event)
{
session()->put('enrollment', $event->id);
return redirect()->route('enrollment.confirm');
}
public function confirm()
{
if (!session()->has('enrollment')) {
return redirect()->route('home');
}
$event = Event::find(session('enrollment'));
return view('enrollment-confirm', compact('event'));
}
public function proccess()
{
dd('Confirmando...');
}
}
- 154 Concluindo Processo de Inscrição
public function proccess()
{
if (!session()->has('enrollment')) {
return redirect()->route('home');
}
$event = Event::find(session('enrollment'));
$event->enrolleds()->attach([
auth()->id() => [
'reference'=> uniqid(),
'status' => 'ACTIVE'
]
]);
session()->forget('enrollment');
return redirect()->route('event.single', $event->slug);
}
- 155 Melhorias Processo de Inscrição
class RegisterController extends Controller
{
protected function registered(Request $request, $user)
{
if(session()->has('enrollment')){
return redirect()->route('enrollment.confirm');
}
}
class LoginController extends Controller
{
protected function authenticated(Request $request, $user)
{
if(session()->has('enrollment')){
return redirect()->route('enrollment.confirm');
}
}
}
- 156 Classe Mailable
$ php artisan make:mail UserEnrollmentMail
Mail created successfully.
class UserEnrollmentMail extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $event;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($user, $event)
{
$this->user = $user;
$this->event = $event;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this
->subject('Confirmação de Inscrição')
// ->replyTo()
->view('emails.enrollment-user');
}
}
<div>
<p>
Olá <strong>{{ $user->name }}</strong>!
<br><br>
Sua inscrição no evento <strong>{{$event->title}}</strong> foi realizada com sucesso!
<br><br>
Obrigado pela Inscrição
</p>
<hr>
Email Enviado em {{ date('d/m/Y H:i') }}
</div>
- 157 Configurações e Envio de E-mail
class EnrollmentController extends Controller
{
public function proccess()
{
if (!session()->has('enrollment')) {
return redirect()->route('home');
}
$event = Event::find(session('enrollment'));
$event->enrolleds()->attach([
auth()->id() => [
'reference'=> uniqid(),
'status' => 'ACTIVE'
]
]);
session()->forget('enrollment');
$user = auth()->user();
Mail::to($user)->send(new UserEnrollmentMail($user, $event));
return redirect()->route('event.single', $event->slug);
}
- 158 Evento: Uma Inscrição Por Usuário
- 159 Categorias Na Criação e Edição de Eventos
- 160 Processando Associação de Categorias e Eventos
- 161 Melhorias Painel
@auth()
<li class="nav-item">
<a href="{{route('admin.events.index')}}" class="nav-link">Meu Painel</a>
</li>
@else
<li class="nav-item">
<a href="{{route('login')}}" class="nav-link">Login</a>
</li>
@endauth
- 162 Iniciando Perfil do Usuário
- 163 Processando Atualização de Perfil
class ProfileController extends Controller
{
public function update()
{
$userData = request()->get('user');
$profile = request()->get('profile');
if($userData['password']){
$userData['password'] = bcrypt($userData['password']);
}else{
unset($userData['password']);
}
$user = auth()->user();
$user->update($userData);
$user->profile()->update($profile);
return redirect()->route('admin.profile.edit');
}
}
- 164 Validações na Atualização do Perfil
- 165 O Validador Unique no Update
class ProfimeRequest extends FormRequest
{
public function rules()
{
$rules = [
'user.name' => 'required',
'user.email' => 'required|email|unique:users,email,' . auth()->id(),
];
if ($this->request->get('user')['password']) {
$rules['user.password'] = 'string|min:8|confirmed';
}
return $rules;
}
public function messages()
{
return [
'required' => 'Estes campos são obrigatórios',
'min' => 'A sena deve ter no mínimo 8 caracteres',
'confirmed' => 'A senha e a confirmação da senha não são iguais',
'unique' => 'Este email já está sendo usado por outro usuário'
];
}
- 166 Concluindo Perfil
class Profile extends Model
{
protected $fillable = ['about', 'phone' , 'social_networks'];
public function getSocialNetworksAttribute()
{
return $this->attributes['social_networks'] ?
json_decode($this->attributes['social_networks'], true) : [];
}
-
167 Iniciando Mensagens de Feedback
-
168 Exibindo Mensagens de Feedback
-
169 Mensagens de Feedback Painel
-
170 Laravel Sluggable e Dicas
composer require spatie/laravel-sluggable
- 171 Utilizando Laravel Sluggable
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
class Category extends Model
{
use HasFactory, HasSlug;
protected $fillable = ['name', 'description', 'slug'];
/**
* Get the options for generating the slug.
*/
public function getSlugOptions() : SlugOptions
{
return SlugOptions::create()
->generateSlugsFrom('name')
->saveSlugsTo('slug');
}
public function events()
{
return $this->belongsToMany(Event::class);
}
}
-
172 Iniciando Verificação de Conta
-
https://gist.github.com/NandoKstroNet/b659f2bb652e1288038f720ce8619586
-
173 Entendendo Mais a Fundo Verificaçãod e Conta
-
174 Traduzindo Emails: Verificação e Resete Senha
-
175 Considerações Finais Bloco
- 176 Introdução
- 177 O que é ACL?
- 178 Gates e Policies Laravel
-
179 Entendendo Projeto ACL
-
180 Praticando Gate
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
//
Gate::define('user-can-access', function () {
return false;
});
Gate::define('user-can-edit', function () {
return false;
});
}
}
class PostController extends Controller
{
public function index()
{
$this->authorize('user-can-access');
return "POSTs";
}
}
- 181 Usuário Autenticado Para Autorização
- 182 Parametros Extras & Método Before
- 183 Gate Denies e Allow
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Gate::before(function ($user) {
if ($result = $user->isAdmin()) {
return $result;
}
});
Gate::define('user-can-access', function ($user) {
return false;
});
Gate::define('user-can-edit', function ($user, $post) {
return $user->posts->contains($post);
// return $post->user->id == $user->id;
// dd($post);
// return $user->isAdmin();
});
}
}
class PostController extends Controller
{
public function index()
{
$this->authorize('user-can-access');
return "POSTs";
}
public function edit($id)
{
$post = \App\Models\Post::find($id);
// Este metodo verifica o controle/ability/permissao e dispara uma exception
// causando um 403 Unauthorized
// $this->authorize('user-can-edit', $post);
//true se o usuário NAO é permitido
// Gate::denies('user-can-edit', $post);
// true se o usuário é permitido
// Gate::allows('user-can-edit', $post);
if (!Gate::allows('user-can-edit', $post)) {
die('VOcê não tem permissão para acessar');
}
return "EDIT POSTs.....";
}
}
- 184 As Policies
$ php artisan make:policy PostPolicy --model=Post
Policy created successfully.
- 185 Diretivas Blade Autorização
<ul>
@foreach($posts as $post)
<li>
{{ $post->title }} - @can('update', $post) <a href="{{ route('post.edit', $post) }}">Editar</a>@endcan
</li>
@endforeach
</ul>
- 186 Uma Abordagem Dinâmica Gates
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Models\Post' => 'App\Policies\PostPolicy',
];
public function boot()
{
$this->registerPolicies();
Gate::before(function ($user) {
if ($result = $user->isAdmin()) {
return $result;
}
});
foreach (\App\Models\Permission::all() as $permission) {
Gate::define($permission->permission, function ($user) use ($permission){
if (!$user->role) {
return false;
}
return $user->role->permissions->contains($permission);
});
}
}
}
- 187 Controle Global via Middleware
$ php artisan make:middleware AccessControlMiddleware
Middleware created successfully.
class AccessControlMiddleware
{
use AuthorizesRequests;
public function handle(Request $request, Closure $next)
{
// dd($request->route()->getName());
$ignoreRoutes = config('acl.ignore');
// dd($ignoreRoutes);
if (!in_array($request->route()->getName(), $ignoreRoutes)) {
$this->authorize($request->route()->getName());
}
return $next($request);
}
}
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Gate::before(function ($user) {
if ($result = $user->isAdmin()) {
return $result;
}
});
if(!Schema::hasTable('permissions')) return null;
foreach (\App\Models\Permission::all() as $permission) {
Gate::define($permission->permission, function ($user) use ($permission){
if (!$user->role) {
return false;
}
return $user->role->permissions->contains($permission);
});
}
}
}
- 188 Mais Métodos de Controle
- 189 Conclusões