updated on: 28th November 2020
Route Naming Conventions
- resource.index
- resource.create
- resource.store
- resource.show
- resource.edit
- resource.update
- resource.destroy
Middleware
this->middleware('auth')
, this->middleware('admin')
Eloquent
Path Prefix
Route::prefix('dashboard')->group(function(){
...
})
Subdomain
Route::domain('api.myapp.com')->group(function(){
})
Name Prefixes
Route::name('users.')->prefix('users');
Signed Routes
They are used to create unique routes for validaton purposes
//normal link
URL::route('invitations',['invitation'=>12345,'answer'=>yes]);
//signed link
URL::signedRoute('invitations',['invitation'=>12345,'answer'=>yes]);
// signed link with expiration
URL::temporarySignedRoute(
'invitations',
now()->addHours(4),
['invitation'=>12345,'answer'=>yes]
);
Views
View Composers
To make all views related to tasks
share the same variable you could use view()->share('variableName','variableValue')
Controllers
Creating a controller
creating a controller php artisan make:controller TaskController
Creating a rousource controller
A resource controller is a controller with some method naming conventions
php artisan make:controller MyResourceController --resource
and binding the controller to route will be Route::resource('tasks','TaskController');
APi Resouce Controllers
php artisan make:controll MyResourceController --api
and binding Route::apiResource('tasks','TasksController')
Single action controllers
they use the __invoke()
method for single action
// App\http\Controllers\UpdateUserAvatar
public function __invoke(User $user){
//your code
}
binding the route
Route::post('users/user/update-avatar','updateUserAvatar')
;
Form Spoofing
<form action="tasks/5/" method="Post">
@method('DELETE')
</form>
Redirects
return redirect()->to('login')
return redirect('loging')
returen Redirect::to('login')
return redirect()->route('conferences.index')
return redirect()->back()
return redirect()->home()
return redirect()->refresh()
return redirect()->away()
return redirect()->action([Mycontroller::class],'index')
return redirect()->guest()
return redirect()->intended()
return redirect()->with('error',true)
used to pass data along
Aborting a request
Route::post('...',function(){
abort(403,"You can't do this");
abort_unless($request->has('magicToken'),403);
})
Custom Responses
Response()->make()
response->make(Hello,World)
used to pass data
Response()->json() and ->jsonp()
response->json(User::all())
Response()->download(), ->streamDownload(), and ->file()
return response()->dowload('mydriv3453453454.pdf','renamedfile.pdf')
to display the file in the browser response()->file('mydriv3453453454.pdf')
Blade Templating
Conditionals
-
@if(condition) @elseif(condition) @else @endif
-
@unless($user->hasPaid()) @endunless
Loops
-
@for(condition) @endfor
-
@foreach(condition) @endforeach
-
@while(condition) @endwhile
-
@forelse(condition) @empty @endforelse
$loop
within @foreach and @forelse
-
$loop->index
the 0 based index -
$loop->iteration
the 1 based index -
$loop->remaining
checks how many items in the loop -
$loop->count
counts how many items in the loop -
$loop->first
indicates the first item -
$loop->last
indicates the last item -
$loop->depth
-
$loop->parent
references the parent loop item
<ul>
@foreach($pages as $page)
<li> :
@if($page->hasChildren())
<ul>
@foreach($page->children() as $child)
<li>
</li>
@endforeach
</ul>
@endif
</li>
@enforeach
</ul>
Template Inheritance
@section/@show and @yield
@yield
<title> My Site | @yield('title', 'Home Page') </title>
<div class="container">
@yield('content')
</div>
@section('footerScripts')
<script type="app.js"></script>
@show
Extending blade layout
@extends('layouts.master')
@section('title','dashboard')
@section('content')
welcome
@endsection
@section('footerScripts')
@parent
<script type="dashboard.js"></script>
@endsection
@include('sign-up-button',['text'=>'see just how great it is'])
<a class="button">
</a>
Includes
-
@includeIf('sidebars.admin',['some'=>'data'])
include if view exist -
@includeWhen($user->isAdmin()),'sidebars.admin', ['some'=>'data'])
include if it’s admin -
@includeFirst(['customs.header','header'],['some'=>data])
include first view from array
@stack and @push
define @stack(scripts)
in master and @push('scripts') <script src="jobs.css"></script>
to push something in child template at the bottom and @prepend('scripts')...@endprepend
at the top of the stack
Databases
Migrations
Creating Migrations
php artisan make:migration create_users_table
php artisan make:migration add_votes_to_users_table --table=users
php artisan make:migration create_users_table --create=users
Migration blueprints methods
-
integer(columName)
tinyInteger(columName)
smallInteger(columName)
mediumInteger(columName)
-
string(colName, length)
-
binary(colName)
-
boolean(colName)
-
char(colName, length)
-
datetime(colName)
-
decimal(colName)
-
double(colName, precision, scale)
i.edecimal('amount',5,2)
-
enum
-
float(colName, precision, scale)
-
json(colName) or jsonb(colName)
-
text(colName)
` mediumText(colName) -
time(colName)
-
timestamp(colName)
-
uuid(colName)
-
increments(colName)
-
timestamps()
andnullableTimestamps()
-
rememberToken()
-
softDeletes()
-
mordphs(colName)
Migration blueprints extra properties
-
nullable()
-
default('default content')
-
unsigned()
-
first()
for mysql -
after(colName)
for mysql too -
unique()
-
primary()
-
index()
Indexes and foreign keys
Indexes are used for performance optimization and data integrity.
$table->index('amount') // basic index
$table->index('amount', 'amount_index') //basic index with index name
$table->unique('email') // unique index
$table->primary('user_id')
$table->foreign('user_id')->references('id')->on('users'); // foreign Id
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); // foreign Id with constraints
Seeding
-
php artisan migrate --seed
orphp artisan migrate:refresh --seed
runs migrations and seeding database after -
php artisan db:seed
orphp artisan db:seed --class=VotesTableSeeder
runs only seeders or particular seed.
creating a seeder
php artisan make:seeder ContactTableSeeder
calling the seed class
// DtabaseSeeder
public function run(){
$this->call(ContactTableSeeder::class);
}
// contactsTableSeeder
public function run(){
DB::table('contacts')->insert([
'name'=>'Lupita Smith',
'email'=>'lupita@gmail.com',
]);
}
Model Factories
Defining a model factories with eloquent. It’s good to name the factory after your eloquent class.
$factory->define(User::class, function(Faker\Generator $faker){
return [
'name'=> $faker->name,
];
});
$factory->define('users',function(Faker\Generator $faker){
return[
'name'=>$faker->name,
];
});
creating a model factory
php artisan make:factory ContactFactory
defining a factory
Factory are usually used for testing and seeding.
$factory->define(Contact::class, function(Faker\Generator $faker){
return [
'name'=>'Lupita Smith',
'email'=>'lupita@gmail.com',
];
// or you can use faker to generate different entiries
return [
'name'=> $faker->name,
'email'=>$faker->email, or //creating unique $faker->unique()->email;
];
});
//creating one
$contact = factory(Contact::class)->create();
//create many
factory(Contact::class,20)->create();
Attaching relationships with factories
$factory->define(Contact::class, function(Faker\Generator $faker){
return [
'name'=>'Lupita Smith',
'email'=>'lupita@gmail.com',
'company_id'=> function(){
return factory(App\Company::class)->create()->id;
}
];
});
Query Builder
$users = DB::select(['table'=>'users','where'=>['type'=>'donor']]); //non-fluent
$users = DB::table('users')->where('type','donor')->get(); //fluent
Eloquent
Creating an eloquent model
php artisan make:model Contact
php artisan make:model Contact --migration
creates a migration along with your model
protected $table= 'contacts_secondary'; //customizing tablename
protected $primaryKey='contact_id'; // changing the primary key
public $incrementing = false; // turning of incrementing id;
public $timestamps = false; // turns of timestamps
protected $fillable = ['name','email']; //fields allowed in case of mass assignment
protected $guarded =['id','created_at','owner_id']; // fields disallowed in case of mass assignment
Request->only()
Contact::create($request->only('name','email'))
; simpler way for mass assignment selecting the necessary fields.
Deleting with eloquent
$contact = Contact::find(4);
$contact->delete();
//or
$contact->destory(1);
Soft Deletes
use SoftDeletes;
protected $dates = ['deleted_at']; // make this column as a date
Eloquent Relationships
One to One
public function phoneNumber(){
return $this->hasOne(PhoneNumber::class,'owner_id');
}
// accessing
$contact = Contact::first();
$contactPhone = $contact->phoneNumber;
//getting the contact from phone number
public function contact(){
return $this->belongsTo(Contact::class);
}
//accessing
$contact = $phoneNumber->contact;
//inserting related items
$contact = Contact::first();
$phoneNumber = new PhoneNumber;
$contact->phoneNumbers()->save($phoneNumber);
One to Many
public function contacts(){
return $this->hasMany(Contact::class);
}
//accessing
$user = User::first();
$usersContacts = $user->contacts;
public function user(){
return $this->belongsTo(User::class);
}
//accessing
$userName = $contact->user->name;
Attaching and detaching
$contact = Contact::first();
$contact->user()->associate(User::first));
$contact->save();
$contact->user()->dissociate();
$contact->save();
Relationships with query builder
$donors = $user->contacts()->where('status','donor')->get();
FrontEnd Components
Laravel Mix
//webpack configuration
var path = require('path');
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports={
entry: './src/sass/app.scss',
module: {
rules:[
{
test:/\.s[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
path: path.resolve(__dirname, './dist'),
filename: 'app.css'
})
]
}
// larave mix configuration
let mix = require('laravel-mix');
mix.sass('resources/sass/app.scss','public/css');
Enabling source maps
let mix = require('laravel-mix');
mix.js('resources/js/app.js','public/js').sourceMaps();
Concatinating files
let mix = require('laravel-mix');
//processing javascript
mix.js('resources/js/app.js','public/js');
//concatenating scripts
mix.scripts([
'resources/js/normalize.js',
'resources/js/app.js',
],'public/js/all.js');
// concatenating styles
mix.styles([
'resources/css/normalize.css',
'resources/css/app.css'
],'public/css/all.css');
Frontend Presets
- php artisan preset react
- php artisan preset bootstrap
- php artisan preset none
Installing a preset
composer require laravel-frontend-presets/tailwindcss
then php artisan preset tailwindcss
Pagination
``
Collection and Handling User Data
-
$request->all()
-
$request->except()
and$request->only()
i.e$request->except('_token');
-
$request->has()
i.e$request->has('utm')
; -
$request->input('name')
-
$request->isMethod('patch')
-
$request->json()
validating file upload
if($request->hasFile('profile_picture') && $request->file('profile_picture')->isValid())
Artisan and Thinker
Creating Commands
// creating commands
#bash
php artisan make:command ResetUser --command=reset:userreset
#arguments and options
protected $signature = 'password:reset {userId} {--sendEmail}';
# arguments and options with descriptions
protected $signature = 'password:reset {userId} {--sendEmail}';
protected $signature = 'password:reset {userId=1} {--sendEmail}';
# requires value
protected $signature = 'password:reset {userId} {--password=}';
# defining description text
protected $signature = 'password:reset
{userId: the Id of the user
--sendEmail: wheter to send user an email
}';
# getting input from user on artisan command
public function handle(){
// all arguments
$arguments= $this->arguments();
//getting specific argument
$userid = $this->argument('userId');
// getting all options
$options = $this->options();
//getting specific options
$sendEmail = $this->option('sendEmail');
#prompting user for input
//ask()
$email = $this->ask('What is your email address?');
//secrets like password
$password = $this->secret('what is the db password');
// confirmation yes/no
if($this->confirm('do you want to delete this user?')){
// all answers except Y will be treated as no
}
//choice
$winner = $this->choice('who is the best at singing',['ed sheeran','the weekend'],0)
$winner = $this->choice('who is the best at singing',['ed'=>ed sheeran','weekend'=>'the weekend'],'ed');
# output
$this->info('Your command has run successfully.')
}
writing a closure based command
// routes/console.php
Artisan::command(
'password:reset {userId} {--sendEmail}',
function($userId, $sendEmail){
$userId = $this->argument('userId');
}
)
calling artisan command with normal code
Route::get('test-artisan', function(){
$exitCode = Artisan::call('password:reset',[
'userId'=>15,
'--sendEmail'=>true,
])
})
Authentication and Authorization
Creating auth files
php artisan make:auth
-
Authentication means verify the identity of someone
-
Authorization means verify if the authenticated user is allowed to perform some act.
Authorization
can()
Authentication
-
auth()->check()
checks if the user is authenticated or not -
auth()->id()
-
auth()->guest()
-
auth()->user()->id()
-
auth()->guest()
making user verify their email Auth::routes(['verify'=>true]);
turning off registration route Auth::routes(['register'=>false]);
turning off account reset Auth::routes(['reset'=>false]);
Attemping user authentication
// attempting login
if(auth()->attempt([
'email'=>$request->input('email');
'password'=>$request->input('password')
])){
// handle the successful login
}
// attempting login with remmber me token
if(auth()->attempt([
'email'=>$request->input('email');
'password'=>$request->input('password');
]),request()->filled('remember')){
// handle the successful login
}
Policies
Making a policy
php artisan make:policy ContactPolicy
Request & Response Object
-
all()
returns all user inputed data -
input(fieldname)
-
only(fiieldName or ['field names'])
-
except(fieldName | ['fieldnames']
-
exists(fieldname)
orhas(fieldname)
-
filled(fieldname)
checks if field exists and is not empty -
json()
returns json -
json(keyname)
returns given key in json
Request state methods
-
method(Get,post,patch, etc.)
-
path()
returns the path -
url()
returns the url with full domain name -
is('*b*')
fuzzy matches any character -
ip()
returns user ip -
header()
returns an array of the headers
Redirecting
-
redirect('account/payment')
-
redirect()->to('account/payment')
-
redirect()->route('account.payment')
-
redirect()->action('AccountController@showPayment')
-
redirect()->away('https://tighten.co');
redirecting to an external domain -
return back()->withInput('name');
-
return redirect('dashboard')->with('message','contact created');
and to get messageecho session('message')
in the function
Middleware
Creating a middleware
php artisan make:middleware BanDeleteMethod
Testing
Testing Terms
-
Unit Tests
target small, relatively isolated units. class or methods -
feature tests
tests the way individual unites work together and pass messages -
application tests
test usually http calls and behavior of the application -
regression test
usually to test what the user should be able to do
Creating test
-
php artisan make:test FailingTest
for creating feature test -
php artisan make:test SubscriptionTest --unit
for creating unit test
Naming tests
Test that will run and the ones that doesn’t
public function test_it_names_things_well(){
// runs
}
public function testTtNamesThingsWell(){
//runs
}
/** @test */
public function it_names_things_well(){
//runs
}
public function it_names_things_well(){
// doesn't run
}
laravel automatically set your environment to testing when it runs test; it also uses phpunit.xml for it’s environment variables or you can make a copy of .env.example
and rename it to .env.testing
for phpunit to use that file as the environment variables files.
The Testing Traits
-
RefreshDatabase
withIlluminate\Foundation\Testing\RefreshDatabase
runs migration in your test database at the beginning and wraps each test method with transactions -
WithoutMiddleware
withIlluminate\Foundation\Testing\WithouthMiddleware
disable all middleware when running test -
DatabaseMigrations
withIlluminate\Foundation\Testing\DatabaseMigrations
runsphp artisan migrate:fresh
before every test runs -
DatabaseTransactions
withIlluminate\Foundation\Testing\DatabaseTransactions
wraps every test in database transaction, so it returns them back to exact state after the test ends
Writing APIs
Making Apic Controllers
php artisan make:controller Api\DogsController --api
Routing for api
Route::namespace('Api')->group(function(){
Route::apiResource('dogs','DogsController');
})
Sending Response Headers in laravel
Route::get('dogs',function(){
return response(Dog::all())->header('x-Greatness-Index',12);
})
Reading Request Headers in laravel
Route::get('dogs',function(Request $request){
var_dump($request->header('Accept'));
})
Eloquent Pagination for API
Route::get('dogs',function(){
retun Dog::paginate(20);
})
// so pagination in api will be
GET /dogs
GET /dogs?page=1
GET /dogs?page=2
Api Resources
Creating APi Resources
php artisan make:resource Dog
Mail and Notifications
php artisan make:mail AssignmentCreated
Mail Markdown components
-
button
-
panel
-
table
Queueing Mails
Mail::queue(new AssignmentCreate($trainer, $trainee))
//later()
$when = now()->addMinutes(30);
Mail::later($when, new AssignmentCreated($trainer, $trainee));
Notifications
php artisan make:notification WorkoutAvailable
Sending Notifications
Notification::send($users, new WorkoutAvailable($workout));
Queueing notificatons
$delayUntil = now()->addMinutes(15);
$user->notify((new WorkoutAvailable($workout))->delay($delayUntil));