Table of Contents · Laravel 5.0 Laravel 4.2 Laravel 4.1 Laravel 5.0 introduces a fresh application...

Post on 06-Aug-2020

19 views 3 download

transcript

1. Introduction2. Prologue

i. ReleaseNotesi. Laravel5.0ii. Laravel4.2iii. Laravel4.1

ii. UpgradeGuidei. UpgradingTo5.0From4.2ii. UpgradingTo4.2From4.1iii. UpgradingTo4.1.29From<=4.1.xiv. UpgradingTo4.1.26From<=4.1.25v. UpgradingTo4.1From4.0

iii. ContributionGuidei. BugReportsii. CoreDevelopmentDiscussioniii. WhichBranch?iv. SecurityVulnerabilitiesv. CodingStyle

3. Setupi. Installation

i. InstallComposerii. InstallLaraveliii. ServerRequirements

ii. Configurationi. Introductionii. AfterInstallationiii. AccessingConfigurationValuesiv. EnvironmentConfigurationv. ConfigurationCachingvi. MaintenanceModevii. PrettyURLs

iii. Homesteadi. Introductionii. IncludedSoftwareiii. Installation&Setupiv. DailyUsagev. Ports

4. TheBasicsi. Routing

i. BasicRoutingii. CSRFProtectioniii. MethodSpoofingiv. RouteParametersv. NamedRoutesvi. RouteGroupsvii. RouteModelBindingviii. Throwing404Errors

ii. Middlewarei. Introductionii. DefiningMiddlewareiii. RegisteringMiddlewareiv. TerminableMiddleware

TableofContents

iii. Controllersi. Introductionii. BasicControllersiii. ControllerMiddlewareiv. ImplicitControllersv. RESTfulResourceControllersvi. DependencyInjection&Controllersvii. RouteCaching

iv. Requestsi. ObtainingARequestInstanceii. RetrievingInputiii. OldInputiv. Cookiesv. Filesvi. OtherRequestInformation

v. Responsesi. BasicResponsesii. Redirectsiii. OtherResponsesiv. ResponseMacros

vi. Viewsi. BasicUsageii. ViewComposers

5. ArchitectureFoundationsi. ServiceProviders

i. Introductionii. BasicProviderExampleiii. RegisteringProvidersiv. DeferredProviders

ii. ServiceContaineri. Introductionii. BasicUsageiii. BindingInterfacesToImplementationsiv. ContextualBindingv. Taggingvi. PracticalApplicationsvii. ContainerEvents

iii. Contractsi. Introductionii. WhyContracts?iii. ContractReferenceiv. HowToUseContracts

iv. Facadesi. Introductionii. Explanationiii. PracticalUsageiv. CreatingFacadesv. MockingFacadesvi. FacadeClassReference

v. RequestLifecyclei. Introductionii. LifecycleOverviewiii. FocusOnServiceProviders

vi. ApplicationStructurei. Introductionii. TheRootDirectory

iii. TheAppDirectoryiv. NamespacingYourApplication

6. Servicesi. Authentication

i. Introductionii. AuthenticatingUsersiii. RetrievingTheAuthenticatedUseriv. ProtectingRoutesv. HTTPBasicAuthenticationvi. PasswordReminders&Resetvii. SocialAuthentication

ii. Billingi. Introductionii. Configurationiii. SubscribingToAPlaniv. NoCardUpFrontv. SwappingSubscriptionsvi. SubscriptionQuantityvii. CancellingASubscriptionviii. ResumingASubscriptionix. CheckingSubscriptionStatusx. HandlingFailedPaymentsxi. HandlingOtherStripeWebhooksxii. Invoices

iii. Cachei. Configurationii. CacheUsageiii. Increments&Decrementsiv. CacheTagsv. DatabaseCache

iv. Collectionsi. Introductionii. BasicUsage

v. CommandBusi. Introductionii. CreatingCommandsiii. DispatchingCommandsiv. QueuedCommandsv. CommandPipeline

vi. CoreExtensioni. Managers&Factoriesii. Cacheiii. Sessioniv. Authenticationv. IoCBasedExtension

vii. Elixiri. Introductionii. Installation&Setupiii. Usageiv. Gulpv. Extensions

viii. Encryptioni. Introductionii. BasicUsage

ix. Errors&Loggingi. Configuration

ii. HandlingErrorsiii. HTTPExceptionsiv. Logging

x. Eventsi. BasicUsageii. QueuedEventHandlersiii. EventSubscribers

xi. Filesystem/CloudStoragei. Introductionii. Configurationiii. BasicUsage

xii. Hashingi. Introductionii. BasicUsage

xiii. Helpersi. Arraysii. Pathsiii. Stringsiv. URLsv. Miscellaneous

xiv. Localizationi. Introductionii. LanguageFilesiii. BasicUsageiv. Pluralizationv. ValidationLocalizationvi. OverridingPackageLanguageFiles

xv. Maili. Configurationii. BasicUsageiii. EmbeddingInlineAttachmentsiv. QueueingMailv. Mail&LocalDevelopment

xvi. PackageDevelopmenti. Introductionii. Viewsiii. Translationsiv. Configurationv. PublishingFileGroupsvi. Routing

xvii. Paginationi. Configurationii. Usageiii. AppendingToPaginationLinksiv. ConvertingToJSON

xviii. Queuesi. Configurationii. BasicUsageiii. QueueingClosuresiv. RunningTheQueueListenerv. DaemonQueueWorkervi. PushQueuesvii. FailedJobs

xix. Sessioni. Configurationii. SessionUsage

iii. FlashDataiv. DatabaseSessionsv. SessionDrivers

xx. Templatesi. BladeTemplatingii. OtherBladeControlStructuresiii. ExtendingBlade

xxi. UnitTestingi. Introductionii. Defining&RunningTestsiii. TestEnvironmentiv. CallingRoutesFromTestsv. MockingFacadesvi. FrameworkAssertionsvii. HelperMethodsviii. RefreshingTheApplication

xxii. Validationi. BasicUsageii. ControllerValidationiii. FormRequestValidationiv. WorkingWithErrorMessagesv. ErrorMessages&Viewsvi. AvailableValidationRulesvii. ConditionallyAddingRulesviii. CustomErrorMessagesix. CustomValidationRules

7. Databasei. BasicUsage

i. Configurationii. Read/WriteConnectionsiii. RunningQueriesiv. DatabaseTransactionsv. AccessingConnectionsvi. QueryLogging

ii. QueryBuilderi. Introductionii. Selectsiii. Joinsiv. AdvancedWheresv. Aggregatesvi. RawExpressionsvii. Insertsviii. Updatesix. Deletesx. Unionsxi. PessimisticLocking

iii. EloquentORMi. Introductionii. BasicUsageiii. MassAssignmentiv. Insert,Update,Deletev. SoftDeletingvi. Timestampsvii. QueryScopesviii. GlobalScopesix. Relationships

x. QueryingRelationsxi. EagerLoadingxii. InsertingRelatedModelsxiii. TouchingParentTimestampsxiv. WorkingWithPivotTablesxv. Collectionsxvi. Accessors&Mutatorsxvii. DateMutatorsxviii. AttributeCastingxix. ModelEventsxx. ModelObserversxxi. ConvertingToArrays/JSON

iv. SchemaBuilderi. Introductionii. Creating&DroppingTablesiii. AddingColumnsiv. ChangingColumnsv. RenamingColumnsvi. DroppingColumnsvii. CheckingExistenceviii. AddingIndexesix. ForeignKeysx. DroppingIndexesxi. DroppingTimestamps&SoftDeletesxii. StorageEngines

v. Migrations&Seedingi. Introductionii. CreatingMigrationsiii. RunningMigrationsiv. RollingBackMigrationsv. DatabaseSeeding

vi. Redisi. Introductionii. Configurationiii. Usageiv. Pipelining

8. ArtisanCLIi. Overview

i. Introductionii. Usageiii. CallingCommandsOutsideOfCLIiv. SchedulingArtisanCommands

ii. Developmenti. Introductionii. BuildingACommandiii. RegisteringCommands

AGitBookversionofLaravel5.0Documentation

Introduction

ReleaseNotesLaravel5.0Laravel4.2Laravel4.1

UpgradeGuideUpgradingTo5.0From4.2UpgradingTo4.2From4.1UpgradingTo4.1.29From<=4.1.xUpgradingTo4.1.26From<=4.1.25UpgradingTo4.1From4.0

ContributionGuideBugReportsCoreDevelopmentDiscussionWhichBranch?SecurityVulnerabilitiesCodingStyle

Prologue

Laravel5.0Laravel4.2Laravel4.1

Laravel5.0introducesafreshapplicationstructuretothedefaultLaravelproject.ThisnewstructureservesasabetterfoundationforbuildingrobustapplicationinLaravel,aswellasembracesnewauto-loadingstandards(PSR-4)throughouttheapplication.First,let'sexaminesomeofthemajorchanges:

Theoldapp/modelsdirectoryhasbeenentirelyremoved.Instead,allofyourcodelivesdirectlywithintheappfolder,and,bydefault,isorganizedtotheAppnamespace.Thisdefaultnamespacecanbequicklychangedusingthenewapp:nameArtisancommand.

Controllers,middleware,andrequests(anewtypeofclassinLaravel5.0)arenowgroupedundertheapp/Httpdirectory,astheyareallclassesrelatedtotheHTTPtransportlayerofyourapplication.Insteadofasingle,flatfileofroutefilters,allmiddlewarearenowbrokenintotheirownclassfiles.

Anewapp/Providersdirectoryreplacestheapp/startfilesfrompreviousversionsofLaravel4.x.Theseserviceprovidersprovidevariousbootstrappingfunctionstoyourapplication,suchaserrorhandling,logging,routeloading,andmore.Ofcourse,youarefreetocreateadditionalserviceprovidersforyourapplication.

Applicationlanguagefilesandviewshavebeenmovedtotheresourcesdirectory.

AllmajorLaravelcomponentsimplementinterfaceswhicharelocatedintheilluminate/contractsrepository.Thisrepositoryhasnoexternaldependencies.Havingaconvenient,centrallylocatedsetofinterfacesyoumayusefordecouplinganddependencyinjectionwillserveasaneasyalternativeoptiontoLaravelFacades.

Formoreinformationoncontracts,consultthefulldocumentation.

Ifyourapplicationismadeupentirelyofcontrollerroutes,youmayutilizethenewroute:cacheArtisancommandtodrasticallyspeeduptheregistrationofyourroutes.Thisisprimarilyusefulonapplicationswith100+routesandwilldrasticallyspeedupthisportionofyourapplication.

InadditiontoLaravel4styleroute"filters",Laravel5nowsupportsHTTPmiddleware,andtheincludedauthenticationandCSRF"filters"havebeenconvertedtomiddleware.Middlewareprovidesasingle,consistentinterfacetoreplacealltypesoffilters,allowingyoutoeasilyinspect,andevenreject,requestsbeforetheyenteryourapplication.

Formoreinformationonmiddleware,checkoutthedocumentation.

Inadditiontotheexistingconstructorinjection,youmaynowtype-hintdependenciesoncontrollermethods.TheIoCcontainerwillautomaticallyinjectthedependencies,eveniftheroutecontainsotherparameters:

ReleaseNotes

Laravel5.0

NewFolderStructure

Contracts

RouteCache

RouteMiddleware

ControllerMethodInjection

publicfunctioncreatePost(Request$request,PostRepository$posts)

{

//

}

Userregistration,authentication,andpasswordresetcontrollersarenowincludedoutofthebox,aswellassimplecorrespondingviews,whicharelocatedatresources/views/auth.Inaddition,a"users"tablemigrationhasbeenincludedwiththeframework.Includingthesesimpleresourcesallowsrapiddevelopmentofapplicationideaswithoutboggingdownonauthenticationboilerplate.Theauthenticationviewsmaybeaccessedontheauth/loginandauth/registerroutes.TheApp\Services\Auth\Registrarserviceisresponsibleforuservalidationandcreation.

Youmaynowdefineeventsasobjectsinsteadofsimplyusingstrings.Forexample,checkoutthefollowingevent:

classPodcastWasPurchased{

public$podcast;

publicfunction__construct(Podcast$podcast)

{

$this->podcast=$podcast;

}

}

Theeventmaybedispatchedlikenormal:

Event::fire(newPodcastWasPurchased($podcast));

Ofcourse,youreventhandlerwillreceivetheeventobjectinsteadofalistofdata:

classReportPodcastPurchase{

publicfunctionhandle(PodcastWasPurchased$event)

{

//

}

}

Formoreinformationonworkingwithevents,checkoutthefulldocumentation.

InadditiontothequeuejobformatsupportedinLaravel4,Laravel5allowsyoutorepresentyourqueuedjobsassimplecommandobjects.Thesecommandsliveintheapp/Commandsdirectory.Here'sasamplecommand:

classPurchasePodcastextendsCommandimplementsSelfHandling,ShouldBeQueued{

useSerializesModels;

protected$user,$podcast;

/**

*Createanewcommandinstance.

*

*@returnvoid

AuthenticationScaffolding

EventObjects

Commands/Queueing

*/

publicfunction__construct(User$user,Podcast$podcast)

{

$this->user=$user;

$this->podcast=$podcast;

}

/**

*Executethecommand.

*

*@returnvoid

*/

publicfunctionhandle()

{

//Handlethelogictopurchasethepodcast...

event(newPodcastWasPurchased($this->user,$this->podcast));

}

}

ThebaseLaravelcontrollerutilizesthenewDispatchesCommandstrait,allowingyoutoeasilydispatchyourcommandsforexecution:

$this->dispatch(newPurchasePodcastCommand($user,$podcast));

Ofcourse,youmayalsousecommandsfortasksthatareexecutedsynchonrously(arenotqueued).Infact,usingcommandsisagreatwaytoencapsulatecomplextasksyourapplicationneedstoperform.Formoreinformation,checkoutthecommandbusdocumentation.

AdatabasequeuedriverisnowincludedinLaravel,providingasimple,localqueuedriverthatrequiresnoextrapackageinstallationbeyondyourdatabasesoftware.

Inthepast,developershavegeneratedaCronentryforeachconsolecommandtheywishedtoschedule.However,thisisaheadache.Yourconsolescheduleisnolongerinsourcecontrol,andyoumustSSHintoyourservertoaddtheCronentries.Let'smakeourliveseasier.TheLaravelcommandschedulerallowsyoutofluentlyandexpressivelydefineyourcommandschedulewithinLaravelitself,andonlyasingleCronentryisneededonyourserver.

Itlookslikethis:

$schedule->command('artisan:command')->dailyAt('15:00');

Ofcourse,checkoutthefulldocumentationtolearnallaboutthescheduler!

ThephpartisantinkercommandnowutilizesPsyshbyJustinHileman,amorerobustREPLforPHP.IfyoulikedBorisinLaravel4,you'regoingtolovePsysh.Evenbetter,itworksonWindows!Togetstarted,justtry:

phpartisantinker

Insteadofavarietyofconfusing,nestedenvironmentconfigurationdirectories,Laravel5nowutilizesDotEnvbyVance

DatabaseQueue

LaravelScheduler

Tinker/Psysh

DotEnv

Lucas.Thislibraryprovidesasupersimplewaytomanageyourenvironmentconfiguration,andmakesenvironmentdetectioninLaravel5abreeze.Formoredetails,checkoutthefullconfigurationdocumentation.

LaravelElixir,byJeffreyWay,providesafluent,expressiveinterfacetocompilingandconcatenatingyourassets.Ifyou'veeverbeenintimidatedbylearningGruntorGulp,fearnomore.ElixirmakesitacinchtogetstartedusingGulptocompileyourLess,Sass,andCoffeeScript.Itcanevenrunyourtestsforyou!

FormoreinformationonElixir,checkoutthefulldocumentation.

LaravelSocialiteisanoptional,Laravel5.0+compatiblepackagethatprovidestotallypainlessauthenticationwithOAuthproviders.Currently,SocialitesupportsFacebook,Twitter,Google,andGitHub.Here'swhatitlookslike:

publicfunctionredirectForAuth()

{

returnSocialize::with('twitter')->redirect();

}

publicfunctiongetUserFromProvider()

{

$user=Socialize::with('twitter')->user();

}

NomorespendinghourswritingOAuthauthenticationflows.Getstartedinminutes!Thefulldocumentationhasallthedetails.

LaravelnowincludesthepowerfulFlysystemfilesystemabstractionlibrary,providingpainfreeintegrationwithlocal,AmazonS3,andRackspacecloudstorage-allwithone,unifiedandelegantAPI!StoringafileinAmazonS3isnowassimpleas:

Storage::put('file.txt','contents');

FormoreinformationontheLaravelFlysystemintegration,consultthefulldocumentation.

Laravel5.0introducesformrequests,whichextendtheIlluminate\Foundation\Http\FormRequestclass.Theserequestobjectscanbecombinedwithcontrollermethodinjectiontoprovideaboiler-platefreemethodofvalidatinguserinput.Let'sdiginandlookatasampleFormRequest:

<?phpnamespaceApp\Http\Requests;

classRegisterRequestextendsFormRequest{

publicfunctionrules()

{

return[

'email'=>'required|email|unique:users',

'password'=>'required|confirmed|min:8',

];

}

publicfunctionauthorize()

{

returntrue;

}

LaravelElixir

LaravelSocialite

FlysystemIntegration

FormRequests

}

Oncetheclasshasbeendefined,wecantype-hintitonourcontrolleraction:

publicfunctionregister(RegisterRequest$request)

{

var_dump($request->input());

}

WhentheLaravelIoCcontaineridentifiesthattheclassitisinjectingisaFormRequestinstance,therequestwillautomaticallybevalidated.Thismeansthatifyourcontrolleractioniscalled,youcansafelyassumetheHTTPrequestinputhasbeenvalidatedaccordingtotherulesyouspecifiedinyourformrequestclass.Evenmore,iftherequestisinvalid,anHTTPredirect,whichyoumaycustomize,willautomaticallybeissued,andtheerrormessageswillbeeitherflashedtothesessionorconvertedtoJSON.Formvalidationhasneverbeenmoresimple.FormoreinformationonFormRequestvalidation,checkoutthedocumentation.

TheLaravel5basecontrollernowincludesaValidatesRequeststrait.Thistraitprovidesasimplevalidatemethodtovalidateincomingrequests.IfFormRequestsarealittletoomuchforyourapplication,checkthisout:

publicfunctioncreatePost(Request$request)

{

$this->validate($request,[

'title'=>'required|max:255',

'body'=>'required',

]);

}

Ifthevalidationfails,anexceptionwillbethrownandtheproperHTTPresponsewillautomaticallybesentbacktothebrowser.Thevalidationerrorswillevenbeflashedtothesession!IftherequestwasanAJAXrequest,LaraveleventakescareofsendingaJSONrepresentationofthevalidationerrorsbacktoyou.

Formoreinformationonthisnewmethod,checkoutthedocumentation.

Tocomplimentthenewdefaultapplicationstructure,newArtisangeneratorcommandshavebeenaddedtotheframework.Seephpartisanlistformoredetails.

Youmaynowcacheallofyourconfigurationinasinglefileusingtheconfig:cachecommand.

Thepopularddhelperfunction,whichdumpsvariabledebuginformation,hasbeenupgradedtousetheamazingSymfonyVarDumper.Thisprovidescolor-codedoutputandevencollapsingofarrays.Justtrythefollowinginyourproject:

dd([1,2,3]);

Thefullchangelistforthisreleasebyrunningthephpartisanchangescommandfroma4.2installation,orbyviewingthe

SimpleControllerRequestValidation

NewGenerators

ConfigurationCache

SymfonyVarDumper

Laravel4.2

changefileonGithub.Thesenotesonlycoverthemajorenhancementsandchangesfortherelease.

Note:Duringthe4.2releasecycle,manysmallbugfixesandenhancementswereincorporatedintothevariousLaravel4.1pointreleases.So,besuretocheckthechangelistforLaravel4.1aswell!

Laravel4.2requiresPHP5.4orgreater.ThisupgradedPHPrequirementallowsustousenewPHPfeaturessuchastraitstoprovidemoreexpressiveinterfacesfortoolslikeLaravelCashier.PHP5.4alsobringssignificantspeedandperformanceimprovementsoverPHP5.3.

LaravelForge,anewwebbasedapplication,providesasimplewaytocreateandmanagePHPserversonthecloudofyourchoice,includingLinode,DigitalOcean,Rackspace,andAmazonEC2.SupportingautomatedNginxconfiguration,SSHkeyaccess,Cronjobautomation,servermonitoringviaNewRelic&Papertrail,"PushToDeploy",Laravelqueueworkerconfiguration,andmore,ForgeprovidesthesimplestandmostaffordablewaytolaunchallofyourLaravelapplications.

ThedefaultLaravel4.2installation'sapp/config/database.phpconfigurationfileisnowconfiguredforForgeusagebydefault,allowingformoreconvenientdeploymentoffreshapplicationsontotheplatform.

MoreinformationaboutLaravelForgecanbefoundontheofficialForgewebsite.

LaravelHomesteadisanofficialVagrantenvironmentfordevelopingrobustLaravelandPHPapplications.Thevastmajorityoftheboxes'provisioningneedsarehandledbeforetheboxispackagedfordistribution,allowingtheboxtobootextremelyquickly.HomesteadincludesNginx1.6,PHP5.6,MySQL,Postgres,Redis,Memcached,Beanstalk,Node,Gulp,Grunt,&Bower.HomesteadincludesasimpleHomestead.yamlconfigurationfileformanagingmultipleLaravelapplicationsonasinglebox.

ThedefaultLaravel4.2installationnowincludesanapp/config/local/database.phpconfigurationfilethatisconfiguredtousetheHomesteaddatabaseoutofthebox,makingLaravelinitialinstallationandconfigurationmoreconvenient.

TheofficialdocumentationhasalsobeenupdatedtoincludeHomesteaddocumentation.

LaravelCashierisasimple,expressivelibraryformanagingsubscriptionbillingwithStripe.WiththeintroductionofLaravel4.2,weareincludingCashierdocumentationalongwiththemainLaraveldocumentation,thoughinstallationofthecomponentitselfisstilloptional.ThisreleaseofCashierbringsnumerousbugfixes,multi-currencysupport,andcompatibilitywiththelatestStripeAPI.

TheArtisanqueue:workcommandnowsupportsa--daemonoptiontostartaworkerin"daemonmode",meaningtheworkerwillcontinuetoprocessjobswithouteverre-bootingtheframework.ThisresultsinasignificantreductioninCPUusageatthecostofaslightlymorecomplexapplicationdeploymentprocess.

Moreinformationaboutdaemonqueueworkerscanbefoundinthequeuedocumentation.

Laravel4.2introducesnewMailgunandMandrillAPIdriversfortheMailfunctions.Formanyapplications,thisprovidesafasterandmorereliablemethodofsendinge-mailsthantheSMTPoptions.ThenewdriversutilizetheGuzzle4HTTPlibrary.

PHP5.4Requirement

LaravelForge

LaravelHomestead

LaravelCashier

DaemonQueueWorkers

MailAPIDrivers

Amuchcleanerarchitecturefor"softdeletes"andother"globalscopes"hasbeenintroducedviaPHP5.4traits.Thisnewarchitectureallowsfortheeasierconstructionofsimilarglobaltraits,andacleanerseparationofconcernswithintheframeworkitself.

MoreinformationonthenewSoftDeletingTraitmaybefoundintheEloquentdocumentation.

ThedefaultLaravel4.2installationnowusessimpletraitsforincludingtheneededpropertiesfortheauthenticationandpasswordreminderuserinterfaces.ThisprovidesamuchcleanerdefaultUsermodelfileoutofthebox.

AnewsimplePaginatemethodwasaddedtothequeryandEloquentbuilderwhichallowsformoreefficientquerieswhenusingsimple"Next"and"Previous"linksinyourpaginationview.

Inproduction,destructivemigrationoperationswillnowaskforconfirmation.Commandsmaybeforcedtorunwithoutanypromptsusingthe--forcecommand.

Thefullchangelistforthisreleasebyrunningthephpartisanchangescommandfroma4.1installation,orbyviewingthechangefileonGithub.Thesenotesonlycoverthemajorenhancementsandchangesfortherelease.

AnentirelynewSSHcomponenthasbeenintroducedwiththisrelease.ThisfeatureallowsyoutoeasilySSHintoremoteserversandruncommands.Tolearnmore,consulttheSSHcomponentdocumentation.

ThenewphpartisantailcommandutilizesthenewSSHcomponent.Formoreinformation,consultthetailcommanddocumentation.

ThephpartisantinkercommandnowutilizestheBorisREPLifyoursystemsupportsit.ThereadlineandpcntlPHPextensionsmustbeinstalledtousethisfeature.Ifyoudonothavetheseextensions,theshellfrom4.0willbeused.

AnewhasManyThroughrelationshiphasbeenaddedtoEloquent.Tolearnhowtouseit,consulttheEloquentdocumentation.

AnewwhereHasmethodhasalsobeenintroducedtoallowretrievingmodelsbasedonrelationshipconstraints.

Automatichandlingofseparateread/writeconnectionsisnowavailablethroughoutthedatabaselayer,includingthequerybuilderandEloquent.Formoreinformation,consultthedocumentation.

SoftDeletingTraits

ConvenientAuth&RemindableTraits

"SimplePaginate"

MigrationConfirmation

Laravel4.1

FullChangeList

NewSSHComponent

BorisInTinker

EloquentImprovements

DatabaseRead/WriteConnections

Queueprioritiesarenowsupportedbypassingacomma-delimitedlisttothequeue:listencommand.

Thequeuefacilitiesnowincludeautomatichandlingoffailedjobswhenusingthenew--triesswitchonqueue:listen.Moreinformationonhandlingfailedjobscanbefoundinthequeuedocumentation.

Cache"sections"havebeensupersededby"tags".Cachetagsallowyoutoassignmultiple"tags"toacacheitem,andflushallitemsassignedtoasingletag.Moreinformationonusingcachetagsmaybefoundinthecachedocumentation.

Thepasswordreminderenginehasbeenchangedtoprovidegreaterdeveloperflexibilitywhenvalidatingpasswords,flashingstatusmessagestothesession,etc.Formoreinformationonusingtheenhancedpasswordreminderengine,consultthedocumentation.

Laravel4.1featuresatotallyre-writtenroutinglayer.TheAPIisthesame;however,registeringroutesisafull100%fastercomparedto4.0.Theentireenginehasbeengreatlysimplified,andthedependencyonSymfonyRoutinghasbeenminimizedtothecompilingofrouteexpressions.

Withthisrelease,we'realsointroducinganentirelynewsessionengine.Similartotheroutingimprovements,thenewsessionlayerisleanerandfaster.WearenolongerusingSymfony's(andthereforePHP's)sessionhandlingfacilities,andareusingacustomsolutionthatissimplerandeasiertomaintain.

IfyouareusingtherenameColumnfunctioninyourmigrations,youwillneedtoaddthedoctrine/dbaldependencytoyourcomposer.jsonfile.ThispackageisnolongerincludedinLaravelbydefault.

QueuePriority

FailedQueueJobHandling

CacheTags

FlexiblePasswordReminders

ImprovedRoutingEngine

ImprovedSessionEngine

DoctrineDBAL

UpgradingTo5.0From4.2UpgradingTo4.2From4.1UpgradingTo4.1.29From<=4.1.xUpgradingTo4.1.26From<=4.1.25UpgradingTo4.1From4.0

TherecommendedmethodofupgradingistocreateanewLaravel5.0installandthentocopyyour4.2site'suniqueapplicationfilesintothenewapplication.Thiswouldincludecontrollers,routes,Eloquentmodels,Artisancommands,assets,andothercodespecifictoyourapplication.

Tostart,installanewLaravel5applicationintoafreshdirectoryinyourlocalenvironment.We'lldiscusseachpieceofthemigrationprocessinfurtherdetailbelow.

Don'tforgettocopyanyadditionalComposerdependenciesintoyour5.0application.Thisincludesthird-partycodesuchasSDKs.

SomeLaravel-specificpackagesmaynotbecompatiblewithLaravel5oninitialrelease.Checkwithyourpackage'smaintainertodeterminetheproperversionofthepackageforLaravel5.OnceyouhaveaddedanyadditionalComposerdependenciesyourapplicationneeds,runcomposerupdate.

Bydefault,Laravel4applicationsdidnotutilizenamespacingwithinyourapplicationcode.So,forexample,allEloquentmodelsandcontrollerssimplylivedinthe"global"namespace.Foraquickermigration,youcansimplyleavetheseclassesintheglobalnamespaceinLaravel5aswell.

Copythenew.env.examplefileto.env,whichisthe5.0equivalentoftheold.env.phpfile.Setanyappropriatevaluesthere,likeyourAPP_ENVandAPP_KEY(yourencryptionkey),yourdatabasecredentials,andyourcacheandsessiondrivers.

Additionally,copyanycustomvaluesyouhadinyourold.env.phpfileandplacetheminboth.env(therealvalueforyourlocalenvironment)and.env.example(asampleinstructionalvalueforotherteammembers).

Formoreinformationonenvironmentconfiguration,viewthefulldocumentation.

Note:Youwillneedtoplacetheappropriate.envfileandvaluesonyourproductionserverbeforedeployingyourLaravel5application.

Laravel5.0nolongerusesapp/config/{environmentName}/directoriestoprovidespecificconfigurationfilesforagivenenvironment.Instead,moveanyconfigurationvaluesthatvarybyenvironmentinto.env,andthenaccesstheminyour

UpgradeGuide

UpgradingTo5.0From4.2

FreshInstall,ThenMigrate

ComposerDependencies&Packages

Namespacing

Configuration

MigratingEnvironmentVariables

ConfigurationFiles

configurationfilesusingenv('key','defaultvalue').Youwillseeexamplesofthisintheconfig/database.phpconfigurationfile.

Settheconfigfilesintheconfig/directorytorepresenteitherthevaluesthatareconsistentacrossallofyourenvironments,orsetthemtouseenv()toloadvaluesthatvarybyenvironment.

Remember,ifyouaddmorekeysto.envfile,addsamplevaluestothe.env.examplefileaswell.Thiswillhelpyourotherteammemberscreatetheirown.envfiles.

Copyandpasteyouroldroutes.phpfileintoyournewapp/Http/routes.php.

Next,moveallofyourcontrollersintotheapp/Http/Controllersdirectory.Sincewearenotgoingtomigratetofullnamespacinginthisguide,addtheapp/Http/Controllersdirectorytotheclassmapdirectiveofyourcomposer.jsonfile.Next,youcanremovethenamespacefromtheabstractapp/Http/Controllers/Controller.phpbaseclass.Verifythatyourmigratedcontrollersareextendingthisbaseclass.

Inyourapp/Providers/RouteServiceProvider.phpfile,setthenamespacepropertytonull.

Copyyourfilterbindingsfromapp/filters.phpandplacethemintotheboot()methodofapp/Providers/RouteServiceProvider.php.AdduseIlluminate\Support\Facades\Route;intheapp/Providers/RouteServiceProvider.phpinordertocontinueusingtheRouteFacade.

YoudonotneedtomoveoveranyofthedefaultLaravel4.0filterssuchasauthandcsrf;they'reallhere,butasmiddleware.Editanyroutesorcontrollersthatreferencetheolddefaultfilters(e.g.['before'=>'auth'])andchangethemtoreferencethenewmiddleware(e.g.['middleware'=>'auth'].)

FiltersarenotremovedinLaravel5.Youcanstillbindanduseyourowncustomfiltersusingbeforeandafter.

Bydefault,CSRFprotectionisenabledonallroutes.Ifyou'dliketodisablethis,oronlymanuallyenableitoncertainroutes,removethislinefromApp\Http\Kernel'smiddlewarearray:

'App\Http\Middleware\VerifyCsrfToken',

Ifyouwanttouseitelsewhere,addthislineto$routeMiddleware:

'csrf'=>'App\Http\Middleware\VerifyCsrfToken',

Nowyoucanaddthemiddlewaretoindividualroutes/controllersusing['middleware'=>'csrf']ontheroute.Formoreinformationonmiddleware,consultthefulldocumentation.

Feelfreetocreateanewapp/ModelsdirectorytohouseyourEloquentmodels.Again,addthisdirectorytotheclassmapdirectiveofyourcomposer.jsonfile.

UpdateanymodelsusingSoftDeletingTraittouseIlluminate\Database\Eloquent\SoftDeletes.

Routes

Controllers

RouteFilters

GlobalCSRF

EloquentModels

Eloquentnolongerprovidestheremembermethodforcachingqueries.YounowareresponsibleforcachingyourqueriesmanuallyusingtheCache::rememberfunction.Formoreinformationoncaching,consultthefulldocumentation.

ToupgradeyourUsermodelforLaravel5'sauthenticationsystem,followtheseinstructions:

Deletethefollowingfromyouruseblock:

useIlluminate\Auth\UserInterface;

useIlluminate\Auth\Reminders\RemindableInterface;

Addthefollowingtoyouruseblock:

useIlluminate\Auth\Authenticatable;

useIlluminate\Auth\Passwords\CanResetPassword;

useIlluminate\Contracts\Auth\AuthenticatableasAuthenticatableContract;

useIlluminate\Contracts\Auth\CanResetPasswordasCanResetPasswordContract;

RemovetheUserInterfaceandRemindableInterfaceinterfaces.

Marktheclassasimplementingthefollowinginterfaces:

implementsAuthenticatableContract,CanResetPasswordContract

Includethefollowingtraitswithintheclassdeclaration:

useAuthenticatable,CanResetPassword;

Ifyouusedthem,removeIlluminate\Auth\Reminders\RemindableTraitandIlluminate\Auth\UserTraitfromyouruseblockandyourclassdeclaration.

ThenameofthetraitandinterfaceusedbyLaravelCashierhaschanged.InsteadofusingBillableTrait,usetheLaravel\Cashier\Billabletrait.And,insteadofLaravel\Cashier\BillableInterfaceimplementtheLaravel\Cashier\Contracts\Billableinterfaceinstead.Noothermethodchangesarerequired.

Moveallofyourcommandclassesfromyouroldapp/commandsdirectorytothenewapp/Console/Commandsdirectory.Next,addtheapp/Console/Commandsdirectorytotheclassmapdirectiveofyourcomposer.jsonfile.

Then,copyyourlistofArtisancommandsfromstart/artisan.phpintothecommandarrayoftheapp/Console/Kernel.phpfile.

DeletethetwomigrationsincludedwithLaravel5.0,sinceyoushouldalreadyhavetheuserstableinyourdatabase.

Moveallofyourmigrationclassesfromtheoldapp/database/migrationsdirectorytothenewdatabase/migrations.Allofyourseedsshouldbemovedfromapp/database/seedstodatabase/seeds.

EloquentCaching

UserAuthenticationModel

CashierUserChanges

ArtisanCommands

DatabaseMigrations&Seeds

IfyouhaveanyIoCbindingsinstart/global.php,movethemalltotheregistermethodoftheapp/Providers/AppServiceProvider.phpfile.YoumayneedtoimporttheAppfacade.

Optionally,youmaybreakthesebindingsupintoseparateserviceprovidersbycategory.

Moveyourviewsfromapp/viewstothenewresources/viewsdirectory.

Forbettersecuritybydefault,Laravel5.0escapesalloutputfromboththe{{}}and{{{}}}Bladedirectives.Anew{!!!!}directivehasbeenintroducedtodisplayraw,unescapedoutput.Themostsecureoptionwhenupgradingyourapplicationistoonlyusethenew{!!!!}directivewhenyouarecertainthatitissafetodisplayrawoutput.

However,ifyoumustusetheoldBladesyntax,addthefollowinglinesatthebottomofAppServiceProvider@register:

\Blade::setRawTags('{{','}}');

\Blade::setContentTags('{{{','}}}');

\Blade::setEscapedContentTags('{{{','}}}');

Thisshouldnotbedonelightly,andmaymakeyourapplicationmorevulnerabletoXSSexploits.Also,commentswith{{--willnolongerwork.

Moveyourlanguagefilesfromapp/langtothenewresources/langdirectory.

Copyyourapplication'spublicassetsfromyour4.2application'spublicdirectorytoyournewapplication'spublicdirectory.Besuretokeepthe5.0versionofindex.php.

Moveyourtestsfromapp/teststothenewtestsdirectory.

Copyinanyotherfilesinyourproject.Forexample,.scrutinizer.yml,bower.jsonandothersimilartoolingconfigurationfiles.

YoumaymoveyourSass,Less,orCoffeeScripttoanylocationyouwish.Theresources/assetsdirectorycouldbeagooddefaultlocation.

Ifyou'reusingFormorHTMLhelpers,youwillseeanerrorstatingclass'Form'notfoundorclass'Html'notfound.Tofixthis,add"illuminate/html":"~5.0"toyourcomposer.jsonfile'srequiresection.

You'llalsoneedtoaddtheFormandHTMLfacadesandserviceprovider.Editconfig/app.php,andaddthislinetothe'providers'array:

GlobalIoCBindings

Views

BladeTagChanges

TranslationFiles

PublicDirectory

Tests

Misc.Files

Form&HTMLHelpers

'Illuminate\Html\HtmlServiceProvider',

Next,addtheselinestothe'aliases'array:

'Form'=>'Illuminate\Html\FormFacade',

'Html'=>'Illuminate\Html\HtmlFacade',

IfyourapplicationcodewasinjectingIlluminate\Cache\CacheManagertogetanon-FacadeversionofLaravel'scache,injectIlluminate\Contracts\Cache\Repositoryinstead.

Replaceanycallsto$paginator->links()with$paginator->render().

Laravel5.0nowrequires"pda/pheanstalk":"~3.0"insteadof"pda/pheanstalk":"~2.1".

TheRemotecomponenthasbeendeprecated.

TheWorkbenchcomponenthasbeendeprecated.

Laravel4.2requiresPHP5.4.0orgreater.

Addanewcipheroptioninyourapp/config/app.phpconfigurationfile.ThevalueofthisoptionshouldbeMCRYPT_RIJNDAEL_256.

'cipher'=>MCRYPT_RIJNDAEL_256

ThissettingmaybeusedtocontrolthedefaultcipherusedbytheLaravelencryptionfacilities.

Note:InLaravel4.2,thedefaultcipherisMCRYPT_RIJNDAEL_128(AES),whichisconsideredtobethemostsecurecipher.ChangingthecipherbacktoMCRYPT_RIJNDAEL_256isrequiredtodecryptcookies/valuesthatwereencryptedinLaravel<=4.1

Ifyouareusingsoftdeletingmodels,thesoftDeletespropertyhasbeenremoved.YoumustnowusetheSoftDeletingTraitlikeso:

CacheManager

Pagination

BeanstalkQueuing

Remote

Workbench

UpgradingTo4.2From4.1

PHP5.4+

EncryptionDefaults

SoftDeletingModelsNowUseTraits

useIlluminate\Database\Eloquent\SoftDeletingTrait;

classUserextendsEloquent{

useSoftDeletingTrait;

}

Youmustalsomanuallyaddthedeleted_atcolumntoyourdatesproperty:

classUserextendsEloquent{

useSoftDeletingTrait;

protected$dates=['deleted_at'];

}

TheAPIforallsoftdeleteoperationsremainsthesame.

Note:TheSoftDeletingTraitcannotbeappliedonabasemodel.Itmustbeusedonanactualmodelclass.

IfyouaredirectlyreferencingtheIlluminate\View\EnvironmentclassorIlluminate\Pagination\Environmentclass,updateyourcodetoreferenceIlluminate\View\FactoryandIlluminate\Pagination\Factoryinstead.Thesetwoclasseshavebeenrenamedtobetterreflecttheirfunction.

IfyouareextendingtheIlluminate\Pagination\Presenterclass,theabstractmethodgetPageLinkWrappersignaturehaschangedtoaddtherelargument:

abstractpublicfunctiongetPageLinkWrapper($url,$page,$rel=null);

IfyouareusingtheIron.ioqueuedriver,youwillneedtoaddanewencryptoptiontoyourqueueconfigurationfile:

'encrypt'=>true

Laravel4.1.29improvesthecolumnquotingforalldatabasedrivers.Thisprotectsyourapplicationfromsomemassassignmentvulnerabilitieswhennotusingthefillablepropertyonmodels.Ifyouareusingthefillablepropertyonyourmodelstoprotectagainstmassassignment,yourapplicationisnotvulnerable.However,ifyouareusingguardedandarepassingausercontrolledarrayintoan"update"or"save"typefunction,youshouldupgradeto4.1.29immediatelyasyourapplicationmaybeatriskofmassassignment.

ToupgradetoLaravel4.1.29,simplycomposerupdate.Nobreakingchangesareintroducedinthisrelease.

Laravel4.1.26introducessecurityimprovementsfor"rememberme"cookies.Beforethisupdate,ifaremembercookiewashijackedbyanothermalicioususer,thecookiewouldremainvalidforalongperiodoftime,evenafterthetrueowneroftheaccountresettheirpassword,loggedout,etc.

View/PaginationEnvironmentRenamed

AdditionalParameterOnPaginationPresenter

Iron.IoQueueEncryption

UpgradingTo4.1.29From<=4.1.x

UpgradingTo4.1.26From<=4.1.25

Thischangerequirestheadditionofanewremember_tokencolumntoyourusers(orequivalent)databasetable.Afterthischange,afreshtokenwillbeassignedtotheusereachtimetheylogintoyourapplication.Thetokenwillalsoberefreshedwhentheuserlogsoutoftheapplication.Theimplicationsofthischangeare:ifa"rememberme"cookieishijacked,simplyloggingoutoftheapplicationwillinvalidatethecookie.

First,addanew,nullableremember_tokenofVARCHAR(100),TEXT,orequivalenttoyouruserstable.

Next,ifyouareusingtheEloquentauthenticationdriver,updateyourUserclasswiththefollowingthreemethods:

publicfunctiongetRememberToken()

{

return$this->remember_token;

}

publicfunctionsetRememberToken($value)

{

$this->remember_token=$value;

}

publicfunctiongetRememberTokenName()

{

return'remember_token';

}

Note:Allexisting"rememberme"sessionswillbeinvalidatedbythischange,soalluserswillbeforcedtore-authenticatewithyourapplication.

TwonewmethodswereaddedtotheIlluminate\Auth\UserProviderInterfaceinterface.Sampleimplementationsmaybefoundinthedefaultdrivers:

publicfunctionretrieveByToken($identifier,$token);

publicfunctionupdateRememberToken(UserInterface$user,$token);

TheIlluminate\Auth\UserInterfacealsoreceivedthethreenewmethodsdescribedinthe"UpgradePath".

ToupgradeyourapplicationtoLaravel4.1,changeyourlaravel/frameworkversionto4.1.*inyourcomposer.jsonfile.

Replaceyourpublic/index.phpfilewiththisfreshcopyfromtherepository.

Replaceyourartisanfilewiththisfreshcopyfromtherepository.

Updateyouraliasesandprovidersarraysinyourapp/config/app.phpconfigurationfile.Theupdatedvaluesforthesearrayscanbefoundinthisfile.Besuretoaddyourcustomandpackageserviceproviders/aliasesbacktothearrays.

Addthenewapp/config/remote.phpfilefromtherepository.

UpgradePath

PackageMaintainers

UpgradingTo4.1From4.0

UpgradingYourComposerDependency

ReplacingFiles

AddingConfigurationFiles&Options

Addthenewexpire_on_closeconfigurationoptiontoyourapp/config/session.phpfile.Thedefaultvalueshouldbefalse.

Addthenewfailedconfigurationsectiontoyourapp/config/queue.phpfile.Herearethedefaultvaluesforthesection:

'failed'=>array(

'database'=>'mysql','table'=>'failed_jobs',

),

(Optional)Updatethepaginationconfigurationoptioninyourapp/config/view.phpfiletopagination::slider-3.

Ifapp/controllers/BaseController.phphasausestatementatthetop,changeuseIlluminate\Routing\Controllers\Controller;touseIlluminate\Routing\Controller;.

Passwordremindershavebeenoverhauledforgreaterflexibility.Youmayexaminethenewstubcontrollerbyrunningthephpartisanauth:reminders-controllerArtisancommand.Youmayalsobrowsetheupdateddocumentationandupdateyourapplicationaccordingly.

Updateyourapp/lang/en/reminders.phplanguagefiletomatchthisupdatedfile.

Forsecurityreasons,URLdomainsmaynolongerbeusedtodetectyourapplicationenvironment.Thesevaluesareeasilyspoofableandallowattackerstomodifytheenvironmentforarequest.Youshouldconvertyourenvironmentdetectiontousemachinehostnames(hostnamecommandonMac,Linux,andWindows).

Laravelnowgeneratesasinglelogfile:app/storage/logs/laravel.log.However,youmaystillconfigurethisbehaviorinyourapp/start/global.phpfile.

Inyourbootstrap/start.phpfile,removethecallto$app->redirectIfTrailingSlash().Thismethodisnolongerneededasthisfunctionalityisnowhandledbythe.htaccessfileincludedwiththeframework.

Next,replaceyourApache.htaccessfilewiththisnewonethathandlestrailingslashes.

ThecurrentrouteisnowaccessedviaRoute::current()insteadofRoute::getCurrentRoute().

Onceyouhavecompletedthechangesabove,youcanrunthecomposerupdatefunctiontoupdateyourcoreapplicationfiles!Ifyoureceiveclassloaderrors,tryrunningtheupdatecommandwiththe--no-scriptsoptionenabledlikeso:composerupdate--no-scripts.

Thewildcardeventlistenersnolongerappendtheeventtoyourhandlerfunctionsparameters.IfyourequirefindingtheeventthatwasfiredyoushoulduseEvent::firing().

ControllerUpdates

PasswordRemindersUpdates

EnvironmentDetectionUpdates

SimplerLogFiles

RemovingRedirectTrailingSlash

CurrentRouteAccess

ComposerUpdate

WildcardEventListeners

BugReportsCoreDevelopmentDiscussionWhichBranch?SecurityVulnerabilitiesCodingStyle

Toencourageactivecollaboration,Laravelstronglyencouragespullrequests,notjustbugreports."Bugreports"mayalsobesentintheformofapullrequestcontainingafailingunittest.

However,ifyoufileabugreport,yourissueshouldcontainatitleandacleardescriptionoftheissue.Youshouldalsoincludeasmuchrelevantinformationaspossibleandacodesamplethatdemonstratestheissue.Thegoalofabugreportistomakeiteasyforyourself-andothers-toreplicatethebuganddevelopafix.

Remember,bugreportsarecreatedinthehopethatotherswiththesameproblemwillbeabletocollaboratewithyouonsolvingit.Donotexpectthatthebugreportwillautomaticallyseeanyactivityorthatotherswilljumptofixit.Creatingabugreportservestohelpyourselfandothersstartonthepathoffixingtheproblem.

TheLaravelsourcecodeismanagedonGithub,andtherearerepositoriesforeachoftheLaravelprojects:

LaravelFrameworkLaravelApplicationLaravelDocumentationLaravelCashierLaravelEnvoyLaravelHomesteadLaravelHomesteadBuildScriptsLaravelWebsiteLaravelArt

Discussionregardingbugs,newfeatures,andimplementationofexistingfeaturestakesplaceinthe#laravel-devIRCchannel(Freenode).TaylorOtwell,themaintainerofLaravel,istypicallypresentinthechannelonweekdaysfrom8am-5pm(UTC-06:00orAmerica/Chicago),andsporadicallypresentinthechannelatothertimes.

The#laravel-devIRCchannelisopentoall.Allarewelcometojointhechanneleithertoparticipateorsimplyobservethediscussions!

Allbugfixesshouldbesenttothelateststablebranch.Bugfixesshouldneverbesenttothemasterbranchunlesstheyfixfeaturesthatexistonlyintheupcomingrelease.

MinorfeaturesthatarefullybackwardscompatiblewiththecurrentLaravelreleasemaybesenttothelateststablebranch.

Majornewfeaturesshouldalwaysbesenttothemasterbranch,whichcontainstheupcomingLaravelrelease.

Ifyouareunsureifyourfeaturequalifiesasamajororminor,pleaseaskTaylorOtwellinthe#laravel-devIRCchannel

ContributionGuide

BugReports

CoreDevelopmentDiscussion

WhichBranch?

(Freenode).

IfyoudiscoverasecurityvulnerabilitywithinLaravel,pleasesendane-mailtoTaylorOtwellattaylorotwell@gmail.com.Allsecurityvulnerabilitieswillbepromptlyaddressed.

LaravelfollowsthePSR-0andPSR-1codingstandards.Inadditiontothesestandards,thefollowingcodingstandardsshouldbefollowed:

Theclassnamespacedeclarationmustbeonthesamelineas<?php.Aclass'opening{mustbeonthesamelineastheclassname.FunctionsandcontrolstructuresmustuseAllmanstylebraces.Indentwithtabs,alignwithspaces.

SecurityVulnerabilities

CodingStyle

InstallationInstallComposerInstallLaravelServerRequirements

ConfigurationIntroductionAfterInstallationAccessingConfigurationValuesEnvironmentConfigurationConfigurationCachingMaintenanceModePrettyURLs

HomesteadIntroductionIncludedSoftwareInstallation&SetupDailyUsagePorts

Setup

InstallComposerInstallLaravelServerRequirements

LaravelutilizesComposertomanageitsdependencies.So,beforeusingLaravel,youwillneedtomakesureyouhaveComposerinstalledonyourmachine.

First,downloadtheLaravelinstallerusingComposer.

composerglobalrequire"laravel/installer=~1.1"

Makesuretoplacethe~/.composer/vendor/bindirectoryinyourPATHsothelaravelexecutablecanbelocatedbyyoursystem.

Onceinstalled,thesimplelaravelnewcommandwillcreateafreshLaravelinstallationinthedirectoryyouspecify.Forinstance,laravelnewblogwouldcreateadirectorynamedblogcontainingafreshLaravelinstallationwithalldependenciesinstalled.ThismethodofinstallationismuchfasterthaninstallingviaComposer:

laravelnewblog

YoumayalsoinstallLaravelbyissuingtheComposercreate-projectcommandinyourterminal:

composercreate-projectlaravel/laravel--prefer-dist

TheLaravelframeworkhasafewsystemrequirements:

PHP>=5.4McryptPHPExtensionOpenSSLPHPExtensionMbstringPHPExtension

AsofPHP5.5,someOSdistributionsmayrequireyoutomanuallyinstallthePHPJSONextension.WhenusingUbuntu,thiscanbedoneviaapt-getinstallphp5-json.

Installation

InstallComposer

InstallLaravel

ViaLaravelInstaller

ViaComposerCreate-Project

ServerRequirements

Configuration

ThefirstthingyoushoulddoafterinstallingLaravelissetyourapplicationkeytoarandomstring.IfyouinstalledLaravelviaComposer,thiskeyhasprobablyalreadybeensetforyoubythekey:generatecommand.

Typically,thisstringshouldbe32characterslong.Thekeycanbesetinthe.envenvironmentfile.Iftheapplicationkeyisnotset,yourusersessionsandotherencrypteddatawillnotbesecure!

Laravelneedsalmostnootherconfigurationoutofthebox.Youarefreetogetstarteddeveloping!However,youmaywishtoreviewtheconfig/app.phpfileanditsdocumentation.Itcontainsseveraloptionssuchastimezoneandlocalethatyoumaywishtochangeaccordingtoyourapplication.

OnceLaravelisinstalled,youshouldalsoconfigureyourlocalenvironment.

Note:Youshouldneverhavetheapp.debugconfigurationoptionsettotrueforaproductionapplication.

Laravelmayrequiresomepermissionstobeconfigured:folderswithinstoragerequirewriteaccessbythewebserver.

Theframeworkshipswithapublic/.htaccessfilethatisusedtoallowURLswithoutindex.php.IfyouuseApachetoserveyourLaravelapplication,besuretoenablethemod_rewritemodule.

Ifthe.htaccessfilethatshipswithLaraveldoesnotworkwithyourApacheinstallation,trythisone:

Options+FollowSymLinks

RewriteEngineOn

RewriteCond%{REQUEST_FILENAME}!-d

RewriteCond%{REQUEST_FILENAME}!-f

RewriteRule^index.php[L]

OnNginx,thefollowingdirectiveinyoursiteconfigurationwillallow"pretty"URLs:

location/{

try_files$uri$uri//index.php?$query_string;

}

Ofcourse,whenusingHomestead,prettyURLswillbeconfiguredautomatically.

Permissions

PrettyURLs

Apache

Nginx

IntroductionAfterInstallationAccessingConfigurationValuesEnvironmentConfigurationConfigurationCachingMaintenanceModePrettyURLs

AlloftheconfigurationfilesfortheLaravelframeworkarestoredintheconfigdirectory.Eachoptionisdocumented,sofeelfreetolookthroughthefilesandgetfamiliarwiththeoptionsavailabletoyou.

AfterinstallingLaravel,youmaywishto"name"yourapplication.Bydefault,theappdirectoryisnamespacedunderApp,andautoloadedbyComposerusingthePSR-4autoloadingstandard.However,youmaychangethenamespacetomatchthenameofyourapplication,whichyoucaneasilydoviatheapp:nameArtisancommand.

Forexample,ifyourapplicationisnamed"Horsefly",youcouldrunthefollowingcommandfromtherootofyourinstallation:

phpartisanapp:nameHorsefly

Renamingyourapplicationisentirelyoptional,andyouarefreetokeeptheAppnamespaceifyouwish.

Laravelneedsverylittleconfigurationoutofthebox.Youarefreetogetstarteddeveloping!However,youmaywishtoreviewtheconfig/app.phpfileanditsdocumentation.Itcontainsseveraloptionssuchastimezoneandlocalethatyoumaywishtochangeaccordingtoyourlocation.

OnceLaravelisinstalled,youshouldalsoconfigureyourlocalenvironment.

Note:Youshouldneverhavetheapp.debugconfigurationoptionsettotrueforaproductionapplication.

Laravelmayrequireonesetofpermissionstobeconfigured:folderswithinstoragerequirewriteaccessbythewebserver.

YoumayeasilyaccessyourconfigurationvaluesusingtheConfigfacade:

$value=Config::get('app.timezone');

Config::set('app.timezone','America/Chicago');

Configuration

Introduction

AfterInstallation

NamingYourApplication

OtherConfiguration

Permissions

AccessingConfigurationValues

Youmayalsousetheconfighelperfunction:

$value=config('app.timezone');

Itisoftenhelpfultohavedifferentconfigurationvaluesbasedontheenvironmenttheapplicationisrunningin.Forexample,youmaywishtouseadifferentcachedriverlocallythanyoudoonyourproductionserver.It'seasyusingenvironmentbasedconfiguration.

Tomakethisacinch,LaravelutilizestheDotEnvPHPlibrarybyVanceLucas.InafreshLaravelinstallation,therootdirectoryofyourapplicationwillcontaina.env.examplefile.IfyouinstallLaravelviaComposer,thisfilewillautomaticallyberenamedto.env.Otherwise,youshouldrenamethefilemanually.

Allofthevariableslistedinthisfilewillbeloadedintothe$_ENVPHPsuper-globalwhenyourapplicationreceivesarequest.Youmayusetheenvhelpertoretrievevaluesfromthesevariables.Infact,ifyoureviewtheLaravelconfigurationfiles,youwillnoticeseveraloftheoptionsalreadyusingthishelper!

Feelfreetomodifyyourenvironmentvariablesasneededforyourownlocalserver,aswellasyourproductionenvironment.However,your.envfileshouldnotbecommittedtoyourapplication'ssourcecontrol,sinceeachdeveloper/serverusingyourapplicationcouldrequireadifferentenvironmentconfiguration.

Ifyouaredevelopingwithateam,youmaywishtocontinueincludinga.env.examplefilewithyourapplication.Byputtingplace-holdervaluesintheexampleconfigurationfile,otherdevelopersonyourteamcanclearlyseewhichenvironmentvariablesareneededtorunyourapplication.

YoumayaccessthecurrentapplicationenvironmentviatheenvironmentmethodontheApplicationinstance:

$environment=$app->environment();

Youmayalsopassargumentstotheenvironmentmethodtocheckiftheenvironmentmatchesagivenvalue:

if($app->environment('local'))

{

//Theenvironmentislocal

}

if($app->environment('local','staging'))

{

//TheenvironmentiseitherlocalORstaging...

}

Toobtainaninstanceoftheapplication,resolvetheIlluminate\Contracts\Foundation\Applicationcontractviatheservicecontainer.Ofcourse,ifyouarewithinaserviceprovider,theapplicationinstanceisavailableviathe$this->appinstancevariable.

AnapplicationinstancemayalsobeaccessedviatheapphelperoftheAppfacade:

$environment=app()->environment();

$environment=App::environment();

EnvironmentConfiguration

AccessingTheCurrentApplicationEnvironment

Togiveyourapplicationalittlespeedboost,youmaycacheallofyourconfigurationfilesintoasinglefileusingtheconfig:cacheArtisancommand.Thiswillcombinealloftheconfigurationoptionsforyourapplicationintoasinglefilewhichcanbeloadedquicklybytheframework.

Youshouldtypicallyruntheconfig:cachecommandaspartofyourdeploymentroutine.

Whenyourapplicationisinmaintenancemode,acustomviewwillbedisplayedforallrequestsintoyourapplication.Thismakesiteasyto"disable"yourapplicationwhileitisupdatingorwhenyouareperformingmaintenance.Amaintenancemodecheckisincludedinthedefaultmiddlewarestackforyourapplication.Iftheapplicationisinmaintenancemode,anHttpExceptionwillbethrownwithastatuscodeof503.

Toenablemaintenancemode,simplyexecutethedownArtisancommand:

phpartisandown

Todisablemaintenancemode,usetheupcommand:

phpartisanup

Thedefaulttemplateformaintenancemoderesponsesislocatedinresources/views/errors/503.blade.php.

Whileyourapplicationisinmaintenancemode,noqueuedjobswillbehandled.Thejobswillcontinuetobehandledasnormaloncetheapplicationisoutofmaintenancemode.

Theframeworkshipswithapublic/.htaccessfilethatisusedtoallowURLswithoutindex.php.IfyouuseApachetoserveyourLaravelapplication,besuretoenablethemod_rewritemodule.

Ifthe.htaccessfilethatshipswithLaraveldoesnotworkwithyourApacheinstallation,trythisone:

Options+FollowSymLinks

RewriteEngineOn

RewriteCond%{REQUEST_FILENAME}!-d

RewriteCond%{REQUEST_FILENAME}!-f

RewriteRule^index.php[L]

OnNginx,thefollowingdirectiveinyoursiteconfigurationwillallow"pretty"URLs:

ConfigurationCaching

MaintenanceMode

MaintenanceModeResponseTemplate

MaintenanceMode&Queues

PrettyURLs

Apache

Nginx

location/{

try_files$uri$uri//index.php?$query_string;

}

Ofcourse,whenusingHomestead,prettyURLswillbeconfiguredautomatically.

IntroductionIncludedSoftwareInstallation&SetupDailyUsagePorts

LaravelstrivestomaketheentirePHPdevelopmentexperiencedelightful,includingyourlocaldevelopmentenvironment.Vagrantprovidesasimple,elegantwaytomanageandprovisionVirtualMachines.

LaravelHomesteadisanofficial,pre-packagedVagrant"box"thatprovidesyouawonderfuldevelopmentenvironmentwithoutrequiringyoutoinstallPHP,HHVM,awebserver,andanyotherserversoftwareonyourlocalmachine.Nomoreworryingaboutmessingupyouroperatingsystem!Vagrantboxesarecompletelydisposable.Ifsomethinggoeswrong,youcandestroyandre-createtheboxinminutes!

HomesteadrunsonanyWindows,Mac,orLinuxsystem,andincludestheNginxwebserver,PHP5.6,MySQL,Postgres,Redis,Memcached,andalloftheothergoodiesyouneedtodevelopamazingLaravelapplications.

Note:IfyouareusingWindows,youmayneedtoenablehardwarevirtualization(VT-x).ItcanusuallybeenabledviayourBIOS.

HomesteadiscurrentlybuiltandtestedusingVagrant1.6.

Ubuntu14.04PHP5.6HHVMNginxMySQLPostgresNode(WithBower,Grunt,andGulp)RedisMemcachedBeanstalkdLaravelEnvoyFabric+HipChatExtension

BeforelaunchingyourHomesteadenvironment,youmustinstallVirtualBoxandVagrant.Bothofthesesoftwarepackagesprovideeasy-to-usevisualinstallersforallpopularoperatingsystems.

OnceVirtualBoxandVagranthavebeeninstalled,youshouldaddthelaravel/homesteadboxtoyourVagrantinstallationusingthefollowingcommandinyourterminal.Itwilltakeafewminutestodownloadthebox,dependingonyourInternet

LaravelHomestead

Introduction

IncludedSoftware

Installation&Setup

InstallingVirtualBox&Vagrant

AddingTheVagrantBox

connectionspeed:

vagrantboxaddlaravel/homestead

Alternatively,ifyoudonotwanttoinstallPHPonyourlocalmachine,youmayinstallHomesteadmanuallybysimplycloningtherepository.ConsidercloningtherepositoryintoaHomesteadfolderwithinyour"home"directory,astheHomesteadboxwillserveasthehosttoallofyourLaravel(andPHP)projects:

gitclonehttps://github.com/laravel/homestead.gitHomestead

OnceyouhaveinstalledtheHomesteadCLItool,runthebashinit.shcommandtocreatetheHomestead.yamlconfigurationfile:

bashinit.sh

TheHomestead.yamlfilewillbeplacedinyour~/.homesteaddirectory.

OncetheboxhasbeenaddedtoyourVagrantinstallation,youarereadytoinstalltheHomesteadCLItoolusingtheComposerglobalcommand:

composerglobalrequire"laravel/homestead=~2.0"

Makesuretoplacethe~/.composer/vendor/bindirectoryinyourPATHsothehomesteadexecutableisfoundwhenyourunthehomesteadcommandinyourterminal.

OnceyouhaveinstalledtheHomesteadCLItool,runtheinitcommandtocreatetheHomestead.yamlconfigurationfile:

homesteadinit

TheHomestead.yamlfilewillbeplacedinthe~/.homesteaddirectory.Ifyou'reusingaMacorLinuxsystem,youmayeditHomestead.yamlfilebyrunningthehomesteadeditcommandinyourterminal:

homesteadedit

Next,youshouldedittheHomestead.yamlfile.Inthisfile,youcanconfigurethepathtoyourpublicSSHkey,aswellasthefoldersyouwishtobesharedbetweenyourmainmachineandtheHomesteadvirtualmachine.

Don'thaveanSSHkey?OnMacandLinux,youcangenerallycreateanSSHkeypairusingthefollowingcommand:

ssh-keygen-trsa-C"you@homestead"

InstallingHomestead

ManuallyViaGit(NoLocalPHP)

WithComposer+PHPTool

SetYourSSHKey

OnWindows,youmayinstallGitandusetheGitBashshellincludedwithGittoissuethecommandabove.Alternatively,youmayusePuTTYandPuTTYgen.

OnceyouhavecreatedaSSHkey,specifythekey'spathintheauthorizepropertyofyourHomestead.yamlfile.

ThefolderspropertyoftheHomestead.yamlfilelistsallofthefoldersyouwishtosharewithyourHomesteadenvironment.Asfileswithinthesefoldersarechanged,theywillbekeptinsyncbetweenyourlocalmachineandtheHomesteadenvironment.Youmayconfigureasmanysharedfoldersasnecessary!

NotfamiliarwithNginx?Noproblem.Thesitespropertyallowsyoutoeasilymapa"domain"toafolderonyourHomesteadenvironment.AsamplesiteconfigurationisincludedintheHomestead.yamlfile.Again,youmayaddasmanysitestoyourHomesteadenvironmentasnecessary.Homesteadcanserveasaconvenient,virtualizedenvironmentforeveryLaravelprojectyouareworkingon!

YoucanmakeanyHomesteadsiteuseHHVMbysettingthehhvmoptiontotrue:

sites:

-map:homestead.app

to:/home/vagrant/Code/Laravel/public

hhvm:true

ToaddBashaliasestoyourHomesteadbox,simplyaddtothealiasesfileintherootofthe~/.homesteaddirectory.

OnceyouhaveeditedtheHomestead.yamltoyourliking,runthevagrantupcommandfromyourHomesteaddirectory.

Vagrantwillbootthevirtualmachine,andconfigureyoursharedfoldersandNginxsitesautomatically!Todestroythemachine,youmayusethevagrantdestroy--forcecommand.

Don'tforgettoaddthe"domains"foryourNginxsitestothehostsfileonyourmachine!ThehostsfilewillredirectyourrequestsforthelocaldomainsintoyourHomesteadenvironment.OnMacandLinux,thisfileislocatedat/etc/hosts.OnWindows,itislocatedatC:\Windows\System32\drivers\etc\hosts.Thelinesyouaddtothisfilewilllooklikethefollowing:

192.168.10.10homestead.app

MakesuretheIPaddresslistedistheoneyousetinyourHomestead.yamlfile.Onceyouhaveaddedthedomaintoyourhostsfile,youcanaccessthesiteviayourwebbrowser!

http://homestead.app

Tolearnhowtoconnecttoyourdatabases,readon!

ConfigureYourSharedFolders

ConfigureYourNginxSites

BashAliases

LaunchTheVagrantBox

DailyUsage

ConnectingViaSSH

ToconnecttoyourHomesteadenvironmentviaSSH,issuethevagrantsshcommandfromyourHomesteaddirectory.

SinceyouwillprobablyneedtoSSHintoyourHomesteadmachinefrequently,considercreatingan"alias"onyourhostmachine:

aliasvm="sshvagrant@127.0.0.1-p2222"

Onceyoucreatethisalias,youcansimplyusethe"vm"commandtoSSHintoyourHomesteadmachinefromanywhereonyoursystem.

AhomesteaddatabaseisconfiguredforbothMySQLandPostgresoutofthebox.Forevenmoreconvenience,Laravel'slocaldatabaseconfigurationissettousethisdatabasebydefault.

ToconnecttoyourMySQLorPostgresdatabasefromyourmainmachineviaNavicatorSequelPro,youshouldconnectto127.0.0.1andport33060(MySQL)or54320(Postgres).Theusernameandpasswordforbothdatabasesishomestead/secret.

Note:Youshouldonlyusethesenon-standardportswhenconnectingtothedatabasesfromyourmainmachine.Youwillusethedefault3306and5432portsinyourLaraveldatabaseconfigurationfilesinceLaravelisrunningwithintheVirtualMachine.

OnceyourHomesteadenvironmentisprovisionedandrunning,youmaywanttoaddadditionalNginxsitesforyourLaravelapplications.YoucanrunasmanyLaravelinstallationsasyouwishonasingleHomesteadenvironment.Therearetwowaystodothis:First,youmaysimplyaddthesitestoyourHomestead.yamlfileandthenrunvagrantprovision.

Alternatively,youmayusetheservescriptthatisavailableonyourHomesteadenvironment.Tousetheservescript,SSHintoyourHomesteadenvironmentandrunthefollowingcommand:

servedomain.app/home/vagrant/Code/path/to/public/directory

Note:Afterrunningtheservecommand,donotforgettoaddthenewsitetothehostsfileonyourmainmachine!

ThefollowingportsareforwardedtoyourHomesteadenvironment:

SSH:2222→ForwardsTo22HTTP:8000→ForwardsTo80MySQL:33060→ForwardsTo3306Postgres:54320→ForwardsTo5432

ConnectingToYourDatabases

AddingAdditionalSites

Ports

RoutingBasicRoutingCSRFProtectionMethodSpoofingRouteParametersNamedRoutesRouteGroupsRouteModelBindingThrowing404Errors

MiddlewareIntroductionDefiningMiddlewareRegisteringMiddlewareTerminableMiddleware

ControllersIntroductionBasicControllersControllerMiddlewareImplicitControllersRESTfulResourceControllersDependencyInjection&ControllersRouteCaching

RequestsObtainingARequestInstanceRetrievingInputOldInputCookiesFilesOtherRequestInformation

ResponsesBasicResponsesRedirectsOtherResponsesResponseMacros

ViewsBasicUsageViewComposers

TheBasics

BasicRoutingCSRFProtectionMethodSpoofingRouteParametersNamedRoutesRouteGroupsRouteModelBindingThrowing404Errors

Youwilldefinemostoftheroutesforyourapplicationintheapp/Http/routes.phpfile,whichisloadedbytheApp\Providers\RouteServiceProviderclass.ThemostbasicLaravelroutessimplyacceptaURIandaClosure:

Route::get('/',function()

{

return'HelloWorld';

});

Route::post('foo/bar',function()

{

return'HelloWorld';

});

Route::put('foo/bar',function()

{

//

});

Route::delete('foo/bar',function()

{

//

});

Route::match(['get','post'],'/',function()

{

return'HelloWorld';

});

Route::any('foo',function()

{

return'HelloWorld';

});

Often,youwillneedtogenerateURLstoyourroutes,youmaydosousingtheurlhelper:

HTTPRouting

BasicRouting

BasicGETRoute

OtherBasicRoutesRoute

RegisteringARouteForMultipleVerbs

RegisteringARouteThatRespondsToAnyHTTPVerb

$url=url('foo');

Laravelmakesiteasytoprotectyourapplicationfromcross-siterequestforgeries.Cross-siterequestforgeriesareatypeofmaliciousexploitwherebyunauthorizedcommandsareperformedonbehalfoftheauthenticateduser.

LaravelautomaticallygeneratesaCSRF"token"foreachactiveusersessionmanagedbytheapplication.Thistokenisusedtoverifythattheauthenticateduseristheoneactuallymakingtherequeststotheapplication.

<inputtype="hidden"name="_token"value="<?phpechocsrf_token();?>">

Ofcourse,usingtheBladetemplatingengine:

<inputtype="hidden"name="_token"value="{{csrf_token()}}">

YoudonotneedtomanuallyverifytheCSRFtokenonPOST,PUT,orDELETErequests.TheVerifyCsrfTokenHTTPmiddlewarewillverifytokenintherequestinputmatchesthetokenstoredinthesession.

InadditiontolookingfortheCSRFtokenasa"POST"parameter,themiddlewarewillalsocheckfortheX-XSRF-TOKENrequestheader,whichiscommonlyusedbyJavaScriptframeworks.

HTMLformsdonotsupportPUTorDELETEactions.So,whendefiningPUTorDELETEroutesthatarecalledfromanHTMLform,youwillneedtoaddahidden_methodfieldtotheform.

Thevaluesentwiththe_methodfieldwillbeusedastheHTTPrequestmethod.Forexample:

<formaction="/foo/bar"method="POST">

<inputtype="hidden"name="_method"value="PUT">

<inputtype="hidden"name="_token"value="<?phpechocsrf_token();?>">

</form>

Ofcourse,youcancapturesegmentsoftherequestURIwithinyourroute:

Route::get('user/{id}',function($id)

{

return'User'.$id;

});

CSRFProtection

InsertTheCSRFTokenIntoAForm

MethodSpoofing

RouteParameters

BasicRouteParameter

OptionalRouteParameters

Route::get('user/{name?}',function($name=null)

{

return$name;

});

Route::get('user/{name?}',function($name='John')

{

return$name;

});

Route::get('user/{name}',function($name)

{

//

})

->where('name','[A-Za-z]+');

Route::get('user/{id}',function($id)

{

//

})

->where('id','[0-9]+');

Route::get('user/{id}/{name}',function($id,$name)

{

//

})

->where(['id'=>'[0-9]+','name'=>'[a-z]+'])

Ifyouwouldlikearouteparametertoalwaysbeconstrainedbyagivenregularexpression,youmayusethepatternmethod.YoushoulddefinethesepatternsinthebeforemethodofyourRouteServiceProvider:

$router->pattern('id','[0-9]+');

Oncethepatternhasbeendefined,itisappliedtoallroutesusingthatparameter:

Route::get('user/{id}',function($id)

{

//Onlycalledif{id}isnumeric.

});

Ifyouneedtoaccessarouteparametervalueoutsideofaroute,usetheinputmethod:

if($route->input('id')==1)

{

//

}

OptionalRouteParametersWithDefaultValue

RegularExpressionParameterConstraints

PassingAnArrayOfConstraints

DefiningGlobalPatterns

AccessingARouteParameterValue

YoumayalsoaccessthecurrentrouteparametersviatheIlluminate\Http\Requestinstance.TherequestinstanceforthecurrentrequestmaybeaccessedviatheRequestfacade,orbytype-hintingtheIlluminate\Http\Requestwheredependenciesareinjected:

useIlluminate\Http\Request;

Route::get('user/{id}',function(Request$request,$id)

{

if($request->route('id'))

{

//

}

});

NamedroutesallowyoutoconvenientlygenerateURLsorredirectsforaspecificroute.Youmayspecifyanameforaroutewiththeasarraykey:

Route::get('user/profile',['as'=>'profile',function()

{

//

}]);

Youmayalsospecifyroutenamesforcontrolleractions:

Route::get('user/profile',[

'as'=>'profile','uses'=>'UserController@showProfile'

]);

Now,youmayusetheroute'snamewhengeneratingURLsorredirects:

$url=route('profile');

$redirect=redirect()->route('profile');

ThecurrentRouteNamemethodreturnsthenameoftheroutehandlingthecurrentrequest:

$name=Route::currentRouteName();

Sometimesyoumayneedtoapplyfilterstoagroupofroutes.Insteadofspecifyingthefilteroneachroute,youmayusearoutegroup:

Route::group(['middleware'=>'auth'],function()

{

Route::get('/',function()

{

//HasAuthFilter

});

Route::get('user/profile',function()

{

//HasAuthFilter

NamedRoutes

RouteGroups

});

});

Youmayusethenamespaceparameterwithinyourgrouparraytospecifythenamespaceforallcontrollerswithinthegroup:

Route::group(['namespace'=>'Admin'],function()

{

//

});

Note:Bydefault,theRouteServiceProviderincludesyourroutes.phpfilewithinanamespacegroup,allowingyoutoregistercontrollerrouteswithoutspecifyingthefullnamespace.

Laravelroutesalsohandlewildcardsub-domains,andwillpassyourwildcardparametersfromthedomain:

Route::group(['domain'=>'{account}.myapp.com'],function()

{

Route::get('user/{id}',function($account,$id)

{

//

});

});

Agroupofroutesmaybeprefixedbyusingtheprefixoptionintheattributesarrayofagroup:

Route::group(['prefix'=>'admin'],function()

{

Route::get('user',function()

{

//

});

});

Laravelmodelbindingprovidesaconvenientwaytoinjectclassinstancesintoyourroutes.Forexample,insteadofinjectingauser'sID,youcaninjecttheentireUserclassinstancethatmatchesthegivenID.

First,usetherouter'smodelmethodtospecifytheclassforagivenparameter.YoushoulddefineyourmodelbindingsintheRouteServiceProvider::bootmethod:

publicfunctionboot(Router$router)

{

parent::boot($router);

Sub-DomainRouting

RegisteringSub-DomainRoutes

RoutePrefixing

RouteModelBinding

BindingAParameterToAModel

$router->model('user','App\User');

}

Next,definearoutethatcontainsa{user}parameter:

Route::get('profile/{user}',function(App\User$user)

{

//

});

Sincewehaveboundthe{user}parametertotheApp\Usermodel,aUserinstancewillbeinjectedintotheroute.So,forexample,arequesttoprofile/1willinjecttheUserinstancewhichhasanIDof1.

Note:Ifamatchingmodelinstanceisnotfoundinthedatabase,a404errorwillbethrown.

Ifyouwishtospecifyyourown"notfound"behavior,passaClosureasthethirdargumenttothemodelmethod:

Route::model('user','User',function()

{

thrownewNotFoundHttpException;

});

Ifyouwishtouseyourownresolutionlogic,youshouldusetheRouter::bindmethod.TheClosureyoupasstothebindmethodwillreceivethevalueoftheURIsegment,andshouldreturnaninstanceoftheclassyouwanttobeinjectedintotheroute:

Route::bind('user',function($value)

{

returnUser::where('name',$value)->first();

});

Therearetwowaystomanuallytriggera404errorfromaroute.First,youmayusetheaborthelper:

abort(404);

TheaborthelpersimplythrowsaSymfony\Component\HttpFoundation\Exception\HttpExceptionwiththespecifiedstatuscode.

Secondly,youmaymanuallythrowaninstanceofSymfony\Component\HttpKernel\Exception\NotFoundHttpException.

Moreinformationonhandling404exceptionsandusingcustomresponsesfortheseerrorsmaybefoundintheerrorssectionofthedocumentation.

Throwing404Errors

IntroductionDefiningMiddlewareRegisteringMiddlewareTerminableMiddleware

HTTPmiddlewareprovideaconvenientmechanismforfilteringHTTPrequestsenteringyourapplication.Forexample,Laravelincludesamiddlewarethatverifiestheuserofyourapplicationisauthenticated.Iftheuserisnotauthenticated,themiddlewarewillredirecttheusertotheloginscreen.However,iftheuserisauthenticated,themiddlewarewillallowtherequesttoproceedfurtherintotheapplication.

Ofcourse,middlewarecanbewrittentoperformavarietyoftasksbesidesauthentication.ACORSmiddlewaremightberesponsibleforaddingtheproperheaderstoallresponsesleavingyourapplication.Aloggingmiddlewaremightlogallincomingrequeststoyourapplication.

ThereareseveralmiddlewareincludedintheLaravelframework,includingmiddlewareformaintenance,authentication,CSRFprotection,andmore.Allofthesemiddlewarearelocatedintheapp/Http/Middlewaredirectory.

Tocreateanewmiddleware,usethemake:middlewareArtisancommand:

phpartisanmake:middlewareOldMiddleware

ThiscommandwillplaceanewOldMiddlewareclasswithinyourapp/Http/Middlewaredirectory.Inthismiddleware,wewillonlyallowaccesstotherouteifthesuppliedageisgreaterthan200.Otherwise,wewillredirecttheusersbacktothe"home"URI.

<?phpnamespaceApp\Http\Middleware;

classOldMiddleware{

/**

*Runtherequestfilter.

*

*@param\Illuminate\Http\Request$request

*@param\Closure$next

*@returnmixed

*/

publicfunctionhandle($request,Closure$next)

{

if($request->input('age')<200)

{

returnredirect('home');

}

return$next($request);

}

}

Asyoucansee,ifthegivenageislessthan200,themiddlewarewillreturnanHTTPredirecttotheclient;otherwise,therequestwillbepassedfurtherintotheapplication.Topasstherequestdeeperintotheapplication(allowingthemiddlewareto"pass"),simplycallthe$nextcallbackwiththe$request.

HTTPMiddleware

Introduction

DefiningMiddleware

It'sbesttoenvisionmiddlewareasaseriesof"layers"HTTPrequestsmustpassthroughbeforetheyhityourapplication.Eachlayercanexaminetherequestandevenrejectitentirely.

IfyouwantamiddlewaretoberunduringeveryHTTPrequesttoyourapplication,simplylistthemiddlewareclassinthe$middlewarepropertyofyourapp/Http/Kernel.phpclass.

Ifyouwouldliketoassignmiddlewaretospecificroutes,youshouldfirstassignthemiddlewareashort-handkeyinyourapp/Http/Kernel.phpfile.Bydefault,the$routeMiddlewarepropertyofthisclasscontainsentriesforthemiddlewareincludedwithLaravel.Toaddyourown,simplyappendittothislistandassignitakeyofyourchoosing.

OncethemiddlewarehasbeendefinedintheHTTPkernel,youmayusethemiddlewarekeyintherouteoptionsarray:

Route::get('admin/profile',['middleware'=>'auth',function()

{

//

}]);

SometimesamiddlewaremayneedtodosomeworkaftertheHTTPresponsehasalreadybeensenttothebrowser.Forexample,the"session"middlewareincludedwithLaravelwritesthesessiondatatostorageaftertheresponsehasbeensenttothebrowser.Toaccomplishthis,youmaydefinethemiddlewareas"terminable".

useIlluminate\Contracts\Routing\TerminableMiddleware;

classStartSessionimplementsTerminableMiddleware{

publicfunctionhandle($request,$next)

{

return$next($request);

}

publicfunctionterminate($request,$response)

{

//Storethesessiondata...

}

}

Asyoucansee,inadditiontodefiningahandlemethod,TerminableMiddlewaredefineaterminatemethod.Thismethodreceivesboththerequestandtheresponse.Onceyouhavedefinedaterminablemiddleware,youshouldaddittothelistofglobalmiddlewaresinyourHTTPkernel.

RegisteringMiddleware

GlobalMiddleware

AssigningMiddlewareToRoutes

TerminableMiddleware

IntroductionBasicControllersControllerMiddlewareImplicitControllersRESTfulResourceControllersDependencyInjection&ControllersRouteCaching

Insteadofdefiningallofyourrequesthandlinglogicinasingleroutes.phpfile,youmaywishtoorganizethisbehaviorusingControllerclasses.ControllerscangrouprelatedHTTPrequesthandlinglogicintoaclass.Controllersaretypicallystoredintheapp/Http/Controllersdirectory.

Hereisanexampleofabasiccontrollerclass:

<?phpnamespaceApp\Http\Controllers;

useApp\Http\Controllers\Controller;

classUserControllerextendsController{

/**

*Showtheprofileforthegivenuser.

*

*@paramint$id

*@returnResponse

*/

publicfunctionshowProfile($id)

{

returnview('user.profile',['user'=>User::findOrFail($id)]);

}

}

Wecanroutetothecontrolleractionlikeso:

Route::get('user/{id}','UserController@showProfile');

Note:Allcontrollersshouldextendthebasecontrollerclass.

Itisveryimportanttonotethatwedidnotneedtospecifythefullcontrollernamespace,onlytheportionoftheclassnamethatcomesaftertheApp\Http\Controllersnamespace"root".Bydefault,theRouteServiceProviderwillloadtheroutes.phpfilewithinaroutegroupcontainingtherootcontrollernamespace.

IfyouchoosetonestororganizeyourcontrollersusingPHPnamespacesdeeperintotheApp\Http\Controllersdirectory,simplyusethespecificclassnamerelativetotheApp\Http\Controllersrootnamespace.So,ifyourfullcontrollerclassisApp\Http\Controllers\Photos\AdminController,youwouldregisteraroutelikeso:

HTTPControllers

Introduction

BasicControllers

Controllers&Namespaces

Route::get('foo','Photos\AdminController@method');

LikeClosureroutes,youmayspecifynamesoncontrollerroutes:

Route::get('foo',['uses'=>'FooController@method','as'=>'name']);

TogenerateaURLtoacontrolleraction,usetheactionhelpermethod:

$url=action('App\Http\Controllers\FooController@method');

IfyouwishtogenerateaURLtoacontrolleractionwhileusingonlytheportionoftheclassnamerelativetoyourcontrollernamespace,registertherootcontrollernamespacewiththeURLgenerator:

URL::setRootControllerNamespace('App\Http\Controllers');

$url=action('FooController@method');

YoumayaccessthenameofthecontrolleractionbeingrunusingthecurrentRouteActionmethod:

$action=Route::currentRouteAction();

Middlewaremaybespecifiedoncontrollerrouteslikeso:

Route::get('profile',[

'middleware'=>'auth',

'uses'=>'UserController@showProfile'

]);

Additionally,youmayspecifymiddlewarewithinyourcontroller'sconstructor:

classUserControllerextendsController{

/**

*InstantiateanewUserControllerinstance.

*/

publicfunction__construct()

{

$this->middleware('auth');

$this->middleware('log',['only'=>['fooAction','barAction']]);

$this->middleware('subscribed',['except'=>['fooAction','barAction']]);

}

}

NamingControllerRoutes

URLsToControllerActions

ControllerMiddleware

ImplicitControllers

Laravelallowsyoutoeasilydefineasingleroutetohandleeveryactioninacontroller.First,definetherouteusingtheRoute::controllermethod:

Route::controller('users','UserController');

Thecontrollermethodacceptstwoarguments.ThefirstisthebaseURIthecontrollerhandles,whilethesecondistheclassnameofthecontroller.Next,justaddmethodstoyourcontroller,prefixedwiththeHTTPverbtheyrespondto:

classUserControllerextendsBaseController{

publicfunctiongetIndex()

{

//

}

publicfunctionpostProfile()

{

//

}

publicfunctionanyLogin()

{

//

}

}

TheindexmethodswillrespondtotherootURIhandledbythecontroller,which,inthiscase,isusers.

Ifyourcontrolleractioncontainsmultiplewords,youmayaccesstheactionusing"dash"syntaxintheURI.Forexample,thefollowingcontrolleractiononourUserControllerwouldrespondtotheusers/admin-profileURI:

publicfunctiongetAdminProfile(){}

ResourcecontrollersmakeitpainlesstobuildRESTfulcontrollersaroundresources.Forexample,youmaywishtocreateacontrollerthathandlesHTTPrequestsregarding"photos"storedbyyourapplication.Usingthemake:controllerArtisancommand,wecanquicklycreatesuchacontroller:

phpartisanmake:controllerPhotoController

Next,weregisteraresourcefulroutetothecontroller:

Route::resource('photo','PhotoController');

ThissingleroutedeclarationcreatesmultipleroutestohandleavarietyofRESTfulactionsonthephotoresource.Likewise,thegeneratedcontrollerwillalreadyhavemethodsstubbedforeachoftheseactions,includingnotesinformingyouwhichURIsandverbstheyhandle.

Verb Path Action RouteName

GET /resource index resource.index

RESTfulResourceControllers

ActionsHandledByResourceController

GET /resource/create create resource.create

POST /resource store resource.store

GET /resource/{resource} show resource.show

GET /resource/{resource}/edit edit resource.edit

PUT/PATCH /resource/{resource} update resource.update

DELETE /resource/{resource} destroy resource.destroy

Additionally,youmayspecifyonlyasubsetofactionstohandleontheroute:

Route::resource('photo','PhotoController',

['only'=>['index','show']]);

Route::resource('photo','PhotoController',

['except'=>['create','store','update','destroy']]);

Bydefault,allresourcecontrolleractionshavearoutename;however,youcanoverridethesenamesbypassinganamesarraywithyouroptions:

Route::resource('photo','PhotoController',

['names'=>['create'=>'photo.build']]);

To"nest"resourcecontrollers,use"dot"notationinyourroutedeclaration:

Route::resource('photos.comments','PhotoCommentController');

Thisroutewillregistera"nested"resourcethatmaybeaccessedwithURLslikethefollowing:photos/{photos}/comments/{comments}.

classPhotoCommentControllerextendsController{

/**

*Showthespecifiedphotocomment.

*

*@paramint$photoId

*@paramint$commentId

*@returnResponse

*/

publicfunctionshow($photoId,$commentId)

{

//

}

}

Ifitbecomesnecessarytoaddadditionalroutestoaresourcecontrollerbeyondthedefaultresourceroutes,youshoulddefinethoseroutesbeforeyourcalltoRoute::resource:

Route::get('photos/popular');

CustomizingResourceRoutes

HandlingNestedResourceControllers

AddingAdditionalRoutesToResourceControllers

Route::resource('photos','PhotoController');

TheLaravelservicecontainerisusedtoresolveallLaravelcontrollers.Asaresult,youareabletotype-hintanydependenciesyourcontrollermayneedinitsconstructor:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Routing\Controller;

useApp\Repositories\UserRepository;

classUserControllerextendsController{

/**

*Theuserrepositoryinstance.

*/

protected$users;

/**

*Createanewcontrollerinstance.

*

*@paramUserRepository$users

*@returnvoid

*/

publicfunction__construct(UserRepository$users)

{

$this->users=$users;

}

}

Ofcourse,youmayalsotype-hintanyLaravelcontract.Ifthecontainercanresolveit,youcantype-hintit.

Inadditiontoconstructorinjection,youmayalsotype-hintdependenciesonyourcontroller'smethods.Forexample,let'stype-hinttheRequestinstanceononeofourmethods:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Http\Request;

useIlluminate\Routing\Controller;

classUserControllerextendsController{

/**

*Storeanewuser.

*

*@paramRequest$request

*@returnResponse

*/

publicfunctionstore(Request$request)

{

$name=$request->input('name');

//

}

}

Ifyourcontrollermethodisalsoexpectinginputfromarouteparameter,simplylistyourrouteargumentsafteryourotherdependencies:

DependencyInjection&Controllers

ConstructorInjection

MethodInjection

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Http\Request;

useIlluminate\Routing\Controller;

classUserControllerextendsController{

/**

*Storeanewuser.

*

*@paramRequest$request

*@paramint$id

*@returnResponse

*/

publicfunctionupdate(Request$request,$id)

{

//

}

}

Note:Methodinjectionisfullycompatiblewithmodelbinding.Thecontainerwillintelligentlydeterminewhichargumentsaremodelboundandwhichargumentsshouldbeinjected.

Ifyourapplicationisexclusivelyusingcontrollerroutes,youmaytakeadvantageofLaravel'sroutecache.Usingtheroutecachewilldrasticallydecreasetheamountoftimeittaketoregisterallofyourapplication'sroutes.Insomecases,yourrouteregistrationmayevenbeupto100xfaster!Togeneratearoutecache,justexecutetheroute:cacheArtisancommand:

phpartisanroute:cache

That'sallthereistoit!Yourcachedroutesfilewillnowbeusedinsteadofyourapp/Http/routes.phpfile.Remember,ifyouaddanynewroutesyouwillneedtogenerateafreshroutecache.Becauseofthis,youmaywishtoonlyruntheroute:cachecommandduringyourproject'sdeployment.

Toremovethecachedroutesfilewithoutgeneratinganewcache,usetheroute:clearcommand:

phpartisanroute:clear

RouteCaching

ObtainingARequestInstanceRetrievingInputOldInputCookiesFilesOtherRequestInformation

TheRequestfacadewillgrantyouaccesstothecurrentrequestthatisboundinthecontainer.Forexample:

$name=Request::input('name');

Remember,ifyouareinanamespace,youwillhavetoimporttheRequestfacadeusingauseRequest;statementatthetopofyourclassfile.

ToobtainaninstanceofthecurrentHTTPrequestviadependencyinjection,youshouldtype-hinttheclassonyourcontrollerconstructorormethod.Thecurrentrequestinstancewillautomaticallybeinjectedbytheservicecontainer:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Http\Request;

useIlluminate\Routing\Controller;

classUserControllerextendsController{

/**

*Storeanewuser.

*

*@paramRequest$request

*@returnResponse

*/

publicfunctionstore(Request$request)

{

$name=$request->input('name');

//

}

}

Ifyourcontrollermethodisalsoexpectinginputfromarouteparameter,simplylistyourrouteargumentsafteryourotherdependencies:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Http\Request;

useIlluminate\Routing\Controller;

classUserControllerextendsController{

/**

*Storeanewuser.

*

HTTPRequests

ObtainingARequestInstance

ViaFacade

ViaDependencyInjection

*@paramRequest$request

*@paramint$id

*@returnResponse

*/

publicfunctionupdate(Request$request,$id)

{

//

}

}

Usingafewsimplemethods,youmayaccessalluserinputfromyourIlluminate\Http\Requestinstance.YoudonotneedtoworryabouttheHTTPverbusedfortherequest,asinputisaccessedinthesamewayforallverbs.

$name=Request::input('name');

$name=Request::input('name','Sally');

if(Request::has('name'))

{

//

}

$input=Request::all();

$input=Request::only('username','password');

$input=Request::except('credit_card');

Whenworkingonformswith"array"inputs,youmayusedotnotationtoaccessthearrays:

$input=Request::input('products.0.name');

Laravelalsoallowsyoutokeepinputfromonerequestduringthenextrequest.Forexample,youmayneedtore-populateaformaftercheckingitforvalidationerrors.

RetrievingInput

RetrievingAnInputValue

RetrievingADefaultValueIfTheInputValueIsAbsent

DeterminingIfAnInputValueIsPresent

GettingAllInputForTheRequest

GettingOnlySomeOfTheRequestInput

OldInput

Theflashmethodwillflashthecurrentinputtothesessionsothatitisavailableduringtheuser'snextrequesttotheapplication:

Request::flash();

Request::flashOnly('username','email');

Request::flashExcept('password');

Sinceyouoftenwillwanttoflashinputinassociationwitharedirecttothepreviouspage,youmayeasilychaininputflashingontoaredirect.

returnredirect('form')->withInput();

returnredirect('form')->withInput(Request::except('password'));

Toretrieveflashedinputfromthepreviousrequest,usetheoldmethodontheRequestinstance.

$username=Request::old('username');

IfyouaredisplayingoldinputwithinaBladetemplate,itismoreconvenienttousetheoldhelper:

{{old('username')}}

AllcookiescreatedbytheLaravelframeworkareencryptedandsignedwithanauthenticationcode,meaningtheywillbeconsideredinvalidiftheyhavebeenchangedbytheclient.

$value=Request::cookie('name');

ThecookiehelperservesasasimplefactoryforgeneratingnewSymfony\Component\HttpFoundation\Cookieinstances.ThecookiesmaybeattachedtoaResponseinstanceusingthewithCookiemethod:

$response=newIlluminate\Http\Response('HelloWorld');

$response->withCookie(cookie('name','value',$minutes));

FlashingInputToTheSession

FlashingOnlySomeInputToTheSession

Flash&Redirect

RetrievingOldData

Cookies

RetrievingACookieValue

AttachingANewCookieToAResponse

By"forever",wereallymeanfiveyears.

$response->withCookie(cookie()->forever('name','value'));

$file=Request::file('photo');

if(Request::hasFile('photo'))

{

//

}

TheobjectreturnedbythefilemethodisaninstanceoftheSymfony\Component\HttpFoundation\File\UploadedFileclass,whichextendsthePHPSplFileInfoclassandprovidesavarietyofmethodsforinteractingwiththefile.

if(Request::file('photo')->isValid())

{

//

}

Request::file('photo')->move($destinationPath);

Request::file('photo')->move($destinationPath,$fileName);

ThereareavarietyofothermethodsavailableonUploadedFileinstances.CheckouttheAPIdocumentationfortheclassformoreinformationregardingthesemethods.

TheRequestclassprovidesmanymethodsforexaminingtheHTTPrequestforyourapplicationandextendstheSymfony\Component\HttpFoundation\Requestclass.Herearesomeofthehighlights.

$uri=Request::path();

CreatingACookieThatLastsForever*

Files

RetrievingAnUploadedFile

DeterminingIfAFileWasUploaded

DeterminingIfAnUploadedFileIsValid

MovingAnUploadedFile

OtherFileMethods

OtherRequestInformation

RetrievingTheRequestURI

$method=Request::method();

if(Request::isMethod('post'))

{

//

}

if(Request::is('admin/*'))

{

//

}

$url=Request::url();

RetrievingTheRequestMethod

DeterminingIfTheRequestPathMatchesAPattern

GetTheCurrentRequestURL

BasicResponsesRedirectsOtherResponsesResponseMacros

ThemostbasicresponsefromaLaravelrouteisastring:

Route::get('/',function()

{

return'HelloWorld';

});

However,formostroutesandcontrolleractions,youwillbereturningafullIlluminate\Http\Responseinstanceoraview.ReturningafullResponseinstanceallowsyoucustomizetheresponse'sHTTPstatuscodeandheaders.AResponseinstanceinheritsfromtheSymfony\Component\HttpFoundation\Responseclass,providingavarietyofmethodsforbuildingHTTPresponses:

useIlluminate\Http\Response;

return(newResponse($content,$status))

->header('Content-Type',$value);

Forconvenience,youmayalsousetheresponsehelper:

returnresponse($content,$status)

->header('Content-Type',$value);

Note:ForafulllistofavailableResponsemethods,checkoutitsAPIdocumentationandtheSymfonyAPIdocumentation.

IfyouneedaccesstotheResponseclassmethods,butwanttoreturnaviewastheresponsecontent,youmayusetheviewmethodforconvenience:

returnresponse()->view('hello')->header('Content-Type',$type);

returnresponse($content)->withCookie(cookie('name','value'));

HTTPResponses

BasicResponses

ReturningStringsFromRoutes

CreatingCustomResponses

SendingAViewInAResponse

AttachingCookiesToResponses

KeepinmindthatmostResponsemethodsarechainable,allowingforthefluentbuildingofresponses:

returnresponse()->view('hello')->header('Content-Type',$type)

->withCookie(cookie('name','value'));

RedirectresponsesaretypicallyinstancesoftheIlluminate\Http\RedirectResponseclass,andcontaintheproperheadersneededtoredirecttheusertoanotherURL.

ThereareseveralwaystogenerateaRedirectResponseinstance.Thesimplestmethodistousetheredirecthelpermethod.Whentesting,itisnotcommontomockthecreationofaredirectresponse,sousingthehelpermethodisalmostalwaysacceptable:

returnredirect('user/login');

RedirectingtoanewURLandflashingdatatothesessionaretypicallydoneatthesametime.So,forconvenience,youmaycreateaRedirectResponseinstanceandflashdatatothesessioninasinglemethodchain:

returnredirect('user/login')->with('message','LoginFailed');

Youmaywishtoredirecttheusertotheirpreviouslocation,forexample,afteraformsubmission.Youcandosobyusingthebackmethod:

returnredirect()->back();

returnredirect()->back()->withInput();

Whenyoucalltheredirecthelperwithnoparameters,aninstanceofIlluminate\Routing\Redirectorisreturned,allowingyoutocallanymethodontheRedirectorinstance.Forexample,togenerateaRedirectResponsetoanamedroute,youmayusetheroutemethod:

returnredirect()->route('login');

Ifyourroutehasparameters,youmaypassthemasthesecondargumenttotheroutemethod.

//ForaroutewiththefollowingURI:profile/{id}

MethodChaining

Redirects

ReturningARedirect

ReturningARedirectWithFlashData

RedirectingToThePreviousURL

ReturningARedirectToANamedRoute

ReturningARedirectToANamedRouteWithParameters

returnredirect()->route('profile',[1]);

Ifyouareredirectingtoaroutewithan"ID"parameterthatisbeingpopulatedfromanEloquentmodel,youmaysimplypassthemodelitself.TheIDwillbeextractedautomatically:

returnredirect()->route('profile',[$user]);

//ForaroutewiththefollowingURI:profile/{user}

returnredirect()->route('profile',['user'=>1]);

SimilarlytogeneratingRedirectResponseinstancestonamedroutes,youmayalsogenerateredirectstocontrolleractions:

returnredirect()->action('App\Http\Controllers\HomeController@index');

Note:YoudonotneedtospecifythefullnamespacetothecontrollerifyouhaveregisteredarootcontrollernamespaceviaURL::setRootControllerNamespace.

returnredirect()->action('App\Http\Controllers\UserController@profile',[1]);

returnredirect()->action('App\Http\Controllers\UserController@profile',['user'=>1]);

Theresponsehelpermaybeusedtoconvenientlygenerateothertypesofresponseinstances.Whentheresponsehelperiscalledwithoutarguments,animplementationoftheIlluminate\Contracts\Routing\ResponseFactorycontractisreturned.Thiscontractprovidesseveralhelpfulmethodsforgeneratingresponses.

ThejsonmethodwillautomaticallysettheContent-Typeheadertoapplication/json:

returnresponse()->json(['name'=>'Abigail','state'=>'CA']);

returnresponse()->json(['name'=>'Abigail','state'=>'CA'])

->setCallback($request->input('callback'));

ReturningARedirectToANamedRouteUsingNamedParameters

ReturningARedirectToAControllerAction

ReturningARedirectToAControllerActionWithParameters

ReturningARedirectToAControllerActionUsingNamedParameters

OtherResponses

CreatingAJSONResponse

CreatingAJSONPResponse

returnresponse()->download($pathToFile);

returnresponse()->download($pathToFile,$name,$headers);

Note:SymfonyHttpFoundation,whichmanagesfiledownloads,requiresthefilebeingdownloadedtohaveanASCIIfilename.

Ifyouwouldliketodefineacustomresponsethatyoucanre-useinavarietyofyourroutesandcontrollers,youmayusethemacromethodonanimplementationofIlluminate\Contracts\Routing\ResponseFactory.

Forexample,fromaserviceprovider'sbootmethod:

<?phpnamespaceApp\Providers;

useResponse;

useIlluminate\Support\ServiceProvider;

classResponseMacroServiceProviderextendsServiceProvider{

/**

*Performpost-registrationbootingofservices.

*

*@returnvoid

*/

publicfunctionboot()

{

Response::macro('caps',function($value)

{

returnResponse::make(strtoupper($value));

});

}

}

Themacrofunctionacceptsanameasitsfirstargument,andaClosureasitssecond.Themacro'sClosurewillbeexecutedwhencallingthemacronamefromaResponseFactoryimplementationortheresponsehelper:

returnresponse()->caps('foo');

CreatingAFileDownloadResponse

ResponseMacros

BasicUsageViewComposers

ViewscontaintheHTMLservedbyyourapplication,andserveasaconvenientmethodofseparatingyourcontrolleranddomainlogicfromyourpresentationlogic.Viewsarestoredintheresources/viewsdirectory.

Asimpleviewlookslikethis:

<!--Viewstoredinresources/views/greeting.php-->

<html>

<body>

<h1>Hello,<?phpecho$name;?></h1>

</body>

</html>

Theviewmaybereturnedtothebrowserlikeso:

Route::get('/',function()

{

returnview('greeting',['name'=>'James']);

});

Asyoucansee,thefirstargumentpassedtotheviewhelpercorrespondstothenameoftheviewfileintheresources/viewsdirectory.Thesecondargumentpassedtohelperisanarrayofdatathatshouldbemadeavailabletotheview.

Ofcourse,viewsmayalsobenestedwithinsub-directoriesoftheresources/viewsdirectory.Forexample,ifyourviewisstoredatresources/views/admin/profile.php,itshouldbereturnedlikeso:

returnview('admin.profile',$data);

//Usingconventionalapproach

$view=view('greeting')->with('name','Victoria');

//UsingMagicMethods

$view=view('greeting')->withName('Victoria');

Intheexampleabove,thevariable$nameismadeaccessibletotheviewandcontainsVictoria.

Ifyouwish,youmaypassanarrayofdataasthesecondparametertotheviewhelper:

$view=view('greetings',$data);

Views

BasicUsage

PassingDataToViews

SharingDataWithAllViews

Occasionally,youmayneedtoshareapieceofdatawithallviewsthatarerenderedbyyourapplication.Youhaveseveraloptions:theviewhelper,theIlluminate\Contracts\View\Factorycontract,orawildcardviewcomposer.

Forexample,usingtheviewhelper:

view()->share('data',[1,2,3]);

YoumayalsousetheViewfacade:

View::share('data',[1,2,3]);

Typically,youwouldplacecallstothesharemethodwithinaserviceprovider'sbootmethod.YouarefreetoaddthemtotheAppServiceProviderorgenerateaseparateserviceprovidertohousethem.

Note:Whentheviewhelperiscalledwithoutarguments,itreturnsanimplementationoftheIlluminate\Contracts\View\Factorycontract.

Ifyouneedtodetermineifaviewexists,youmayusetheexistsmethod:

if(view()->exists('emails.customer'))

{

//

}

Ifyouwish,youmaygenerateaviewfromafully-qualifiedfilepath:

returnview()->file($pathToFile,$data);

Viewcomposersarecallbacksorclassmethodsthatarecalledwhenaviewisrendered.Ifyouhavedatathatyouwanttobeboundtoavieweachtimethatviewisrendered,aviewcomposerorganizesthatlogicintoasinglelocation.

Let'sorganizeourviewcomposerswithinaserviceprovider.We'llusetheViewfacadetoaccesstheunderlyingIlluminate\Contracts\View\Factorycontractimplementation:

<?phpnamespaceApp\Providers;

useView;

useIlluminate\Support\ServiceProvider;

classComposerServiceProviderextendsServiceProvider{

/**

*Registerbindingsinthecontainer.

*

*@returnvoid

*/

publicfunctionboot()

{

DeterminingIfAViewExists

ReturningAViewFromAFilePath

ViewComposers

DefiningAViewComposer

//Usingclassbasedcomposers...

View::composer('profile','App\Http\ViewComposers\ProfileComposer');

//UsingClosurebasedcomposers...

View::composer('dashboard',function()

{

});

}

}

Note:Laraveldoesnotincludeadefaultdirectoryforviewcomposers.Youarefreetoorganizethemhoweveryouwish.Forexample,youcouldcreateanApp\Http\Composersdirectory.

Nowthatwehaveregisteredthecomposer,theProfileComposer@composemethodwillbeexecutedeachtimetheprofileviewisbeingrendered.So,let'sdefinethecomposerclass:

<?phpnamespaceApp\Http\Composers;

useIlluminate\Contracts\View\View;

useIlluminate\Users\RepositoryasUserRepository;

classProfileComposer{

/**

*Theuserrepositoryimplementation.

*

*@varUserRepository

*/

protected$users;

/**

*Createanewprofilecomposer.

*

*@paramUserRepository$users

*@returnvoid

*/

publicfunction__construct(UserRepository$users)

{

//Dependenciesautomaticallyresolvedbyservicecontainer...

$this->users=$users;

}

/**

*Binddatatotheview.

*

*@paramView$view

*@returnvoid

*/

publicfunctioncompose(View$view)

{

$view->with('count',$this->users->count());

}

}

Justbeforetheviewisrendered,thecomposer'scomposemethodiscalledwiththeIlluminate\Contracts\View\Viewinstance.Youmayusethewithmethodtobinddatatotheview.

Note:Allviewcomposersareresolvedviatheservicecontainer,soyoumaytype-hintanydependenciesyouneedwithinacomposer'sconstructor.

Thecomposermethodacceptsthe*characterasawildcard,soyoumayattachacomposertoallviewslikeso:

View::composer('*',function()

{

//

WildcardViewComposers

});

Youmayalsoattachaviewcomposertomultipleviewsatonce:

View::composer(['profile','dashboard'],'App\Http\ViewComposers\MyViewComposer');

Youmayusethecomposersmethodtoregisteragroupofcomposersatthesametime:

View::composers([

'App\Http\ViewComposers\AdminComposer'=>['admin.index','admin.profile'],

'App\Http\ViewComposers\UserComposer'=>'user',

'App\Http\ViewComposers\ProductComposer'=>'product'

]);

Viewcreatorsworkalmostexactlylikeviewcomposers;however,theyarefiredimmediatelywhentheviewisinstantiated.Toregisteraviewcreator,usethecreatormethod:

View::creator('profile','App\Http\ViewCreators\ProfileCreator');

AttachingAComposerToMultipleViews

DefiningMultipleComposers

ViewCreators

ServiceProvidersIntroductionBasicProviderExampleRegisteringProvidersDeferredProviders

ServiceContainerIntroductionBasicUsageBindingInterfacesToImplementationsContextualBindingTaggingPracticalApplicationsContainerEvents

ContractsIntroductionWhyContracts?ContractReferenceHowToUseContracts

FacadesIntroductionExplanationPracticalUsageCreatingFacadesMockingFacadesFacadeClassReference

RequestLifecycleIntroductionLifecycleOverviewFocusOnServiceProviders

ApplicationStructureIntroductionTheRootDirectoryTheAppDirectoryNamespacingYourApplication

ArchitectureFoundations

IntroductionBasicProviderExampleRegisteringProvidersDeferredProviders

ServiceprovidersarethecentralplaceofallLaravelapplicationbootstrapping.Yourownapplication,aswellasallofLaravel'scoreservicesarebootstrappedviaserviceproviders.

But,whatdowemeanby"bootstrapped"?Ingeneral,wemeanregisteringthings,includingregisteringservicecontainerbindings,eventlisteners,filters,andevenroutes.Serviceprovidersarethecentralplacetoconfigureyourapplication.

Ifyouopentheconfig/app.phpfileincludedwithLaravel,youwillseeaprovidersarray.Thesearealloftheserviceproviderclassesthatwillbeloadedforyourapplication.Ofcourse,manyofthemare"deferred"providers,meaningtheywillnotbeloadedoneveryrequest,butonlywhentheservicestheyprovideareactuallyneeded.

InthisoverviewyouwilllearnhowtowriteyourownserviceprovidersandregisterthemwithyourLaravelapplication.

AllserviceprovidersextendtheIlluminate\Support\ServiceProviderclass.Thisabstractclassrequiresthatyoudefineatleastonemethodonyourprovider:register.Withintheregistermethod,youshouldonlybindthingsintotheservicecontainer.Youshouldneverattempttoregisteranyeventlisteners,routes,oranyotherpieceoffunctionalitywithintheregistermethod.

TheArtisanCLIcaneasilygenerateanewproviderviathemake:providercommand:

phpartisanmake:providerRiakServiceProvider

Now,let'stakealookatabasicserviceprovider:

<?phpnamespaceApp\Providers;

useRiak\Connection;

useIlluminate\Support\ServiceProvider;

classRiakServiceProviderextendsServiceProvider{

/**

*Registerbindingsinthecontainer.

*

*@returnvoid

*/

publicfunctionregister()

{

$this->app->singleton('Riak\Contracts\Connection',function($app)

{

returnnewConnection($app['config']['riak']);

});

}

}

ServiceProviders

Introduction

BasicProviderExample

TheRegisterMethod

Thisserviceprovideronlydefinesaregistermethod,andusesthatmethodtodefineanimplementationofRiak\Contracts\Connectionintheservicecontainer.Ifyoudon'tunderstandhowtheservicecontainerworks,don'tworry,we'llcoverthatsoon.

ThisclassisnamespacedunderApp\ProviderssincethatisthedefaultlocationforserviceprovidersinLaravel.However,youarefreetochangethisasyouwish.YourserviceprovidersmaybeplacedanywherethatComposercanautoloadthem.

So,whatifweneedtoregisteraneventlistenerwithinourserviceprovider?Thisshouldbedonewithinthebootmethod.Thismethodiscalledafterallotherserviceprovidershavebeenregistered,meaningyouhaveaccesstoallotherservicesthathavebeenregisteredbytheframework.

<?phpnamespaceApp\Providers;

useEvent;

useIlluminate\Support\ServiceProvider;

classEventServiceProviderextendsServiceProvider{

/**

*Performpost-registrationbootingofservices.

*

*@returnvoid

*/

publicfunctionboot()

{

Event::listen('SomeEvent','SomeEventHandler');

}

/**

*Registerbindingsinthecontainer.

*

*@returnvoid

*/

publicfunctionregister()

{

//

}

}

Weareabletotype-hintdependenciesforourbootmethod.Theservicecontainerwillautomaticallyinjectanydependenciesyouneed:

useIlluminate\Contracts\Events\Dispatcher;

publicfunctionboot(Dispatcher$events)

{

$events->listen('SomeEvent','SomeEventHandler');

}

Allserviceprovidersareregisteredintheconfig/app.phpconfigurationfile.Thisfilecontainsaprovidersarraywhereyoucanlistthenamesofyourserviceproviders.Bydefault,asetofLaravelcoreserviceprovidersarelistedinthisarray.TheseprovidersbootstrapthecoreLaravelcomponents,suchasthemailer,queue,cache,andothers.

Toregisteryourprovider,simplyaddittothearray:

'providers'=>[

//OtherServiceProviders

TheBootMethod

RegisteringProviders

'App\Providers\AppServiceProvider',

],

Ifyourproviderisonlyregisteringbindingsintheservicecontainer,youmaychoosetodeferitsregistrationuntiloneoftheregisteredbindingsisactuallyneeded.Deferringtheloadingofsuchaproviderwillimprovetheperformanceofyourapplication,sinceitisnotloadedfromthefilesystemoneveryrequest.

Todefertheloadingofaprovider,setthedeferpropertytotrueanddefineaprovidesmethod.Theprovidesmethodreturnstheservicecontainerbindingsthattheproviderregisters:

<?phpnamespaceApp\Providers;

useRiak\Connection;

useIlluminate\Support\ServiceProvider;

classRiakServiceProviderextendsServiceProvider{

/**

*Indicatesifloadingoftheproviderisdeferred.

*

*@varbool

*/

protected$defer=true;

/**

*Registertheserviceprovider.

*

*@returnvoid

*/

publicfunctionregister()

{

$this->app->singleton('Riak\Contracts\Connection',function($app)

{

returnnewConnection($app['config']['riak']);

});

}

/**

*Gettheservicesprovidedbytheprovider.

*

*@returnarray

*/

publicfunctionprovides()

{

return['Riak\Contracts\Connection'];

}

}

Laravelcompilesandstoresalistofalloftheservicessuppliedbydeferredserviceproviders,alongwiththenameofitsserviceproviderclass.Then,onlywhenyouattempttoresolveoneoftheseservicesdoesLaravelloadtheserviceprovider.

DeferredProviders

IntroductionBasicUsageBindingInterfacesToImplementationsContextualBindingTaggingPracticalApplicationsContainerEvents

TheLaravelservicecontainerisapowerfultoolformanagingclassdependencies.Dependencyinjectionisafancywordthatessentiallymeansthis:classdependenciesare"injected"intotheclassviatheconstructoror,insomecases,"setter"methods.

Let'slookatasimpleexample:

<?phpnamespaceApp\Handlers\Commands;

useApp\User;

useApp\Commands\PurchasePodcast;

useIlluminate\Contracts\Mail\Mailer;

classPurchasePodcastHandler{

/**

*Themailerimplementation.

*/

protected$mailer;

/**

*Createanewinstance.

*

*@paramMailer$mailer

*@returnvoid

*/

publicfunction__construct(Mailer$mailer)

{

$this->mailer=$mailer;

}

/**

*Purchaseapodcast.

*

*@paramPurchasePodcastCommand$command

*@returnvoid

*/

publicfunctionhandle(PurchasePodcastCommand$command)

{

//

}

}

Inthisexample,thePurchasePodcastcommandhandlerneedstosende-mailswhenapodcastispurchased.So,wewillinjectaservicethatisabletosende-mails.Sincetheserviceisinjected,weareabletoeasilyswapitoutwithanotherimplementation.Wearealsoabletoeasily"mock",orcreateadummyimplementationofthemailerwhentestingourapplication.

AdeepunderstandingoftheLaravelservicecontainerisessentialtobuildingapowerful,largeapplication,aswellasforcontributingtotheLaravelcoreitself.

ServiceContainer

Introduction

Almostallofyourservicecontainerbindingswillberegisteredwithinserviceproviders,soalloftheseexampleswilldemonstrateusingthecontainerinthatcontext.However,ifyouneedaninstanceofthecontainerelsewhereinyourapplication,suchasafactory,youmaytype-hinttheIlluminate\Contracts\Container\Containercontractandaninstanceofthecontainerwillbeinjectedforyou.Alternatively,youmayusetheAppfacadetoaccessthecontainer.

Withinaserviceprovider,youalwayshaveaccesstothecontainerviathe$this->appinstancevariable.

Thereareseveralwaystheservicecontainercanregisterdependencies,includingClosurecallbacksandbindinginterfacestoimplementations.First,we'llexploreClosurecallbacks.AClosureresolverisregisteredinthecontainerwithakey(typicallytheclassname)andaClosurethatreturnssomevalue:

$this->app->bind('FooBar',function($app)

{

returnnewFooBar($app['SomethingElse']);

});

Sometimes,youmaywishtobindsomethingintothecontainerthatshouldonlyberesolvedonce,andthesameinstanceshouldbereturnedonsubsequentcallsintothecontainer:

$this->app->singleton('FooBar',function($app)

{

returnnewFooBar($app['SomethingElse']);

});

Youmayalsobindanexistingobjectinstanceintothecontainerusingtheinstancemethod.Thegiveninstancewillalwaysbereturnedonsubsequentcallsintothecontainer:

$fooBar=newFooBar(newSomethingElse);

$this->app->instance('FooBar',$fooBar);

Thereareseveralwaystoresolvesomethingoutofthecontainer.First,youmayusethemakemethod:

$fooBar=$this->app->make('FooBar');

Secondly,youmayuse"arrayaccess"onthecontainer,sinceitimplementsPHP'sArrayAccessinterface:

$fooBar=$this->app['FooBar'];

Lastly,butmostimportantly,youmaysimply"type-hint"thedependencyintheconstructorofaclassthatisresolvedbythe

BasicUsage

Binding

RegisteringABasicResolver

RegisteringASingleton

BindingAnExistingInstanceIntoTheContainer

Resolving

container,includingcontrollers,eventlisteners,queuejobs,filters,andmore.Thecontainerwillautomaticallyinjectthedependencies:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Routing\Controller;

useApp\Users\RepositoryasUserRepository;

classUserControllerextendsController{

/**

*Theuserrepositoryinstance.

*/

protected$users;

/**

*Createanewcontrollerinstance.

*

*@paramUserRepository$users

*@returnvoid

*/

publicfunction__construct(UserRepository$users)

{

$this->users=$users;

}

/**

*ShowtheuserwiththegivenID.

*

*@paramint$id

*@returnResponse

*/

publicfunctionshow($id)

{

//

}

}

Averypowerfulfeaturesoftheservicecontainerisitsabilitytobindaninterfacetoagivenimplementation.Forexample,perhapsourapplicationintegrateswiththePusherwebserviceforsendingandreceivingreal-timeevents.IfweareusingPusher'sPHPSDK,wecouldinjectaninstanceofthePusherclientintoaclass:

<?phpnamespaceApp\Handlers\Commands;

useApp\Commands\CreateOrder;

usePusher\ClientasPusherClient;

classCreateOrderHandler{

/**

*ThePusherSDKclientinstance.

*/

protected$pusher;

/**

*Createaneworderhandlerinstance.

*

*@paramPusherClient$pusher

*@returnvoid

*/

publicfunction__construct(PusherClient$pusher)

{

$this->pusher=$pusher;

}

/**

*Executethegivencommand.

BindingInterfacesToImplementations

InjectingConcreteDependencies

*

*@paramCreateOrder$command

*@returnvoid

*/

publicfunctionexecute(CreateOrder$command)

{

//

}

}

Inthisexample,itisgoodthatweareinjectingtheclassdependencies;however,wearetightlycoupledtothePusherSDK.IfthePusherSDKmethodschangeorwedecidetoswitchtoaneweventserviceentirely,wewillneedtochangeourCreateOrderHandlercode.

Inorderto"insulate"theCreateOrderHandleragainstchangestoeventpushing,wecoulddefineanEventPusherinterfaceandaPusherEventPusherimplementation:

<?phpnamespaceApp\Contracts;

interfaceEventPusher{

/**

*Pushaneweventtoallclients.

*

*@paramstring$event

*@paramarray$data

*@returnvoid

*/

publicfunctionpush($event,array$data);

}

OncewehavecodedourPusherEventPusherimplementationofthisinterface,wecanregisteritwiththeservicecontainerlikeso:

$this->app->bind('App\Contracts\EventPusher','App\Services\PusherEventPusher');

ThistellsthecontainerthatitshouldinjectthePusherEventPusherwhenaclassneedsanimplementationofEventPusher.Nowwecantype-hinttheEventPusherinterfaceinourconstructor:

/**

*Createaneworderhandlerinstance.

*

*@paramEventPusher$pusher

*@returnvoid

*/

publicfunction__construct(EventPusher$pusher)

{

$this->pusher=$pusher;

}

Sometimesyoumayhavetwoclassesthatutilizethesameinterface,butyouwishtoinjectdifferentimplementationsintoeachclass.Forexample,whenoursystemreceivesanewOrder,wemaywanttosendaneventviaPubNubratherthanPusher.Laravelprovidesasimple,fluentinterfacefordefininingthisbehavior:

$this->app->when('App\Handlers\Commands\CreateOrderHandler')

ProgramToAnInterface

ContextualBinding

->needs('App\Contracts\EventPusher')

->give('App\Services\PubNubEventPusher');

Occasionally,youmayneedtoresolveallofacertain"category"ofbinding.Forexample,perhapsyouarebuildingareportaggregatorthatreceivesanarrayofmanydifferentReportinterfaceimplementations.AfterregisteringtheReportimplementations,youcanassignthematagusingthetagmethod:

$this->app->bind('SpeedReport',function()

{

//

});

$this->app->bind('MemoryReport',function()

{

//

});

$this->app->tag(['SpeedReport','MemoryReport'],'reports');

Oncetheserviceshavebeentagged,youmayeasilyresolvethemallviathetaggedmethod:

$this->app->bind('ReportAggregator',function($app)

{

returnnewReportAggregator($app->tagged('reports'));

});

Laravelprovidesseveralopportunitiestousetheservicecontainertoincreasetheflexibilityandtestabilityofyourapplication.Oneprimaryexampleiswhenresolvingcontrollers.Allcontrollersareresolvedthroughtheservicecontainer,meaningyoucantype-hintdependenciesinacontrollerconstructor,andtheywillautomaticallybeinjected.

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Routing\Controller;

useApp\Repositories\OrderRepository;

classOrdersControllerextendsController{

/**

*Theorderrepositoryinstance.

*/

protected$orders;

/**

*Createacontrollerinstance.

*

*@paramOrderRepository$orders

*@returnvoid

*/

publicfunction__construct(OrderRepository$orders)

{

$this->orders=$orders;

}

/**

*Showalloftheorders.

*

*@returnResponse

*/

publicfunctionindex()

{

$all=$this->orders->all();

Tagging

PracticalApplications

returnview('orders',['all'=>$all]);

}

}

Inthisexample,theOrderRepositoryclasswillautomaticallybeinjectedintothecontroller.Thismeansthata"mock"OrderRepositorymaybeboundintothecontainerwhenunittesting,allowingforpainlessstubbingofdatabaselayerinteraction.

Ofcourse,asmentionedabove,controllersarenottheonlyclassesLaravelresolvesviatheservicecontainer.Youmayalsotype-hintdependenciesonrouteClosures,filters,queuejobs,eventlisteners,andmore.Forexamplesofusingtheservicecontainerinthesecontexts,pleaserefertotheirdocumentation.

Thecontainerfiresaneventeachtimeitresolvesanobject.Youmaylistentothiseventusingtheresolvingmethod:

$this->app->resolving(function($object,$app)

{

//Calledwhencontainerresolvesobjectofanytype...

});

$this->app->resolving(function(FooBar$fooBar,$app)

{

//Calledwhencontainerresolvesobjectsoftype"FooBar"...

});

Theobjectbeingresolvedwillbepassedtothecallback.

OtherExamplesOfContainerUsage

ContainerEvents

RegisteringAResolvingListener

IntroductionWhyContracts?ContractReferenceHowToUseContracts

Laravel'sContractsareasetofinterfacesthatdefinethecoreservicesprovidedbytheframework.Forexample,aQueuecontractdefinesthemethodsneededforqueueingjobs,whiletheMailercontractdefinesthemethodsneededforsendinge-mail.

Eachcontracthasacorrespondingimplementationprovidedbytheframework.Forexample,LaravelprovidesaQueueimplementationwithavarietyofdrivers,andaMailerimplementationthatispoweredbySwiftMailer.

AlloftheLaravelcontractsliveintheirownGitHubrepository.Thisprovidesaquickreferencepointforallavailablecontracts,aswellasasingle,decoupledpackagethatmaybeutilizedbyotherpackagedevelopers.

Youmayhaveseveralquestionsregardingcontracts.Whyuseinterfacesatall?Isn'tusinginterfacesmorecomplicated?

Let'sdistillthereasonsforusinginterfacestothefollowingheadings:loosecouplingandsimplicity.

First,let'sreviewsomecodethatistightlycoupledtoacacheimplementation.Considerthefollowing:

<?phpnamespaceApp\Orders;

classRepository{

/**

*Thecache.

*/

protected$cache;

/**

*Createanewrepositoryinstance.

*

*@param\Package\Cache\Memcached$cache

*@returnvoid

*/

publicfunction__construct(\SomePackage\Cache\Memcached$cache)

{

$this->cache=$cache;

}

/**

*RetrieveanOrderbyID.

*

*@paramint$id

*@returnOrder

*/

publicfunctionfind($id)

{

if($this->cache->has($id))

{

//

}

}

Contracts

Introduction

WhyContracts?

LooseCoupling

}

Inthisclass,thecodeistightlycoupledtoagivencacheimplementation.ItistightlycoupledbecausewearedependingonaconcreteCacheclassfromapackagevendor.IftheAPIofthatpackagechangesourcodemustchangeaswell.

Likewise,ifwewanttoreplaceourunderlyingcachetechnology(Memcached)withanothertechnology(Redis),weagainwillhavetomodifyourrepository.Ourrepositoryshouldnothavesomuchknowledgeregardingwhoisprovidingthemdataorhowtheyareprovidingit.

Insteadofthisapproach,wecanimproveourcodebydependingonasimple,vendoragnosticinterface:

<?phpnamespaceApp\Orders;

useIlluminate\Contracts\Cache\RepositoryasCache;

classRepository{

/**

*Createanewrepositoryinstance.

*

*@paramCache$cache

*@returnvoid

*/

publicfunction__construct(Cache$cache)

{

$this->cache=$cache;

}

}

Nowthecodeisnotcoupledtoanyspecificvendor,orevenLaravel.Sincethecontractspackagecontainsnoimplementationandnodependencies,youmayeasilywriteanalternativeimplementationofanygivencontract,allowingyoutoreplaceyourcacheimplementationwithoutmodifyinganyofyourcacheconsumingcode.

WhenallofLaravel'sservicesareneatlydefinedwithinsimpleinterfaces,itisveryeasytodeterminethefunctionalityofferedbyagivenservice.Thecontractsserveassuccinctdocumentationtotheframework'sfeatures.

Inaddition,whenyoudependonsimpleinterfaces,yourcodeiseasiertounderstandandmaintain.Ratherthantrackingdownwhichmethodsareavailabletoyouwithinalarge,complicatedclass,youcanrefertoasimple,cleaninterface.

ThisisareferencetomostLaravelContracts,aswellastheirLaravel"facade"counterparts:

Contract Laravel4.xFacade

Illuminate\Contracts\Auth\Guard Auth

Illuminate\Contracts\Auth\PasswordBroker Password

Illuminate\Contracts\Cache\Repository Cache

Illuminate\Contracts\Cache\Factory Cache::driver()

Illuminate\Contracts\Config\Repository Config

Illuminate\Contracts\Container\Container App

Illuminate\Contracts\Cookie\Factory Cookie

Illuminate\Contracts\Cookie\QueueingFactory Cookie::queue()

Illuminate\Contracts\Encryption\Encrypter Crypt

Simplicity

ContractReference

Illuminate\Contracts\Events\Dispatcher Event

Illuminate\Contracts\Filesystem\Cloud

Illuminate\Contracts\Filesystem\Factory File

Illuminate\Contracts\Filesystem\Filesystem File

Illuminate\Contracts\Foundation\Application App

Illuminate\Contracts\Hashing\Hasher Hash

Illuminate\Contracts\Logging\Log Log

Illuminate\Contracts\Mail\MailQueue Mail::queue()

Illuminate\Contracts\Mail\Mailer Mail

Illuminate\Contracts\Queue\Factory Queue::driver()

Illuminate\Contracts\Queue\Queue Queue

Illuminate\Contracts\Redis\Database Redis

Illuminate\Contracts\Routing\Registrar Route

Illuminate\Contracts\Routing\ResponseFactory Response

Illuminate\Contracts\Routing\UrlGenerator URL

Illuminate\Contracts\Support\Arrayable

Illuminate\Contracts\Support\Jsonable

Illuminate\Contracts\Support\Renderable

Illuminate\Contracts\Validation\Factory Validator::make()

Illuminate\Contracts\Validation\Validator

Illuminate\Contracts\View\Factory View::make()

Illuminate\Contracts\View\View

So,howdoyougetanimplementationofacontract?It'sactuallyquitesimple.ManytypesofclassesinLaravelareresolvedthroughtheservicecontainer,includingcontrollers,eventlisteners,filters,queuejobs,andevenrouteClosures.So,togetanimplementationofacontract,youcanjust"type-hint"theinterfaceintheconstructoroftheclassbeingresolved.Forexample,takealookatthiseventhandler:

<?phpnamespaceApp\Handlers\Events;

useApp\User;

useApp\Events\NewUserRegistered;

useIlluminate\Contracts\Redis\Database;

classCacheUserInformation{

/**

*TheRedisdatabaseimplementation.

*/

protected$redis;

/**

*Createaneweventhandlerinstance.

*

*@paramDatabase$redis

*@returnvoid

*/

publicfunction__construct(Database$redis)

{

$this->redis=$redis;

HowToUseContracts

}

/**

*Handletheevent.

*

*@paramNewUserRegistered$event

*@returnvoid

*/

publicfunctionhandle(NewUserRegistered$event)

{

//

}

}

Whentheeventlistenerisresolved,theservicecontainerwillreadthetype-hintsontheconstructoroftheclass,andinjecttheappropriatevalue.Tolearnmoreaboutregisteringthingsintheservicecontainer,checkoutthedocumentation.

IntroductionExplanationPracticalUsageCreatingFacadesMockingFacadesFacadeClassReference

Facadesprovidea"static"interfacetoclassesthatareavailableintheapplication'sIoCcontainer.Laravelshipswithmanyfacades,andyouhaveprobablybeenusingthemwithoutevenknowingit!Laravel"facades"serveas"staticproxies"tounderlyingclassesintheIoCcontainer,providingthebenefitofaterse,expressivesyntaxwhilemaintainingmoretestabilityandflexibilitythantraditionalstaticmethods.

Occasionally,Youmaywishtocreateyourownfacadesforyourapplicationsandpackages,solet'sexploretheconcept,developmentandusageoftheseclasses.

Note:Beforediggingintofacades,itisstronglyrecommendedthatyoubecomeveryfamiliarwiththeLaravelIoCcontainer.

InthecontextofaLaravelapplication,afacadeisaclassthatprovidesaccesstoanobjectfromthecontainer.ThemachinerythatmakesthisworkisintheFacadeclass.Laravel'sfacades,andanycustomfacadesyoucreate,willextendthebaseFacadeclass.

Yourfacadeclassonlyneedstoimplementasinglemethod:getFacadeAccessor.It'sthegetFacadeAccessormethod'sjobtodefinewhattoresolvefromthecontainer.TheFacadebaseclassmakesuseofthe__callStatic()magic-methodtodefercallsfromyourfacadetotheresolvedobject.

So,whenyoumakeafacadecalllikeCache::get,LaravelresolvestheCachemanagerclassoutoftheIoCcontainerandcallsthegetmethodontheclass.Intechnicalterms,LaravelFacadesareaconvenientsyntaxforusingtheLaravelIoCcontainerasaservicelocator.

Intheexamplebelow,acallismadetotheLaravelcachesystem.Byglancingatthiscode,onemightassumethatthestaticmethodgetisbeingcalledontheCacheclass.

$value=Cache::get('key');

However,ifwelookatthatIlluminate\Support\Facades\Cacheclass,you'llseethatthereisnostaticmethodget:

classCacheextendsFacade{

/**

*Gettheregisterednameofthecomponent.

*

*@returnstring

*/

protectedstaticfunctiongetFacadeAccessor(){return'cache';}

Facades

Introduction

Explanation

PracticalUsage

}

TheCacheclassextendsthebaseFacadeclassanddefinesamethodgetFacadeAccessor().Remember,thismethod'sjobistoreturnthenameofanIoCbinding.

WhenauserreferencesanystaticmethodontheCachefacade,LaravelresolvesthecachebindingfromtheIoCcontainerandrunstherequestedmethod(inthiscase,get)againstthatobject.

So,ourCache::getcallcouldbere-writtenlikeso:

$value=$app->make('cache')->get('key');

Remember,ifyouareusingafacadewhenacontrollerthatisnamespaced,youwillneedtoimportthefacadeclassintothenamespace.Allfacadesliveintheglobalnamespace:

<?phpnamespaceApp\Http\Controllers;

useCache;

classPhotosControllerextendsController{

/**

*Getalloftheapplicationphotos.

*

*@returnResponse

*/

publicfunctionindex()

{

$photos=Cache::get('photos');

//

}

}

Creatingafacadeforyourownapplicationorpackageissimple.Youonlyneed3things:

AnIoCbinding.Afacadeclass.Afacadealiasconfiguration.

Let'slookatanexample.Here,wehaveaclassdefinedasPaymentGateway\Payment.

namespacePaymentGateway;

classPayment{

publicfunctionprocess()

{

//

}

}

WeneedtobeabletoresolvethisclassfromtheIoCcontainer.So,let'saddabindingtoaserviceprovider:

ImportingFacades

CreatingFacades

App::bind('payment',function()

{

returnnew\PaymentGateway\Payment;

});

AgreatplacetoregisterthisbindingwouldbetocreateanewserviceprovidernamedPaymentServiceProvider,andaddthisbindingtotheregistermethod.YoucanthenconfigureLaraveltoloadyourserviceproviderfromtheconfig/app.phpconfigurationfile.

Next,wecancreateourownfacadeclass:

useIlluminate\Support\Facades\Facade;

classPaymentextendsFacade{

protectedstaticfunctiongetFacadeAccessor(){return'payment';}

}

Finally,ifwewish,wecanaddanaliasforourfacadetothealiasesarrayintheconfig/app.phpconfigurationfile.Now,wecancalltheprocessmethodonaninstanceofthePaymentclass.

Payment::process();

ClassesinthealiasesarrayarenotavailableinsomeinstancesbecausePHPwillnotattempttoautoloadundefinedtype-hintedclasses.If\ServiceWrapper\ApiTimeoutExceptionisaliasedtoApiTimeoutException,acatch(ApiTimeoutException$e)outsideofthenamespace\ServiceWrapperwillnevercatchtheexception,evenifoneisthrown.Asimilarproblemisfoundinclasseswhichhavetypehintstoaliasedclasses.Theonlyworkaroundistoforegoaliasingandusetheclassesyouwishtotypehintatthetopofeachfilewhichrequiresthem.

Unittestingisanimportantaspectofwhyfacadesworkthewaythattheydo.Infact,testabilityistheprimaryreasonforfacadestoevenexist.Formoreinformation,checkoutthemockingfacadessectionofthedocumentation.

Belowyouwillfindeveryfacadeanditsunderlyingclass.ThisisausefultoolforquicklydiggingintotheAPIdocumentationforagivenfacaderoot.TheIoCbindingkeyisalsoincludedwhereapplicable.

Facade Class IoCBinding

App Illuminate\Foundation\Application app

Artisan Illuminate\Console\Application artisan

Auth Illuminate\Auth\AuthManager auth

Auth(Instance) Illuminate\Auth\Guard

Blade Illuminate\View\Compilers\BladeCompiler blade.compiler

Cache Illuminate\Cache\Repository cache

Config Illuminate\Config\Repository config

Cookie Illuminate\Cookie\CookieJar cookie

ANoteOnAuto-LoadingAliases

MockingFacades

FacadeClassReference

Crypt Illuminate\Encryption\Encrypter encrypter

DB Illuminate\Database\DatabaseManager db

DB(Instance) Illuminate\Database\Connection

Event Illuminate\Events\Dispatcher events

File Illuminate\Filesystem\Filesystem files

Form Illuminate\Html\FormBuilder form

Hash Illuminate\Hashing\HasherInterface hash

HTML Illuminate\Html\HtmlBuilder html

Input Illuminate\Http\Request request

Lang Illuminate\Translation\Translator translator

Log Illuminate\Log\Writer log

Mail Illuminate\Mail\Mailer mailer

Paginator Illuminate\Pagination\Factory paginator

Paginator(Instance) Illuminate\Pagination\Paginator

Password Illuminate\Auth\Passwords\PasswordBroker auth.reminder

Queue Illuminate\Queue\QueueManager queue

Queue(Instance) Illuminate\Queue\QueueInterface

Queue(BaseClass) Illuminate\Queue\Queue

Redirect Illuminate\Routing\Redirector redirect

Redis Illuminate\Redis\Database redis

Request Illuminate\Http\Request request

Response Illuminate\Support\Facades\Response

Route Illuminate\Routing\Router router

Schema Illuminate\Database\Schema\Blueprint

Session Illuminate\Session\SessionManager session

Session(Instance) Illuminate\Session\Store

SSH Illuminate\Remote\RemoteManager remote

SSH(Instance) Illuminate\Remote\Connection

URL Illuminate\Routing\UrlGenerator url

Validator Illuminate\Validation\Factory validator

Validator(Instance) Illuminate\Validation\Validator

View Illuminate\View\Factory view

View(Instance) Illuminate\View\View

IntroductionLifecycleOverviewFocusOnServiceProviders

Whenusinganytoolinthe"realworld",youfeelmoreconfidentifyouunderstandhowthattoolworks.Applicationdevelopmentisnodifferent.Whenyouunderstandhowyourdevelopmenttoolsfunction,youfeelmorecomfortableandconfidentusingthem.

Thegoalofthisdocumentistogiveyouagood,high-leveloverviewofhowtheLaravelframework"works".Bygettingtoknowtheoverallframeworkbetter,everythingfeelsless"magical"andyouwillbemoreconfidentbuildingyourapplications.

Ifyoudon'tunderstandallofthetermsrightaway,don'tloseheart!Justtrytogetabasicgraspofwhatisgoingon,andyourknowledgewillgrowasyouexploreothersectionsofthedocumentation.

TheentrypointforallrequeststoaLaravelapplicationisthepublic/index.phpfile.Allrequestsaredirectedtothisfilebyyourwebserver(Apache/Nginx)configuration.Theindex.phpfiledoesn'tcontainmuchcode.Rather,itissimplyastartingpointforloadingtherestoftheframework.

Theindex.phpfileloadstheComposergeneratedautoloaderdefinition,andthenretrievesaninstanceoftheLaravelapplicationfrombootstrap/app.phpscript.ThefirstactiontakenbyLaravelitselfistocreateaninstanceoftheapplication/servicecontainer.

Next,theincomingrequestissenttoeithertheHTTPkernelortheconsolekernel,dependingonthetypeofrequestthatisenteringtheapplication.Thesetwokernelsserveasthecentrallocationthatallrequestsflowthrough.Fornow,let'sjustfocusontheHTTPkernel,whichislocatedinapp/Http/Kernel.php.

TheHTTPkernelextendstheIlluminate\Foundation\Http\Kernelclass,whichdefinesanarrayofbootstrappersthatwillberunbeforetherequestisexecuted.Thesebootstrappersconfigureerrorhandling,configurelogging,detecttheapplicationenvironment,andperformothertasksthatneedtobedonebeforetherequestisactuallyhandled.

TheHTTPkernelalsodefinesalistofHTTPmiddlewarethatallrequestsmustpassthroughbeforebeinghandledbytheapplication.ThesemiddlewarehandlereadingandwritingtheHTTPsession,determineiftheapplicationisinmaintenancemode,verifyingtheCSRFtoken,andmore.

ThemethodsignaturefortheHTTPkernel'shandlemethodisquitesimple:receiveaRequestandreturnaResponse.ThinkoftheKernelasbeingabigblackboxthatrepresentsyourentireapplication.FeeditHTTPrequestsanditwillreturnHTTPresponses.

OneofthemostimportantKernelbootstrappingactionsisloadingtheserviceprovidersforyourapplication.Alloftheserviceprovidersfortheapplicationareconfiguredintheconfig/app.phpconfigurationfile'sprovidersarray.First,theregistermethodwillbecalledonallproviders,then,onceallprovidershavebeenregistered,thebootmethodwillbe

RequestLifecycle

Introduction

LifecycleOverview

FirstThings

HTTP/ConsoleKernels

ServiceProviders

called.

Oncetheapplicationhasbeenbootstrappedandallserviceprovidershavebeenregistered,theRequestwillbehandedofftotherouterfordispatching.Therouterwilldispatchtherequesttoarouteorcontroller,aswellasrunanyroutespecificmiddleware.

ServiceprovidersaretrulythekeytobootstrappingaLaravelapplication.Theapplicationinstanceiscreated,theserviceprovidersareregistered,andtherequestishandedtothebootstrappedapplication.It'sreallythatsimple!

HavingafirmgraspofhowaLaravelapplicationisbuiltandbootstrappedviaserviceprovidersisveryvaluable.Ofcourse,yourapplication'sdefaultserviceprovidersarestoredintheapp/Providersdirectory.

Bydefault,theAppServiceProviderisfairlyempty.Thisproviderisagreatplacetoaddyourapplication'sownbootstrappingandservicecontainerbindings.Ofcourse,forlargeapplications,youmaywishtocreateseveralserviceproviders,eachwithamoregranulartypeofbootstrapping.

DispatchRequest

FocusOnServiceProviders

IntroductionTheRootDirectoryTheAppDirectoryNamespacingYourApplication

ThedefaultLaravelapplicationstructureisintendedtoprovideagreatstartingpointforbothlargeandsmallapplications.Ofcourse,youarefreetoorganizeyourapplicationhoweveryoulike.Laravelimposesalmostnorestrictionsonwhereanygivenclassislocated-aslongasComposercanautoloadtheclass.

TherootdirectoryofafreshLaravelinstallationcontainsavarietyoffolders:

Theappdirectory,asyoumightexpect,containsthecorecodeofyourapplication.We'llexplorethisfolderinmoredetailsoon.

Thebootstrapfoldercontainsafewfilesthatbootstraptheframeworkandconfigureautoloading.

Theconfigdirectory,asthenameimplies,containsallofyourapplication'sconfigurationfiles.

Thedatabasefoldercontainsyourdatabasemigrationandseeds.

Thepublicdirectorycontainsthefrontcontrollerandyourassets(images,JavaScript,CSS,etc.).

Theresourcesdirectorycontainsyourviews,rawassets(LESS,SASS,CoffeeScript),and"language"files.

ThestoragedirectorycontainscompiledBladetemplates,filebasedsessions,filecaches,andotherfilesgeneratedbytheframework.

Thetestsdirectorycontainsyourautomatedtests.

ThevendordirectorycontainsyourComposerdependencies.

The"meat"ofyourapplicationlivesintheappdirectory.Bydefault,thisdirectoryisnamespacedunderAppandisautoloadedbyComposerusingthePSR-4autoloadingstandard.Youmaychangethisnamespaceusingtheapp:nameArtisancommand.

TheappdirectoryshipswithavarietyofadditionaldirectoriessuchasConsole,Http,andProviders.ThinkoftheConsoleandHttpdirectoriesasprovidinganAPIintothe"core"ofyourapplication.TheHTTPprotocolandCLIarebothmechanismstointeractwithyourapplication,butdonotactuallycontainapplicationlogic.Inotherwords,theyaresimplytwowaysofissuingcommandstoyourapplication.TheConsoledirectorycontainsallofyourArtisancommands,whiletheHttpdirectorycontainsyourcontrollers,filters,andrequests.

TheCommandsdirectory,ofcourse,housesthecommandsforyourapplication.Commandsrepresentjobsthatcanbequeuedbyyourapplication,aswellastasksthatyoucanrunsynchronouslywithinthecurrentrequestlifecycle.

TheEventsdirectory,asyoumightexpect,houseseventclasses.Ofcourse,usingclassestorepresenteventsisnot

ApplicationStructure

Introduction

TheRootDirectory

TheAppDirectory

required;however,ifyouchoosetousethem,thisdirectoryisthedefaultlocationtheywillbecreatedbytheArtisancommandline.

TheHandlersdirectorycontainsthehandlerclassesforbothcommandsandevents.Handlersreceiveacommandoreventandperformlogicinresponsetothatcommandoreventbeingfired.

TheServicesdirectorycontainsvarious"helper"servicesyourapplicationneedstofunction.Forexample,theRegistrarserviceincludedwithLaravelisresponsibleforvalidatingandcreatingnewusersofyourapplication.OtherexamplesmightbeservicestointeractwithexternalAPIs,metricssystems,orevenservicesthataggregatedatafromyourownapplication.

TheExceptionsdirectorycontainsyourapplication'sexceptionhandlerandisalsoagoodplacetostickanyexceptionsthrownbyyourapplication.

Note:ManyoftheclassesintheappdirectorycanbegeneratedbyArtisanviacommands.Toreviewtheavailablecommands,runthephpartisanlistmakecommandinyourterminal.

Asdiscussedabove,thedefaultapplicationnamespaceisApp;however,youmaychangethisnamespacetomatchthenameofyourapplication,whichiseasilydoneviatheapp:nameArtisancommand.Forexample,ifyourapplicationisnamed"SocialNet",youwouldrunthefollowingcommand:

phpartisanapp:nameSocialNet

NamespacingYourApplication

AuthenticationIntroductionAuthenticatingUsersRetrievingTheAuthenticatedUserProtectingRoutesHTTPBasicAuthenticationPasswordReminders&ResetSocialAuthentication

BillingIntroductionConfigurationSubscribingToAPlanNoCardUpFrontSwappingSubscriptionsSubscriptionQuantityCancellingASubscriptionResumingASubscriptionCheckingSubscriptionStatusHandlingFailedPaymentsHandlingOtherStripeWebhooksInvoices

CacheConfigurationCacheUsageIncrements&DecrementsCacheTagsDatabaseCache

CollectionsIntroductionBasicUsage

CommandBusIntroductionCreatingCommandsDispatchingCommandsQueuedCommandsCommandPipeline

CoreExtensionManagers&FactoriesCacheSessionAuthenticationIoCBasedExtension

ElixirIntroductionInstallation&SetupUsageGulpExtensions

EncryptionIntroductionBasicUsage

Errors&Logging

Services

ConfigurationHandlingErrorsHTTPExceptionsLogging

EventsBasicUsageQueuedEventHandlersEventSubscribers

Filesystem/CloudStorageIntroductionConfigurationBasicUsage

HashingIntroductionBasicUsage

HelpersArraysPathsStringsURLsMiscellaneous

LocalizationIntroductionLanguageFilesBasicUsagePluralizationValidationLocalizationOverridingPackageLanguageFiles

MailConfigurationBasicUsageEmbeddingInlineAttachmentsQueueingMailMail&LocalDevelopment

PackageDevelopmentIntroductionViewsTranslationsConfigurationPublishingFileGroupsRouting

PaginationConfigurationUsageAppendingToPaginationLinksConvertingToJSON

QueuesConfigurationBasicUsageQueueingClosuresRunningTheQueueListenerDaemonQueueWorkerPushQueuesFailedJobs

SessionConfiguration

SessionUsageFlashDataDatabaseSessionsSessionDrivers

TemplatesBladeTemplatingOtherBladeControlStructuresExtendingBlade

UnitTestingIntroductionDefining&RunningTestsTestEnvironmentCallingRoutesFromTestsMockingFacadesFrameworkAssertionsHelperMethodsRefreshingTheApplication

ValidationBasicUsageControllerValidationFormRequestValidationWorkingWithErrorMessagesErrorMessages&ViewsAvailableValidationRulesConditionallyAddingRulesCustomErrorMessagesCustomValidationRules

IntroductionAuthenticatingUsersRetrievingTheAuthenticatedUserProtectingRoutesHTTPBasicAuthenticationPasswordReminders&ResetSocialAuthentication

Laravelmakesimplementingauthenticationverysimple.Infact,almosteverythingisconfiguredforyououtofthebox.Theauthenticationconfigurationfileislocatedatconfig/auth.php,whichcontainsseveralwelldocumentedoptionsfortweakingthebehavioroftheauthenticationservices.

Bydefault,LaravelincludesanApp\Usermodelinyourappdirectory.ThismodelmaybeusedwiththedefaultEloquentauthenticationdriver.

Remember:whenbuildingthedatabaseschemaforthismodel,makethepasswordcolumnatleast60characters.Also,beforegettingstarted,makesurethatyourusers(orequivalent)tablecontainsanullable,stringremember_tokencolumnof100characters.Thiscolumnwillbeusedtostoreatokenfor"rememberme"sessionsbeingmaintainedbyyourapplication.Thiscanbedonebyusing$table->rememberToken();inamigration.Ofcourse,Laravel5shipsmigrationsforthesecolumnsoutofthebox!

IfyourapplicationisnotusingEloquent,youmayusethedatabaseauthenticationdriverwhichusestheLaravelquerybuilder.

Laravelshipswithtwoauthenticationrelatedcontrollersoutofthebox.TheAuthControllerhandlesnewuserregistrationand"loggingin",whilethePasswordControllercontainsthelogictohelpexistingusersresettheirforgottenpasswords.

Eachofthesecontrollersusesatraittoincludetheirnecessarymethods.Formanyapplications,youwillnotneedtomodifythesecontrollersatall.Theviewsthatthesecontrollersrenderarelocatedintheresources/views/authdirectory.Youarefreetocustomizetheseviewshoweveryouwish.

Tomodifytheformfieldsthatarerequiredwhenanewuserregisterswithyourapplication,youmaymodifytheApp\Services\Registrarclass.Thisclassisresponsibleforvalidatingandcreatingnewusersofyourapplication.

ThevalidatormethodoftheRegistrarcontainsthevalidationrulesfornewusersoftheapplication,whilethecreatemethodoftheRegistrarisresponsibleforcreatingnewUserrecordsinyourdatabase.Youarefreetomodifyeachofthesemethodsasyouwish.TheRegistrariscalledbytheAuthControllerviathemethodscontainedintheAuthenticatesAndRegistersUserstrait.

IfyouchoosenottousetheprovidedAuthControllerimplementation,youwillneedtomanagetheauthenticationofyourusersusingtheLaravelauthenticationclassesdirectly.Don'tworry,it'sstillacinch!First,let'scheckouttheattemptmethod:

Authentication

Introduction

AuthenticatingUsers

TheUserRegistrar

ManualAuthentication

<?phpnamespaceApp\Http\Controllers;

useAuth;

useIlluminate\Routing\Controller;

classAuthControllerextendsController{

/**

*Handleanauthenticationattempt.

*

*@returnResponse

*/

publicfunctionauthenticate()

{

if(Auth::attempt(['email'=>$email,'password'=>$password]))

{

returnredirect()->intended('dashboard');

}

}

}

Theattemptmethodacceptsanarrayofkey/valuepairsasitsfirstargument.Thepasswordvaluewillbehashed.Theothervaluesinthearraywillbeusedtofindtheuserinyourdatabasetable.So,intheexampleabove,theuserwillberetrievedbythevalueoftheemailcolumn.Iftheuserisfound,thehashedpasswordstoredinthedatabasewillbecomparedwiththehashedpasswordvaluepassedtothemethodviathearray.Ifthetwohashedpasswordsmatch,anewauthenticatedsessionwillbestartedfortheuser.

Theattemptmethodwillreturntrueifauthenticationwassuccessful.Otherwise,falsewillbereturned.

Note:Inthisexample,emailisnotarequiredoption,itismerelyusedasanexample.Youshouldusewhatevercolumnnamecorrespondstoa"username"inyourdatabase.

TheintendedredirectfunctionwillredirecttheusertotheURLtheywereattemptingtoaccessbeforebeingcaughtbytheauthenticationfilter.AfallbackURImaybegiventothismethodincasetheintendeddestinationisnotavailable.

Youalsomayaddextraconditionstotheauthenticationquery:

if(Auth::attempt(['email'=>$email,'password'=>$password,'active'=>1]))

{

//Theuserisactive,notsuspended,andexists.

}

Todetermineiftheuserisalreadyloggedintoyourapplication,youmayusethecheckmethod:

if(Auth::check())

{

//Theuserisloggedin...

}

Ifyouwouldliketoprovide"rememberme"functionalityinyourapplication,youmaypassabooleanvalueasthesecondargumenttotheattemptmethod,whichwillkeeptheuserauthenticatedindefinitely,oruntiltheymanuallylogout.Ofcourse,youruserstablemustincludethestringremember_tokencolumn,whichwillbeusedtostorethe"rememberme"token.

if(Auth::attempt(['email'=>$email,'password'=>$password],$remember))

AuthenticatingAUserWithConditions

DeterminingIfAUserIsAuthenticated

AuthenticatingAUserAnd"Remembering"Them

{

//Theuserisbeingremembered...

}

Ifyouare"remembering"users,youmayusetheviaRemembermethodtodetermineiftheuserwasauthenticatedusingthe"rememberme"cookie:

if(Auth::viaRemember())

{

//

}

TologauserintotheapplicationbytheirID,usetheloginUsingIdmethod:

Auth::loginUsingId(1);

Thevalidatemethodallowsyoutovalidateauser'scredentialswithoutactuallyloggingthemintotheapplication:

if(Auth::validate($credentials))

{

//

}

Youmayalsousetheoncemethodtologauserintotheapplicationforasinglerequest.Nosessionsorcookieswillbeutilized:

if(Auth::once($credentials))

{

//

}

Ifyouneedtologanexistinguserinstanceintoyourapplication,youmaycalltheloginmethodwiththeuserinstance:

Auth::login($user);

Thisisequivalenttologginginauserviacredentialsusingtheattemptmethod.

Auth::logout();

Ofcourse,ifyouareusingthebuilt-inLaravelauthenticationcontrollers,acontrollermethodthathandlesloggingusersoutoftheapplicationisprovidedoutofthebox.

AuthenticatingUsersByID

ValidatingUserCredentialsWithoutLogin

LoggingAUserInForASingleRequest

ManuallyLoggingInAUser

LoggingAUserOutOfTheApplication

Whentheattemptmethodiscalled,theauth.attempteventwillbefired.Iftheauthenticationattemptissuccessfulandtheuserisloggedin,theauth.logineventwillbefiredaswell.

Onceauserisauthenticated,thereareseveralwaystoobtainaninstanceoftheUser.

First,youmayaccesstheuserfromtheAuthfacade:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Routing\Controller;

classProfileControllerextendsController{

/**

*Updatetheuser'sprofile.

*

*@returnResponse

*/

publicfunctionupdateProfile()

{

if(Auth::user())

{

//Auth::user()returnsaninstanceoftheauthenticateduser...

}

}

}

Second,youmayaccesstheauthenticateduserviaanIlluminate\Http\Requestinstance:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Http\Request;

useIlluminate\Routing\Controller;

classProfileControllerextendsController{

/**

*Updatetheuser'sprofile.

*

*@returnResponse

*/

publicfunctionupdateProfile(Request$request)

{

if($request->user())

{

//$request->user()returnsaninstanceoftheauthenticateduser...

}

}

}

Thirdly,youmaytype-hinttheIlluminate\Contracts\Auth\Authenticatablecontract.Thistype-hintmaybeaddedtoacontrollerconstructor,controllermethod,oranyotherconstructorofaclassresolvedbytheservicecontainer:

<?phpnamespaceApp\Http\Controllers;

useIlluminate\Routing\Controller;

useIlluminate\Contracts\Auth\Authenticatable;

classProfileControllerextendsController{

/**

*Updatetheuser'sprofile.

AuthenticationEvents

RetrievingTheAuthenticatedUser

*

*@returnResponse

*/

publicfunctionupdateProfile(Authenticatable$user)

{

//$userisaninstanceoftheauthenticateduser...

}

}

Routemiddlewarecanbeusedtoallowonlyauthenticateduserstoaccessagivenroute.Laravelprovidestheauthmiddlewarebydefault,anditisdefinedinapp\Http\Middleware\Authenticate.php.Allyouneedtodoisattachittoaroutedefinition:

//WithARouteClosure...

Route::get('profile',['middleware'=>'auth',function()

{

//Onlyauthenticatedusersmayenter...

}]);

//WithAController...

Route::get('profile',['middleware'=>'auth','uses'=>'ProfileController@show']);

HTTPBasicAuthenticationprovidesaquickwaytoauthenticateusersofyourapplicationwithoutsettingupadedicated"login"page.Togetstarted,attachtheauth.basicmiddlewaretoyourroute:

Route::get('profile',['middleware'=>'auth.basic',function()

{

//Onlyauthenticatedusersmayenter...

}]);

Bydefault,thebasicmiddlewarewillusetheemailcolumnontheuserrecordasthe"username".

YoumayalsouseHTTPBasicAuthenticationwithoutsettingauseridentifiercookieinthesession,whichisparticularlyusefulforAPIauthentication.Todoso,defineamiddlewarethatcallstheonceBasicmethod:

publicfunctionhandle($request,Closure$next)

{

returnAuth::onceBasic()?:$next($request);

}

IfyouareusingPHPFastCGI,HTTPBasicauthenticationmaynotworkcorrectlyoutofthebox.Thefollowinglinesshouldbeaddedtoyour.htaccessfile:

RewriteCond%{HTTP:Authorization}^(.+)$

RewriteRule.*-[E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

ProtectingRoutes

HTTPBasicAuthentication

ProtectingARouteWithHTTPBasic

SettingUpAStatelessHTTPBasicFilter

Mostwebapplicationsprovideawayforuserstoresettheirforgottenpasswords.Ratherthanforcingyoutore-implementthisoneachapplication,Laravelprovidesconvenientmethodsforsendingpasswordremindersandperformingpasswordresets.

Togetstarted,verifythatyourUsermodelimplementstheIlluminate\Contracts\Auth\CanResetPasswordcontract.Ofcourse,theUsermodelincludedwiththeframeworkalreadyimplementsthisinterface,andusestheIlluminate\Auth\Passwords\CanResetPasswordtraittoincludethemethodsneededtoimplementtheinterface.

Next,atablemustbecreatedtostorethepasswordresettokens.ThemigrationforthistableisincludedwithLaraveloutofthebox,andresidesinthedatabase/migrationsdirectory.Soallyouneedtodoismigrate:

phpartisanmigrate

LaravelalsoincludesanAuth\PasswordControllerthatcontainsthelogicnecessarytoresetuserpasswords.We'veevenprovidedviewstogetyoustarted!Theviewsarelocatedintheresources/views/authdirectory.Youarefreetomodifytheseviewsasyouwishtosuityourownapplication'sdesign.

Youruserwillreceiveane-mailwithalinkthatpointstothegetResetmethodofthePasswordController.Thismethodwillrenderthepasswordresetformandallowuserstoresettheirpasswords.Afterthepasswordisreset,theuserwillautomaticallybeloggedintotheapplicationandredirectedto/home.Youcancustomizethepost-resetredirectlocationbydefiningaredirectTopropertyonthePasswordController:

protected$redirectTo='/dashboard';

Note:Bydefault,passwordresettokensexpireafteronehour.Youmaychangethisviathereminder.expireoptionofyourconfig/auth.phpfile.

Inadditiontotypical,formbasedauthentication,Laravelalsoprovidesasimple,convenientwaytoauthenticatewithOAuthprovidersusingLaravelSocialite.SocialitecurrentlysupportsauthenticationwithFacebook,Twitter,Google,andGitHub.

TogetstartedwithSocialite,includethepackageinyourcomposer.jsonfile:

"laravel/socialite":"~2.0"

Next,registertheLaravel\Socialite\SocialiteServiceProviderinyourconfig/app.phpconfigurationfile.Youmayalsoregisterafacade:

'Socialize'=>'Laravel\Socialite\Facades\Socialite',

PasswordReminders&Reset

Model&Table

GeneratingTheReminderTableMigration

PasswordReminderController

SocialAuthentication

YouwillneedtoaddcredentialsfortheOAuthservicesyourapplicationutilizes.Thesecredentialsshouldbeplacedinyourconfig/services.phpconfigurationfile,andshouldusethekeyfacebook,twitter,google,orgithub,dependingontheprovidersyourapplicationrequires.Forexample:

'github'=>[

'client_id'=>'your-github-app-id',

'client_secret'=>'your-github-app-secret',

'redirect'=>'http://your-callback-url',

],

Next,youarereadytoauthenticateusers!Youwillneedtworoutes:oneforredirectingtheusertotheOAuthprovider,andanotherforreceivingthecallbackfromtheproviderafterauthentication.Here'sanexampleusingtheSocializefacade:

publicfunctionredirectToProvider()

{

returnSocialize::with('github')->redirect();

}

publicfunctionhandleProviderCallback()

{

$user=Socialize::with('github')->user();

//$user->token;

}

TheredirectmethodtakescareofsendingtheusertotheOAuthprovider,whiletheusermethodwillreadtheincomingrequestandretrievetheuser'sinformationfromtheprovider.Beforeredirectingtheuser,youmayalsoset"scopes"ontherequest:

returnSocialize::with('github')->scopes(['scope1','scope2'])->redirect();

Onceyouhaveauserinstance,youcangrabafewmoredetailsabouttheuser:

$user=Socialize::with('github')->user();

//OAuthTwoProviders

$token=$user->token;

//OAuthOneProviders

$token=$user->token;

$tokenSecret=$user->tokenSecret;

//AllProviders

$user->getNickname();

$user->getName();

$user->getEmail();

$user->getAvatar();

RetrievingUserDetails

IntroductionConfigurationSubscribingToAPlanNoCardUpFrontSwappingSubscriptionsSubscriptionQuantityCancellingASubscriptionResumingASubscriptionCheckingSubscriptionStatusHandlingFailedPaymentsHandlingOtherStripeWebhooksInvoices

LaravelCashierprovidesanexpressive,fluentinterfacetoStripe'ssubscriptionbillingservices.Ithandlesalmostalloftheboilerplatesubscriptionbillingcodeyouaredreadingwriting.Inadditiontobasicsubscriptionmanagement,Cashiercanhandlecoupons,swappingsubscription,subscription"quantities",cancellationgraceperiods,andevengenerateinvoicePDFs.

First,addtheCashierpackagetoyourcomposer.jsonfile:

"laravel/cashier":"~3.0"

Next,registertheLaravel\Cashier\CashierServiceProviderinyourappconfigurationfile.

BeforeusingCashier,we'llneedtoaddseveralcolumnstoyourdatabase.Don'tworry,youcanusethecashier:tableArtisancommandtocreateamigrationtoaddthenecessarycolumn.Forexample,toaddthecolumntotheuserstableusephpartisancashier:tableusers.Oncethemigrationhasbeencreated,simplyrunthemigratecommand.

Next,addtheBillabletraitandappropriatedatemutatorstoyourmodeldefinition:

useLaravel\Cashier\Billable;

useLaravel\Cashier\Contracts\BillableasBillableContract;

classUserextendsEloquentimplementsBillableContract{

useBillable;

protected$dates=['trial_ends_at','subscription_ends_at'];

}

LaravelCashier

Introduction

Configuration

Composer

ServiceProvider

Migration

ModelSetup

Finally,setyourStripekeyinoneofyourbootstrapfilesorserviceproviders,suchastheAppServiceProvider:

User::setStripeKey('stripe-key');

Onceyouhaveamodelinstance,youcaneasilysubscribethatusertoagivenStripeplan:

$user=User::find(1);

$user->subscription('monthly')->create($creditCardToken);

Ifyouwouldliketoapplyacouponwhencreatingthesubscription,youmayusethewithCouponmethod:

$user->subscription('monthly')

->withCoupon('code')

->create($creditCardToken);

ThesubscriptionmethodwillautomaticallycreatetheStripesubscription,aswellasupdateyourdatabasewithStripecustomerIDandotherrelevantbillinginformation.IfyourplanhasatrialconfiguredinStripe,thetrialenddatewillalsoautomaticallybesetontheuserrecord.

IfyourplanhasatrialperiodthatisnotconfiguredinStripe,youmustsetthetrialenddatemanuallyaftersubscribing:

$user->trial_ends_at=Carbon::now()->addDays(14);

$user->save();

Ifyouwouldliketospecifyadditionalcustomerdetails,youmaydosobypassingthemassecondargumenttothecreatemethod:

$user->subscription('monthly')->create($creditCardToken,[

'email'=>$email,'description'=>'OurFirstCustomer'

]);

TolearnmoreabouttheadditionalfieldssupportedbyStripe,checkoutStripe'sdocumentationoncustomercreation.

Ifyourapplicationoffersafree-trialwithnocredit-cardupfront,setthecardUpFrontpropertyonyourmodeltofalse:

protected$cardUpFront=false;

Onaccountcreation,besuretosetthetrialenddateonthemodel:

StripeKey

SubscribingToAPlan

SpecifyingAdditionalUserDetails

NoCardUpFront

$user->trial_ends_at=Carbon::now()->addDays(14);

$user->save();

Toswapausertoanewsubscription,usetheswapmethod:

$user->subscription('premium')->swap();

Iftheuserisontrial,thetrialwillbemaintainedasnormal.Also,ifa"quantity"existsforthesubscription,thatquantitywillalsobemaintained.

Sometimessubscriptionsareaffectedby"quantity".Forexample,yourapplicationmightcharge$10permonthperuseronanaccount.Toeasilyincrementordecrementyoursubscriptionquantity,usetheincrementanddecrementmethods:

$user=User::find(1);

$user->subscription()->increment();

//Addfivetothesubscription'scurrentquantity...

$user->subscription()->increment(5);

$user->subscription->decrement();

//Subtractfivetothesubscription'scurrentquantity...

$user->subscription()->decrement(5);

Cancellingasubscriptionisawalkinthepark:

$user->subscription()->cancel();

Whenasubscriptioniscancelled,Cashierwillautomaticallysetthesubscription_ends_atcolumnonyourdatabase.Thiscolumnisusedtoknowwhenthesubscribedmethodshouldbeginreturningfalse.Forexample,ifacustomercancelsasubscriptiononMarch1st,butthesubscriptionwasnotscheduledtoenduntilMarch5th,thesubscribedmethodwillcontinuetoreturntrueuntilMarch5th.

Ifauserhascancelledtheirsubscriptionandyouwishtoresumeit,usetheresumemethod:

$user->subscription('monthly')->resume($creditCardToken);

Iftheusercancelsasubscriptionandthenresumesthatsubscriptionbeforethesubscriptionhasfullyexpired,theywillnotbebilledimmediately.Theirsubscriptionwillsimplybere-activated,andtheywillbebilledontheoriginalbillingcycle.

SwappingSubscriptions

SubscriptionQuantity

CancellingASubscription

ResumingASubscription

CheckingSubscriptionStatus

Toverifythatauserissubscribedtoyourapplication,usethesubscribedcommand:

if($user->subscribed())

{

//

}

Thesubscribedmethodmakesagreatcandidateforaroutemiddleware:

publicfunctionhandle($request,Closure$next)

{

if($request->user()&&!$request->user()->subscribed())

{

returnredirect('billing');

}

return$next($request);

}

Youmayalsodetermineiftheuserisstillwithintheirtrialperiod(ifapplicable)usingtheonTrialmethod:

if($user->onTrial())

{

//

}

Todetermineiftheuserwasonceanactivesubscriber,buthascancelledtheirsubscription,youmayusethecancelledmethod:

if($user->cancelled())

{

//

}

Youmayalsodetermineifauserhascancelledtheirsubscription,butarestillontheir"graceperiod"untilthesubscriptionfullyexpires.Forexample,ifausercancelsasubscriptiononMarch5ththatwasscheduledtoendonMarch10th,theuserisontheir"graceperiod"untilMarch10th.Notethatthesubscribedmethodstillreturnstrueduringthistime.

if($user->onGracePeriod())

{

//

}

TheeverSubscribedmethodmaybeusedtodetermineiftheuserhaseversubscribedtoaplaninyourapplication:

if($user->everSubscribed())

{

//

}

TheonPlanmethodmaybeusedtodetermineiftheuserissubscribedtoagivenplanbasedonitsID:

if($user->onPlan('monthly'))

{

//

}

Whatifacustomer'screditcardexpires?Noworries-CashierincludesaWebhookcontrollerthatcaneasilycancelthecustomer'ssubscriptionforyou.Justpointaroutetothecontroller:

Route::post('stripe/webhook','Laravel\Cashier\WebhookController@handleWebhook');

That'sit!Failedpaymentswillbecapturedandhandledbythecontroller.Thecontrollerwillcancelthecustomer'ssubscriptionafterthreefailedpaymentattempts.Thestripe/webhookURIinthisexampleisjustforexample.YouwillneedtoconfiguretheURIinyourStripesettings.

IfyouhaveadditionalStripewebhookeventsyouwouldliketohandle,simplyextendtheWebhookcontroller.YourmethodnamesshouldcorrespondtoCashier'sexpectedconvention,specifically,methodsshouldbeprefixedwithhandleandthenameoftheStripewebhookyouwishtohandle.Forexample,ifyouwishtohandletheinvoice.payment_succeededwebhook,youshouldaddahandleInvoicePaymentSucceededmethodtothecontroller.

classWebhookControllerextendsLaravel\Cashier\WebhookController{

publicfunctionhandleInvoicePaymentSucceeded($payload)

{

//HandleTheEvent

}

}

Note:Inadditiontoupdatingthesubscriptioninformationinyourdatabase,theWebhookcontrollerwillalsocancelthesubscriptionviatheStripeAPI.

Youcaneasilyretrieveanarrayofauser'sinvoicesusingtheinvoicesmethod:

$invoices=$user->invoices();

Whenlistingtheinvoicesforthecustomer,youmayusethesehelpermethodstodisplaytherelevantinvoiceinformation:

{{$invoice->id}}

{{$invoice->dateString()}}

{{$invoice->dollars()}}

UsethedownloadInvoicemethodtogenerateaPDFdownloadoftheinvoice.Yes,it'sreallythiseasy:

return$user->downloadInvoice($invoice->id,[

'vendor'=>'YourCompany',

'product'=>'YourProduct',

]);

HandlingFailedPayments

HandlingOtherStripeWebhooks

Invoices

ConfigurationCacheUsageIncrements&DecrementsCacheTagsDatabaseCache

LaravelprovidesaunifiedAPIforvariouscachingsystems.Thecacheconfigurationislocatedatconfig/cache.php.Inthisfileyoumayspecifywhichcachedriveryouwouldlikeusedbydefaultthroughoutyourapplication.LaravelsupportspopularcachingbackendslikeMemcachedandRedisoutofthebox.

Thecacheconfigurationfilealsocontainsvariousotheroptions,whicharedocumentedwithinthefile,somakesuretoreadovertheseoptions.Bydefault,Laravelisconfiguredtousethefilecachedriver,whichstorestheserialized,cachedobjectsinthefilesystem.Forlargerapplications,itisrecommendedthatyouuseanin-memorycachesuchasMemcachedorAPC.Youmayevenconfiguremultiplecacheconfigurationsforthesamedriver.

BeforeusingaRediscachewithLaravel,youwillneedtoinstallthepredis/predispackage(~1.0)viaComposer.

Cache::put('key','value',$minutes);

$expiresAt=Carbon::now()->addMinutes(10);

Cache::put('key','value',$expiresAt);

Cache::add('key','value',$minutes);

Theaddmethodwillreturntrueiftheitemisactuallyaddedtothecache.Otherwise,themethodwillreturnfalse.

if(Cache::has('key'))

{

//

}

Cache

Configuration

CacheUsage

StoringAnItemInTheCache

UsingCarbonObjectsToSetExpireTime

StoringAnItemInTheCacheIfItDoesn'tExist

CheckingForExistenceInCache

RetrievingAnItemFromTheCache

$value=Cache::get('key');

$value=Cache::get('key','default');

$value=Cache::get('key',function(){return'default';});

Cache::forever('key','value');

Sometimesyoumaywishtoretrieveanitemfromthecache,butalsostoreadefaultvalueiftherequesteditemdoesn'texist.YoumaydothisusingtheCache::remembermethod:

$value=Cache::remember('users',$minutes,function()

{

returnDB::table('users')->get();

});

Youmayalsocombinetherememberandforevermethods:

$value=Cache::rememberForever('users',function()

{

returnDB::table('users')->get();

});

Notethatallitemsstoredinthecacheareserialized,soyouarefreetostoreanytypeofdata.

Ifyouneedtoretrieveanitemfromthecacheandthendeleteit,youmayusethepullmethod:

$value=Cache::pull('key');

Cache::forget('key');

Alldriversexceptfileanddatabasesupporttheincrementanddecrementoperations:

Cache::increment('key');

Cache::increment('key',$amount);

RetrievingAnItemOrReturningADefaultValue

StoringAnItemInTheCachePermanently

PullingAnItemFromTheCache

RemovingAnItemFromTheCache

Increments&Decrements

IncrementingAValue

Cache::decrement('key');

Cache::decrement('key',$amount);

Note:Cachetagsarenotsupportedwhenusingthefileordatabasecachedrivers.Furthermore,whenusingmultipletagswithcachesthatarestored"forever",performancewillbebestwithadriversuchasmemcached,whichautomaticallypurgesstalerecords.

Cachetagsallowyoutotagrelateditemsinthecache,andthenflushallcachestaggedwithagivenname.Toaccessataggedcache,usethetagsmethod.

Youmaystoreataggedcachebypassinginanorderedlistoftagnamesasarguments,orasanorderedarrayoftagnames:

Cache::tags('people','authors')->put('John',$john,$minutes);

Cache::tags(array('people','artists'))->put('Anne',$anne,$minutes);

Youmayuseanycachestoragemethodincombinationwithtags,includingremember,forever,andrememberForever.Youmayalsoaccesscacheditemsfromthetaggedcache,aswellasusetheothercachemethodssuchasincrementanddecrement.

Toaccessataggedcache,passthesameorderedlistoftagsusedtosaveit.

$anne=Cache::tags('people','artists')->get('Anne');

$john=Cache::tags(array('people','authors'))->get('John');

Youmayflushallitemstaggedwithanameorlistofnames.Forexample,thisstatementwouldremoveallcachestaggedwitheitherpeople,authors,orboth.So,both"Anne"and"John"wouldberemovedfromthecache:

Cache::tags('people','authors')->flush();

Incontrast,thisstatementwouldremoveonlycachestaggedwithauthors,so"John"wouldberemoved,butnot"Anne".

Cache::tags('authors')->flush();

Whenusingthedatabasecachedriver,youwillneedtosetupatabletocontainthecacheitems.You'llfindanexampleSchemadeclarationforthetablebelow:

DecrementingAValue

CacheTags

AccessingATaggedCache

AccessingItemsInATaggedCache

DatabaseCache

Schema::create('cache',function($table)

{

$table->string('key')->unique();

$table->text('value');

$table->integer('expiration');

});

IntroductionBasicUsage

TheIlluminate\Support\Collectionclassprovidesafluent,convenientwrapperforworkingwitharraysofdata.Forexample,checkoutthefollowingcode.We'llusethecollecthelpertocreateanewcollectioninstancefromthearray:

$collection=collect(['taylor','abigail',null])->map(function($name)

{

returnstrtoupper($name);

})

->reject(function($name)

{

returnis_null($value);

});

Asyoucansee,theCollectionclassallowsyoutochainitsmethodstoperformfluentmappingandreducingoftheunderlyingarray.Ingeneral,everyCollectionmethodreturnsanentirelynewCollectioninstance.Todiginfurther,keepreading!

Asmentionedabove,thecollecthelperwillreturnanewIlluminate\Support\Collectioninstanceforthegivenarray.YoumayalsousethemakecommandontheCollectionclass:

$collection=collect([1,2,3]);

$collection=Collection::make([1,2,3]);

Ofcourse,collectionsofEloquentobjectsarealwaysreturnedasCollectioninstances;however,youshouldfeelfreetousetheCollectionclasswhereveritisconvenientforyourapplication.

Insteadoflistingallofthemethods(therearealot)theCollectionmakesavailable,checkouttheAPIdocumentationfortheclass!

Collections

Introduction

BasicUsage

CreatingCollections

ExploreTheCollection

IntroductionCreatingCommandsDispatchingCommandsQueuedCommandsCommandPipeline

TheLaravelcommandbusprovidesaconvenientmethodofencapsulatingtasksyourapplicationneedstoperformintosimple,easytounderstand"commands".Tohelpusunderstandthepurposeofcommands,let'spretendwearebuildinganapplicationthatallowsuserstopurchasepodcasts.

Whenauserpurchasesapodcast,thereareavarietyofthingsthatneedtohappen.Forexample,wemayneedtochargetheuser'screditcard,addarecordtoourdatabasethatrepresentsthepurchase,andsendaconfirmatione-mailofthepurchase.Perhapswealsoneedtoperformsomekindofvalidationastowhethertheuserisallowedtopurchasepodcasts.

Wecouldputallofthislogicinsideacontrollermethod;however,thishasseveraldisadvantages.ThefirstdisadvantageisthatourcontrollerprobablyhandlesseveralotherincomingHTTPactions,andincludingcomplicatedlogicineachcontrollermethodwillsoonbloatourcontrollerandmakeithardertoread.Secondly,itisdifficulttore-usethepurchasepodcastlogicoutsideofthecontrollercontext.Thirdly,itismoredifficulttounit-testthecommandaswemustalsogenerateastubHTTPrequestandmakeafullrequesttotheapplicationtotestthepurchasepodcastlogic.

Insteadofputtingthislogicinthecontroller,wemaychoosetoencapsulateitwithina"command"object,suchasaPurchasePodcastcommand.

TheArtisanCLIcangeneratenewcommandclassesusingthemake:commandcommand:

phpartisanmake:commandPurchasePodcast

Thenewlygeneratedclasswillbeplacedintheapp/Commandsdirectory.Bydefault,thecommandcontainstwomethods:theconstructorandthehandlemethod.Ofcourse,theconstructorallowsyoutopassanyrelevantobjectstothecommand,whilethehandlemethodexecutesthecommand.Forexample:

classPurchasePodcastextendsCommandimplementsSelfHandling{

protected$user,$podcast;

/**

*Createanewcommandinstance.

*

*@returnvoid

*/

publicfunction__construct(User$user,Podcast$podcast)

{

$this->user=$user;

$this->podcast=$podcast;

}

/**

*Executethecommand.

*

*@returnvoid

CommandBus

Introduction

CreatingCommands

*/

publicfunctionhandle()

{

//Handlethelogictopurchasethepodcast...

event(newPodcastWasPurchased($this->user,$this->podcast));

}

}

Thehandlemethodmayalsotype-hintdependencies,andtheywillbeautomaticallyinjectedbytheIoCcontainer.Forexample:

/**

*Executethecommand.

*

*@returnvoid

*/

publicfunctionhandle(BillingGateway$billing)

{

//Handlethelogictopurchasethepodcast...

}

So,oncewehavecreatedacommand,howdowedispatchit?Ofcourse,wecouldcallthehandlemethoddirectly;however,dispatchingthecommandthroughtheLaravel"commandbus"hasseveraladvantageswhichwewilldiscusslater.

Ifyouglanceatyourapplication'sbasecontroller,youwillseetheDispatchesCommandstrait.Thistraitallowsustocallthedispatchmethodfromanyofourcontrollers.Forexample:

publicfunctionpurchasePodcast($podcastId)

{

$this->dispatch(

newPurchasePodcast(Auth::user(),Podcast::findOrFail($podcastId))

);

}

ThecommandbuswilltakecareofexecutingthecommandandcallingtheIoCcontainertoinjectanyneededdependenciesintothehandlemethod.

YoumayaddtheIlluminate\Foundation\Bus\DispatchesCommandstraittoanyclassyouwish.Ifyouwouldliketoreceiveacommandbusinstancethroughtheconstructorofanyofyourclasses,youmaytype-hinttheIlluminate\Contracts\Bus\Dispatcherinterface.Finally,youmayalsousetheBusfacadetoquicklydispatchcommands:

Bus::dispatch(

newPurchasePodcast(Auth::user(),Podcast::findOrFail($podcastId))

);

ItisverycommontomapHTTPrequestvariablesintocommands.So,insteadofforcingyoutodothismanuallyforeachrequest,Laravelprovidessomehelpermethodstomakeitacinch.Let'stakealookatthedispatchFrommethodavailableontheDispatchesCommandstrait:

$this->dispatchFrom('Command\Class\Name',$request);

DispatchingCommands

MappingCommandPropertiesFromRequests

Thismethodwillexaminetheconstructorofthecommandclassitisgiven,andthenextractvariablesfromtheHTTPrequest(oranyotherArrayAccessobject)tofilltheneededconstructorparametersofthecommand.So,ifourcommandclassacceptsafirstNamevariableinitsconstructor,thecommandbuswillattempttopullthefirstNameparameterfromtheHTTPrequest.

YoumayalsopassanarrayasthethirdargumenttothedispatchFrommethod.Thisarraywillbeusedtofillanyconstructorparametersthatarenotavailableontherequest:

$this->dispatchFrom('Command\Class\Name',$request,[

'firstName'=>'Taylor',

]);

Thecommandbusisnotjustforsynchronousjobsthatrunduringthecurrentrequestcycle,butalsoservesastheprimarywaytobuildqueuedjobsinLaravel.So,howdoweinstructcommandbustoqueueourjobforbackgroundprocessinginsteadofrunningitsynchronously?It'seasy.Firstly,whengeneratinganewcommand,justaddthe--queuedflagtothecommand:

phpartisanmake:commandPurchasePodcast--queued

Asyouwillsee,thisaddsafewmorefeaturestothecommand,namelytheIlluminate\Contracts\Queue\ShouldBeQueuedinterfaceandtheSerializesModelstrait.Theseinstructthecommandbustoqueuethecommand,aswellasgracefullyserializeanddeserializeanyEloquentmodelsyourcommandstoresasproperties.

Ifyouwouldliketoconvertanexistingcommandintoaqueuedcommand,simplyimplementtheIlluminate\Contracts\Queue\ShouldBeQueuedinterfaceontheclassmanually.Itcontainsnomethods,andmerelyservesasa"markerinterface"forthedispatcher.

Then,justwriteyourcommandnormally.Whenyoudispatchittothebusthatbuswillautomaticallyqueuethecommandforbackgroundprocessing.Itdoesn'tgetanyeasierthanthat.

Formoreinformationoninteractingwithqueuedcommands,viewthefullqueuedocumentation.

Beforeacommandisdispatchedtoahandler,youmaypassitthroughotherclassesina"pipeline".CommandpipesworkjustlikeHTTPmiddleware,exceptforyourcommands!Forexample,acommandpipecouldwraptheentirecommandoperationwithinadatabasetransaction,orsimplylogitsexecution.

Toaddapipetoyourbus,callthepipeThroughmethodofthedispatcherfromyourApp\Providers\BusServiceProvider::bootmethod:

$dispatcher->pipeThrough(['UseDatabaseTransactions','LogCommand']);

Acommandpipeisdefinedwithahandlemethod,justlikeamiddleware:

classUseDatabaseTransactions{

publicfunctionhandle($command,$next)

{

returnDB::transaction(function()use($command,$next)

{

return$next($command);

QueuedCommands

CommandPipeline

}

}

}

CommandpipeclassesareresolvedthroughtheIoCcontainer,sofeelfreetotype-hintanydependenciesyouneedwithintheirconstructors.

YoumayevendefineaClosureasacommandpipe:

$dispatcher->pipeThrough([function($command,$next)

{

returnDB::transaction(function()use($command,$next)

{

return$next($command);

}

}]);

Managers&FactoriesCacheSessionAuthenticationIoCBasedExtension

LaravelhasseveralManagerclassesthatmanagethecreationofdriver-basedcomponents.Theseincludethecache,session,authentication,andqueuecomponents.Themanagerclassisresponsibleforcreatingaparticulardriverimplementationbasedontheapplication'sconfiguration.Forexample,theCacheManagerclasscancreateAPC,Memcached,File,andvariousotherimplementationsofcachedrivers.

Eachofthesemanagersincludesanextendmethodwhichmaybeusedtoeasilyinjectnewdriverresolutionfunctionalityintothemanager.We'llcovereachofthesemanagersbelow,withexamplesofhowtoinjectcustomdriversupportintoeachofthem.

Note:TakeamomenttoexplorethevariousManagerclassesthatshipwithLaravel,suchastheCacheManagerandSessionManager.ReadingthroughtheseclasseswillgiveyouamorethoroughunderstandingofhowLaravelworksunderthehood.AllmanagerclassesextendtheIlluminate\Support\Managerbaseclass,whichprovidessomehelpful,commonfunctionalityforeachmanager.

ToextendtheLaravelcachefacility,wewillusetheextendmethodontheCacheManager,whichisusedtobindacustomdriverresolvertothemanager,andiscommonacrossallmanagerclasses.Forexample,toregisteranewcachedrivernamed"mongo",wewoulddothefollowing:

Cache::extend('mongo',function($app)

{

returnCache::repository(newMongoStore);

});

Thefirstargumentpassedtotheextendmethodisthenameofthedriver.Thiswillcorrespondtoyourdriveroptionintheconfig/cache.phpconfigurationfile.ThesecondargumentisaClosurethatshouldreturnanIlluminate\Cache\Repositoryinstance.TheClosurewillbepassedan$appinstance,whichisaninstanceofIlluminate\Foundation\ApplicationandanIoCcontainer.

ThecalltoCache::extendcouldbedoneinthebootmethodofthedefaultApp\Providers\AppServiceProviderthatshipswithfreshLaravelapplications,oryoumaycreateyourownserviceprovidertohousetheextension-justdon'tforgettoregistertheproviderintheconfig/app.phpproviderarray.

Tocreateourcustomcachedriver,wefirstneedtoimplementtheIlluminate\Contracts\Cache\Storecontract.So,ourMongoDBcacheimplementationwouldlooksomethinglikethis:

classMongoStoreimplementsIlluminate\Contracts\Cache\Store{

publicfunctionget($key){}

publicfunctionput($key,$value,$minutes){}

publicfunctionincrement($key,$value=1){}

publicfunctiondecrement($key,$value=1){}

publicfunctionforever($key,$value){}

publicfunctionforget($key){}

ExtendingTheFramework

Managers&Factories

Cache

publicfunctionflush(){}

}

WejustneedtoimplementeachofthesemethodsusingaMongoDBconnection.Onceourimplementationiscomplete,wecanfinishourcustomdriverregistration:

Cache::extend('mongo',function($app)

{

returnCache::repository(newMongoStore);

});

Ifyou'rewonderingwheretoputyourcustomcachedrivercode,considermakingitavailableonPackagist!Or,youcouldcreateanExtensionsnamespacewithinyourappdirectory.However,keepinmindthatLaraveldoesnothavearigidapplicationstructureandyouarefreetoorganizeyourapplicationaccordingtoyourpreferences.

ExtendingLaravelwithacustomsessiondriverisjustaseasyasextendingthecachesystem.Again,wewillusetheextendmethodtoregisterourcustomcode:

Session::extend('mongo',function($app)

{

//ReturnimplementationofSessionHandlerInterface

});

YoushouldplaceyoursessionextensioncodeinthebootmethodofyourAppServiceProvider.

NotethatourcustomsessiondrivershouldimplementtheSessionHandlerInterface.Thisinterfacecontainsjustafewsimplemethodsweneedtoimplement.AstubbedMongoDBimplementationwouldlooksomethinglikethis:

classMongoHandlerimplementsSessionHandlerInterface{

publicfunctionopen($savePath,$sessionName){}

publicfunctionclose(){}

publicfunctionread($sessionId){}

publicfunctionwrite($sessionId,$data){}

publicfunctiondestroy($sessionId){}

publicfunctiongc($lifetime){}

}

SincethesemethodsarenotasreadilyunderstandableasthecacheStoreInterface,let'squicklycoverwhateachofthemethodsdo:

Theopenmethodwouldtypicallybeusedinfilebasedsessionstoresystems.SinceLaravelshipswithafilesessiondriver,youwillalmostneverneedtoputanythinginthismethod.Youcanleaveitasanemptystub.Itissimplyafactofpoorinterfacedesign(whichwe'lldiscusslater)thatPHPrequiresustoimplementthismethod.Theclosemethod,liketheopenmethod,canalsousuallybedisregarded.Formostdrivers,itisnotneeded.Thereadmethodshouldreturnthestringversionofthesessiondataassociatedwiththegiven$sessionId.Thereisnoneedtodoanyserializationorotherencodingwhenretrievingorstoringsessiondatainyourdriver,asLaravelwillperformtheserializationforyou.Thewritemethodshouldwritethegiven$datastringassociatedwiththe$sessionIdtosomepersistentstorage

Session

WhereToExtendTheSession

WritingTheSessionExtension

system,suchasMongoDB,Dynamo,etc.Thedestroymethodshouldremovethedataassociatedwiththe$sessionIdfrompersistentstorage.Thegcmethodshoulddestroyallsessiondatathatisolderthanthegiven$lifetime,whichisaUNIXtimestamp.Forself-expiringsystemslikeMemcachedandRedis,thismethodmaybeleftempty.

OncetheSessionHandlerInterfacehasbeenimplemented,wearereadytoregisteritwiththeSessionmanager:

Session::extend('mongo',function($app)

{

returnnewMongoHandler;

});

Oncethesessiondriverhasbeenregistered,wemayusethemongodriverinourconfig/session.phpconfigurationfile.

Note:Remember,ifyouwriteacustomsessionhandler,shareitonPackagist!

Authenticationmaybeextendedthesamewayasthecacheandsessionfacilities.Again,wewillusetheextendmethodwehavebecomefamiliarwith:

Auth::extend('riak',function($app)

{

//ReturnimplementationofIlluminate\Contracts\Auth\UserProvider

});

TheUserProviderimplementationsareonlyresponsibleforfetchingaIlluminate\Contracts\Auth\Authenticatableimplementationoutofapersistentstoragesystem,suchasMySQL,Riak,etc.ThesetwointerfacesallowtheLaravelauthenticationmechanismstocontinuefunctioningregardlessofhowtheuserdataisstoredorwhattypeofclassisusedtorepresentit.

Let'stakealookattheUserProvidercontract:

interfaceUserProvider{

publicfunctionretrieveById($identifier);

publicfunctionretrieveByToken($identifier,$token);

publicfunctionupdateRememberToken(Authenticatable$user,$token);

publicfunctionretrieveByCredentials(array$credentials);

publicfunctionvalidateCredentials(Authenticatable$user,array$credentials);

}

TheretrieveByIdfunctiontypicallyreceivesanumerickeyrepresentingtheuser,suchasanauto-incrementingIDfromaMySQLdatabase.TheAuthenticatableimplementationmatchingtheIDshouldberetrievedandreturnedbythemethod.

TheretrieveByTokenfunctionretrievesauserbytheirunique$identifierand"rememberme"$token,storedinafieldremember_token.Aswithwithpreviousmethod,theAuthenticatableimplementationshouldbereturned.

TheupdateRememberTokenmethodupdatesthe$userfieldremember_tokenwiththenew$token.Thenewtokencanbeeitherafreshtoken,assignedonsuccessfull"rememberme"loginattempt,oranullwhenuserisloggedout.

TheretrieveByCredentialsmethodreceivesthearrayofcredentialspassedtotheAuth::attemptmethodwhenattemptingtosignintoanapplication.Themethodshouldthen"query"theunderlyingpersistentstoragefortheusermatchingthosecredentials.Typically,thismethodwillrunaquerywitha"where"conditionon$credentials['username'].Thismethodshouldnotattempttodoanypasswordvalidationorauthentication.

Authentication

ThevalidateCredentialsmethodshouldcomparethegiven$userwiththe$credentialstoauthenticatetheuser.Forexample,thismethodmightcomparethe$user->getAuthPassword()stringtoaHash::makeof$credentials['password'].

NowthatwehaveexploredeachofthemethodsontheUserProvider,let'stakealookattheAuthenticatable.Remember,theprovidershouldreturnimplementationsofthisinterfacefromtheretrieveByIdandretrieveByCredentialsmethods:

interfaceAuthenticatable{

publicfunctiongetAuthIdentifier();

publicfunctiongetAuthPassword();

publicfunctiongetRememberToken();

publicfunctionsetRememberToken($value);

publicfunctiongetRememberTokenName();

}

Thisinterfaceissimple.ThegetAuthIdentifiermethodshouldreturnthe"primarykey"oftheuser.InaMySQLback-end,again,thiswouldbetheauto-incrementingprimarykey.ThegetAuthPasswordshouldreturntheuser'shashedpassword.ThisinterfaceallowstheauthenticationsystemtoworkwithanyUserclass,regardlessofwhatORMorstorageabstractionlayeryouareusing.Bydefault,LaravelincludesaUserclassintheappdirectorywhichimplementsthisinterface,soyoumayconsultthisclassforanimplementationexample.

Finally,oncewehaveimplementedtheUserProvider,wearereadytoregisterourextensionwiththeAuthfacade:

Auth::extend('riak',function($app)

{

returnnewRiakUserProvider($app['riak.connection']);

});

Afteryouhaveregisteredthedriverwiththeextendmethod,youswitchtothenewdriverinyourconfig/auth.phpconfigurationfile.

AlmosteveryserviceproviderincludedwiththeLaravelframeworkbindsobjectsintotheIoCcontainer.Youcanfindalistofyourapplication'sserviceprovidersintheconfig/app.phpconfigurationfile.Asyouhavetime,youshouldskimthrougheachoftheseprovider'ssourcecode.Bydoingso,youwillgainamuchbetterunderstandingofwhateachprovideraddstotheframework,aswellaswhatkeysareusedtobindvariousservicesintotheIoCcontainer.

Forexample,theHashServiceProviderbindsahashkeyintotheIoCcontainer,whichresolvesintoaIlluminate\Hashing\BcryptHasherinstance.YoucaneasilyextendandoverridethisclasswithinyourownapplicationbyoverridingthisIoCbinding.Forexample:

<?phpnamespaceApp\Providers;

classSnappyHashProviderextends\Illuminate\Hashing\HashServiceProvider{

publicfunctionboot()

{

$this->app->bindShared('hash',function()

{

returnnew\Snappy\Hashing\ScryptHasher;

});

parent::boot();

}

}

NotethatthisclassextendstheHashServiceProvider,notthedefaultServiceProviderbaseclass.Onceyouhave

IoCBasedExtension

extendedtheserviceprovider,swapouttheHashServiceProviderinyourconfig/app.phpconfigurationfilewiththenameofyourextendedprovider.

Thisisthegeneralmethodofextendinganycoreclassthatisboundinthecontainer.Essentiallyeverycoreclassisboundinthecontainerinthisfashion,andcanbeoverridden.Again,readingthroughtheincludedframeworkserviceproviderswillfamiliarizeyouwithwherevariousclassesareboundintothecontainer,andwhatkeystheyareboundby.ThisisagreatwaytolearnmoreabouthowLaravelisputtogether.

IntroductionInstallation&SetupUsageGulpExtensions

LaravelElixirprovidesaclean,fluentAPIfordefiningbasicGulptasksforyourLaravelapplication.ElixirsupportsseveralcommonCSSandJavaScriptpre-processors,andeventestingtools.

Ifyou'veeverbeenconfusedabouthowtogetstartedwithGulpandassetcompilation,youwillloveLaravelElixir!

BeforetriggeringElixir,youmustfirstensurethatNode.jsisinstalledonyourmachine.

node-v

Bydefault,LaravelHomesteadincludeseverythingyouneed;however,ifyouaren'tusingVagrant,thenyoucaneasilyinstallNodebyvisitingtheirdownloadpage.Don'tworry,it'squickandeasy!

Next,you'llwanttopullinGulpasaglobalNPMpackagelikeso:

npminstall--globalgulp

TheonlyremainingstepistoinstallElixir!WithanewinstallofLaravel,you'llfindapackage.jsonfileintheroot.Thinkofthislikeyourcomposer.jsonfile,exceptitdefinesNodedependenciesinsteadofPHP.Youmayinstallthedependenciesitreferencesbyrunning:

npminstall

Nowthatyou'veinstalledElixir,you'llbecompilingandconcatenatinginnotime!

elixir(function(mix){

mix.less("app.less");

LaravelElixir

Introduction

Installation&Setup

InstallingNode

Gulp

LaravelElixir

Usage

CompileLess

});

Intheexampleabove,ElixirassumesthatyourLessfilesarestoredinresources/assets/less.

elixir(function(mix){

mix.sass("app.sass");

});

ThisassumesthatyourSassfilesarestoredinresources/assets/sass.

elixir(function(mix){

mix.coffee();

});

ThisassumesthatyourCoffeeScriptfilesarestoredinresources/assets/coffee.

elixir(function(mix){

mix.less()

.coffee();

});

elixir(function(mix){

mix.phpUnit();

});

elixir(function(mix){

mix.phpSpec();

});

elixir(function(mix){

mix.styles([

"normalize.css",

"main.css"

]);

});

Pathspassedtothismethodarerelativetotheresources/cssdirectory.

elixir(function(mix){

CompileSass

CompileCoffeeScript

CompileAllLessandCoffeeScript

TriggerPHPUnitTests

TriggerPHPSpecTests

CombineStylesheets

CombineStylesheetsandSavetoaCustomDirectory

mix.styles([

"normalize.css",

"main.css"

],'public/build/css/everything.css');

});

elixir(function(mix){

mix.styles([

"normalize.css",

"main.css"

],'public/build/css/everything.css','public/css');

});

Thethirdargumenttoboththestylesandscriptsmethodsdeterminestherelativedirectoryforallpathspassedtothemethods.

elixir(function(mix){

mix.stylesIn("public/css");

});

elixir(function(mix){

mix.scripts([

"jquery.js",

"app.js"

]);

});

Again,thisassumesallpathsarerelativetotheresources/jsdirectory.

elixir(function(mix){

mix.scriptsIn("public/js/some/directory");

});

elixir(function(mix){

mix.scripts(['jquery.js','main.js'],'public/js/main.js')

.scripts(['forum.js','threads.js'],'public/js/forum.js');

});

elixir(function(mix){

mix.version("css/all.css");

});

Thiswillappendauniquehashtothefilename,allowingforcache-busting.Forexample,thegeneratedfilenamewilllook

CombineStylesheetsFromACustomBaseDirectory

CombineAllStylesinaDirectory

CombineScripts

CombineAllScriptsinaDirectory

CombineMultipleSetsofScripts

Version/HashAFile

somethinglike:all-16d570a7.css.

Withinyourviews,youmayusetheelixir()functiontoloadtheappropriatelyhashedasset.Here'sanexample:

<linkrel="stylesheet"href="{{elixir("css/all.css")}}">

Behindthescenes,theelixir()functionwilldeterminethenameofthehashedfilethatshouldbeincluded.Don'tyoufeeltheweightliftingoffyourshouldersalready?

elixir(function(mix){

mix.copy('vendor/foo/bar.css','public/css/bar.css');

});

elixir(function(mix){

mix.copy('vendor/package/views','resources/views');

});

Ofcourse,youmaychainalmostallofElixir'smethodstogethertobuildyourrecipe:

elixir(function(mix){

mix.less("app.less")

.coffee()

.phpUnit()

.version("css/bootstrap.css");

});

Nowthatyou'vetoldElixirwhichtaskstoexecute,youonlyneedtotriggerGulpfromthecommandline.

gulp

gulpwatch

gulptdd

Note:Alltaskswillassumeadevelopmentenvironment,andwillexcludeminification.Forproduction,usegulp--

CopyaFiletoaNewLocation

CopyanEntireDirectorytoaNewLocation

MethodChaining

Gulp

ExecuteAllRegisteredTasksOnce

WatchAssetsForChanges

WatchTestsAndPHPClassesforChanges

production.

YoucanevencreateyourownGulptasks,andhookthemintoElixir.ImaginethatyouwanttoaddafuntaskthatusestheTerminaltoverballynotifyyouwithsomemessage.Here'swhatthatmightlooklike:

vargulp=require("gulp");

varshell=require("gulp-shell");

varelixir=require("laravel-elixir");

elixir.extend("message",function(message){

gulp.task("say",function(){

gulp.src("").pipe(shell("say"+message));

});

returnthis.queueTask("say");

});

NoticethatweextendElixir'sAPIbypassingthekeythatwewillusewithinourGulpfile,aswellasacallbackfunctionthatwillcreatetheGulptask.

Ifyouwantyourcustomtasktobemonitored,thenregisterawatcheraswell.

this.registerWatcher("message","**/*.php");

Thislinesdesignatesthatwhenanyfilethatmatchestheregex,**/*.phpismodified,wewanttotriggerthemessagetask.

That'sit!YoumayeitherplacethisatthetopofyourGulpfile,orinsteadextractittoacustomtasksfile.Ifyouchoosethelatterapproach,simplyrequireitintoyourGulpfile,likeso:

require("./custom-tasks")

You'redone!Now,youcanmixitin.

elixir(function(mix){

mix.message("Tea,EarlGrey,Hot");

});

Withthisaddition,eachtimeyoutriggerGulp,Picardwillrequestsometea.

Extensions

IntroductionBasicUsage

LaravelprovidesfacilitiesforstrongAESencryptionviatheMcryptPHPextension.

$encrypted=Crypt::encrypt('secret');

Note:Besuretoseta16,24,or32characterrandomstringinthekeyoptionoftheconfig/app.phpfile.Otherwise,encryptedvalueswillnotbesecure.

$decrypted=Crypt::decrypt($encryptedValue);

Youmayalsosetthecipherandmodeusedbytheencrypter:

Crypt::setMode('ctr');

Crypt::setCipher($cipher);

Encryption

Introduction

BasicUsage

EncryptingAValue

DecryptingAValue

SettingTheCipher&Mode

ConfigurationHandlingErrorsHTTPExceptionsLogging

TheloggingfacilitiesforyourapplicationareconfiguredintheIlluminate\Foundation\Bootstrap\ConfigureLoggingbootstrapperclass.Thisclassutilizesthelogconfigurationoptionfromyourconfig/app.phpconfigurationfile.

Bydefault,theloggerisconfiguredtousedailylogfiles;however,youmaycustomizethisbehaviorasneeded.SinceLaravelusesthepopularMonologlogginglibrary,youcantakeadvantageofthevarietyofhandlersthatMonologoffers.

Forexample,ifyouwishtouseasinglelogfileinsteadofdailyfiles,youcanmakethefollowingchangetoyourconfig/app.phpconfigurationfile:

'log'=>'single'

Outofthebox,Laravelsupportedsingle,daily,andsyslogloggingmodes.However,youarefreetocustomizetheloggingforyourapplicationasyouwishbyoverridingtheConfigureLoggingbootstrapperclass.

Theamountoferrordetailyourapplicationdisplaysthroughthebrowseriscontrolledbytheapp.debugconfigurationoptioninyourconfig/app.phpconfigurationfile.Bydefault,thisconfigurationoptionissettorespecttheAPP_DEBUGenvironmentvariable,whichisstoredinyour.envfile.

Forlocaldevelopment,youshouldsettheAPP_DEBUGenvironmentvariabletotrue.Inyourproductionenvironment,thisvalueshouldalwaysbefalse.

AllexceptionsarehandledbytheApp\Exceptions\Handlerclass.Thisclasscontainstwomethods:reportandrender.

ThereportmethodisusedtologexceptionsorsendthemtoanexternalservicelikeBugSnag.Bydefault,thereportmethodsimplypassestheexceptiontothebaseimplementationontheparentclasswheretheexceptionislogged.However,youarefreetologexceptionshoweveryouwish.Ifyouneedtoreportdifferenttypesofexceptionsindifferentways,youmayusethePHPinstanceofcomparisonoperator:

/**

*Reportorloganexception.

*

*ThisisagreatspottosendexceptionstoSentry,Bugsnag,etc.

*

*@param\Exception$e

*@returnvoid

*/

publicfunctionreport(Exception$e)

{

if($einstanceofCustomException)

{

//

}

Errors&Logging

Configuration

ErrorDetail

HandlingErrors

returnparent::report($e);

}

TherendermethodisresponsibleforconvertingtheexceptionintoanHTTPresponsethatshouldbesentbacktothebrowser.Bydefault,theexceptionispassedtothebaseclasswhichgeneratesaresponseforyou.However,youarefreetochecktheexceptiontypeorreturnyourowncustomresponse.

ThedontReportpropertyoftheexceptionhandlercontainsanarrayofexceptiontypesthatwillnotbelogged.Bydefault,exceptionsresultingfrom404errorsarenotwrittentoyourlogfiles.Youmayaddotherexceptiontypestothisarrayasneeded.

SomeexceptionsdescribeHTTPerrorcodesfromtheserver.Forexample,thismaybea"pagenotfound"error(404),an"unauthorizederror"(401)orevenadevelopergenerated500error.Inordertoreturnsucharesponse,usethefollowing:

abort(404);

Optionally,youmayprovidearesponse:

abort(403,'Unauthorizedaction.');

Thismethodmaybeusedatanytimeduringtherequest'slifecycle.

Toreturnacustomviewforall404errors,createaresources/views/errors/404.blade.phpfile.Thisviewwillbeservedonall404errorsgeneratedbyyourapplication.

TheLaravelloggingfacilitiesprovideasimplelayerontopofthepowerfulMonologlibrary.Bydefault,Laravelisconfiguredtocreatedailylogfilesforyourapplicationwhicharestoredinthestorage/logsdirectory.Youmaywriteinformationtotheloglikeso:

Log::info('Thisissomeusefulinformation.');

Log::warning('Somethingcouldbegoingwrong.');

Log::error('Somethingisreallygoingwrong.');

TheloggerprovidesthesevenlogginglevelsdefinedinRFC5424:debug,info,notice,warning,error,critical,andalert.

Anarrayofcontextualdatamayalsobepassedtothelogmethods:

Log::info('Logmessage',['context'=>'Otherhelpfulinformation']);

Monologhasavarietyofadditionalhandlersyoumayuseforlogging.Ifneeded,youmayaccesstheunderlyingMonologinstancebeingusedbyLaravel:

HTTPExceptions

Custom404ErrorPage

Logging

$monolog=Log::getMonolog();

Youmayalsoregisteraneventtocatchallmessagespassedtothelog:

Log::listen(function($level,$message,$context)

{

//

});

RegisteringALogEventListener

BasicUsageQueuedEventHandlersEventSubscribers

TheLaraveleventfacilitiesprovidesasimpleobserverimplementation,allowingyoutosubscribeandlistenforeventsinyourapplication.Eventclassesaretypicallystoredintheapp/Eventsdirectory,whiletheirhandlersarestoredinapp/Handlers/Events.

YoucangenerateaneweventclassusingtheArtisanCLItool:

phpartisanmake:eventPodcastWasPurchased

TheEventServiceProviderincludedwithyourLaravelapplicationprovidesaconvenientplacetoregisteralleventhandlers.Thelistenpropertycontainsanarrayofallevents(keys)andtheirhandlers(values).Ofcourse,youmayaddasmanyeventstothisarrayasyourapplicationrequires.Forexample,let'saddourPodcastWasPurchasedevent:

/**

*Theeventhandlermappingsfortheapplication.

*

*@vararray

*/

protected$listen=[

'App\Events\PodcastWasPurchased'=>[

'App\Handlers\Events\EmailPurchaseConfirmation@handle',

],

];

Togenerateahandlerforanevent,usethehandler:eventArtisanCLIcommand:

phpartisanhandler:eventEmailPurchaseConfirmation--event=PodcastWasPurchased

Ofcourse,manuallyrunningthemake:eventandhandler:eventcommandseachtimeyouneedahandleroreventiscumbersome.Instead,simplyaddhandlersandeventstoyourEventServiceProviderandusetheevent:generatecommand.ThiscommandwillgenerateanyeventsorhandlersthatarelistedinyourEventServiceProvider:

phpartisanevent:generate

NowwearereadytofireoureventusingtheEventfacade:

$response=Event::fire(newPodcastWasPurchased($podcast));

Thefiremethodreturnsanarrayofresponsesthatyoucanusetocontrolwhathappensnextinyourapplication.

Events

BasicUsage

SubscribingToAnEvent

FiringAnEvent

Youmayalsousetheeventhelpertofireanevent:

event(newPodcastWasPurchased($podcast));

Youcanevenlistentoeventswithoutcreatingaseparatehandlerclassatall.Forexample,inthebootmethodofyourEventServiceProvider,youcoulddothefollowing:

Event::listen('App\Events\PodcastWasPurchased',function($event)

{

//Handletheevent...

});

Sometimes,youmaywishtostopthepropagationofaneventtootherlisteners.Youmaydosousingbyreturningfalsefromyourhandler:

Event::listen('App\Events\PodcastWasPurchased',function($event)

{

//Handletheevent...

returnfalse;

});

Needtoqueueaneventhandler?Itcouldn'tbeanyeasier.Whengeneratingthehandler,simplyusethe--queuedflag:

phpartisanhandler:eventSendPurchaseConfirmation--event=PodcastWasPurchased--queued

ThiswillgenerateahandlerclassthatimplementstheIlluminate\Contracts\Queue\ShouldBeQueuedinterface.That'sit!Nowwhenthishandleriscalledforanevent,itwillbequeuedautomaticallybytheeventdispatcher.

Ifnoexceptionsarethrownwhenthehandlerisexecutedbythequeue,thequeuedjobwillbedeletedautomaticallyafterithasprocessed.Ifyouneedtoaccessthequeuedjob'sdeleteandreleasemethodsmanually,youmaydoso.TheIlluminate\Queue\InteractsWithQueuetrait,whichisincludedbydefaultonqueuedhandlers,givesyouaccesstothesemethods:

publicfunctionhandle(PodcastWasPurchased$event)

{

if(true)

{

$this->release(30);

}

}

Ifyouhaveanexistinghandlerthatyouwouldliketoconverttoaqueuedhandler,simplyaddtheShouldBeQueuedinterfacetotheclassmanually.

ClosureListeners

StoppingThePropagationOfAnEvent

QueuedEventHandlers

EventSubscribers

Eventsubscribersareclassesthatmaysubscribetomultipleeventsfromwithintheclassitself.Subscribersshoulddefineasubscribemethod,whichwillbepassedaneventdispatcherinstance:

classUserEventHandler{

/**

*Handleuserloginevents.

*/

publicfunctiononUserLogin($event)

{

//

}

/**

*Handleuserlogoutevents.

*/

publicfunctiononUserLogout($event)

{

//

}

/**

*Registerthelistenersforthesubscriber.

*

*@paramIlluminate\Events\Dispatcher$events

*@returnarray

*/

publicfunctionsubscribe($events)

{

$events->listen('App\Events\UserLoggedIn','UserEventHandler@onUserLogin');

$events->listen('App\Events\UserLoggedOut','UserEventHandler@onUserLogout');

}

}

Oncethesubscriberhasbeendefined,itmayberegisteredwiththeEventclass.

$subscriber=newUserEventHandler;

Event::subscribe($subscriber);

YoumayalsousetheLaravelIoCcontainertoresolveyoursubscriber.Todoso,simplypassthenameofyoursubscribertothesubscribemethod:

Event::subscribe('UserEventHandler');

DefiningAnEventSubscriber

RegisteringAnEventSubscriber

IntroductionConfigurationBasicUsage

LaravelprovidesawonderfulfilesystemabstractionthankstotheFlysystemPHPpackagebyFrankdeJonge.TheLaravelFlysystemintegrationprovidessimpletousedriversforworkingwithlocalfilesystems,AmazonS3,andRackspaceCloudStorage.Evenbetter,it'samazinglysimpletoswitchbetweenthesestorageoptionsastheAPIremainsthesameforeachsystem!

Thefilesystemconfigurationfileislocatedatconfig/filesystems.php.Withinthisfileyoumayconfigureallofyour"disks".Eachdiskrepresentsaparticularstoragedriverandstoragelocation.Exampleconfigurationsforeachsupporteddriverisincludedintheconfigurationfile.So,simplymodifytheconfigurationtoreflectyourstoragepreferencesandcredentials!

BeforeusingtheS3orRackspacedrivers,youwillneedtoinstalltheappropriatepackageviaComposer:

AmazonS3:league/flysystem-aws-s3-v2~1.0Rackspace:league/flysystem-rackspace~1.0

Ofcourse,youmayconfigureasmanydisksasyoulike,andmayevenhavemultipledisksthatusethesamedriver.

Whenusingthelocaldriver,notethatallfileoperationsarerelativetotherootdirectorydefinedinyourconfigurationfile.Bydefault,thisvalueissettothestorage/appdirectory.Therefore,thefollowingmethodwouldstoreafileinstorage/app/file.txt:

Storage::disk('local')->put('file.txt','Contents');

TheStoragefacademaybeusedtointeractwithanyofyourconfigureddisks.Alternatively,youmaytype-hinttheIlluminate\Contracts\Filesystem\FactorycontractonanyclassthatisresolvedviatheIoCcontainer.

$disk=Storage::disk('s3');

$disk=Storage::disk('local');

$exists=Storage::disk('s3')->exists('file.jpg');

Filesystem/CloudStorage

Introduction

Configuration

BasicUsage

RetrievingAParticularDisk

DeterminingIfAFileExists

CallingMethodsOnTheDefaultDisk

if(Storage::exists('file.jpg'))

{

//

}

$contents=Storage::get('file.jpg');

Storage::put('file.jpg',$contents);

Storage::prepend('file.log','PrependedText');

Storage::append('file.log','AppendedText');

Storage::delete('file.jpg');

Storage::delete(['file1.jpg','file2.jpg']);

Storage::copy('old/file1.jpg','new/file1.jpg');

Storage::move('old/file1.jpg','new/file1.jpg');

$size=Storage::size('file1.jpg');

$time=Storage::lastModified('file1.jpg');

RetrievingAFile'sContents

SettingAFile'sContents

PrependToAFile

AppendToAFile

DeleteAFile

CopyAFileToANewLocation

MoveAFileToANewLocation

GetFileSize

GetTheLastModificationTime(UNIX)

GetAllFilesWithinADirectory

$files=Storage::files($directory);

//Recursive...

$files=Storage::allFiles($directory);

$directories=Storage::directories($directory);

//Recursive...

$directories=Storage::allDirectories($directory);

Storage::makeDirectory($directory);

Storage::deleteDirectory($directory);

GetAllDirectoriesWithinADirectory

CreateADirectory

DeleteADirectory

IntroductionBasicUsage

TheLaravelHashfacadeprovidessecureBcrypthashingforstoringuserpasswords.IfyouareusingtheAuthControllercontrollerthatisincludedwithyourLaravelapplication,itwillbetakecareofverifyingtheBcryptpasswordagainsttheun-hashedversionprovidedbytheuser.

Likewise,theuserRegistrarservicethatshipswithLaravelmakestheproperbcryptfunctioncalltohashstoredpasswords.

$password=Hash::make('secret');

Youmayalsousethebcrypthelperfunction:

$password=bcrypt('secret');

if(Hash::check('secret',$hashedPassword))

{

//Thepasswordsmatch...

}

if(Hash::needsRehash($hashed))

{

$hashed=Hash::make('secret');

}

Hashing

Introduction

BasicUsage

HashingAPasswordUsingBcrypt

VerifyingAPasswordAgainstAHash

CheckingIfAPasswordNeedsToBeRehashed

ArraysPathsStringsURLsMiscellaneous

Thearray_addfunctionaddsagivenkey/valuepairtothearrayifthegivenkeydoesn'talreadyexistinthearray.

$array=array('foo'=>'bar');

$array=array_add($array,'key','value');

Thearray_dividefunctionreturnstwoarrays,onecontainingthekeys,andtheothercontainingthevaluesoftheoriginalarray.

$array=array('foo'=>'bar');

list($keys,$values)=array_divide($array);

Thearray_dotfunctionflattensamulti-dimensionalarrayintoasinglelevelarraythatuses"dot"notationtoindicatedepth.

$array=array('foo'=>array('bar'=>'baz'));

$array=array_dot($array);

//array('foo.bar'=>'baz');

Thearray_exceptmethodremovesthegivenkey/valuepairsfromthearray.

$array=array_except($array,array('keys','to','remove'));

Thearray_fetchmethodreturnsaflattenedarraycontainingtheselectednestedelement.

$array=array(

array('developer'=>array('name'=>'Taylor')),

array('developer'=>array('name'=>'Dayle')),

);

HelperFunctions

Arrays

array_add

array_divide

array_dot

array_except

array_fetch

$array=array_fetch($array,'developer.name');

//array('Taylor','Dayle');

Thearray_firstmethodreturnsthefirstelementofanarraypassingagiventruthtest.

$array=array(100,200,300);

$value=array_first($array,function($key,$value)

{

return$value>=150;

});

Adefaultvaluemayalsobepassedasthethirdparameter:

$value=array_first($array,$callback,$default);

Thearray_lastmethodreturnsthelastelementofanarraypassingagiventruthtest.

$array=array(350,400,500,300,200,100);

$value=array_last($array,function($key,$value)

{

return$value>350;

});

//500

Adefaultvaluemayalsobepassedasthethirdparameter:

$value=array_last($array,$callback,$default);

Thearray_flattenmethodwillflattenamulti-dimensionalarrayintoasinglelevel.

$array=array('name'=>'Joe','languages'=>array('PHP','Ruby'));

$array=array_flatten($array);

//array('Joe','PHP','Ruby');

Thearray_forgetmethodwillremoveagivenkey/valuepairfromadeeplynestedarrayusing"dot"notation.

$array=array('names'=>array('joe'=>array('programmer')));

array_forget($array,'names.joe');

array_first

array_last

array_flatten

array_forget

array_get

Thearray_getmethodwillretrieveagivenvaluefromadeeplynestedarrayusing"dot"notation.

$array=array('names'=>array('joe'=>array('programmer')));

$value=array_get($array,'names.joe');

$value=array_get($array,'names.john','default');

Note:Wantsomethinglikearray_getbutforobjectsinstead?Useobject_get.

Thearray_onlymethodwillreturnonlythespecifiedkey/valuepairsfromthearray.

$array=array('name'=>'Joe','age'=>27,'votes'=>1);

$array=array_only($array,array('name','votes'));

Thearray_pluckmethodwillpluckalistofthegivenkey/valuepairsfromthearray.

$array=array(array('name'=>'Taylor'),array('name'=>'Dayle'));

$array=array_pluck($array,'name');

//array('Taylor','Dayle');

Thearray_pullmethodwillreturnagivenkey/valuepairfromthearray,aswellasremoveit.

$array=array('name'=>'Taylor','age'=>27);

$name=array_pull($array,'name');

Thearray_setmethodwillsetavaluewithinadeeplynestedarrayusing"dot"notation.

$array=array('names'=>array('programmer'=>'Joe'));

array_set($array,'names.editor','Taylor');

Thearray_sortmethodsortsthearraybytheresultsofthegivenClosure.

$array=array(

array('name'=>'Jill'),

array('name'=>'Barry'),

);

$array=array_values(array_sort($array,function($value)

{

return$value['name'];

}));

array_only

array_pluck

array_pull

array_set

array_sort

FilterthearrayusingthegivenClosure.

$array=array(100,'200',300,'400',500);

$array=array_where($array,function($key,$value)

{

returnis_string($value);

});

//Array([1]=>200[3]=>400)

Returnthefirstelementinthearray.UsefulformethodchaininginPHP5.3.x.

$first=head($this->returnsArray('foo'));

Returnthelastelementinthearray.Usefulformethodchaining.

$last=last($this->returnsArray('foo'));

Getthefullyqualifiedpathtotheappdirectory.

$path=app_path();

Getthefullyqualifiedpathtotherootoftheapplicationinstall.

Getthefullyqualifiedpathtothepublicdirectory.

Getthefullyqualifiedpathtothestoragedirectory.

ConvertthegivenstringtocamelCase.

array_where

head

last

Paths

app_path

base_path

public_path

storage_path

Strings

camel_case

$camel=camel_case('foo_bar');

//fooBar

Gettheclassnameofthegivenclass,withoutanynamespacenames.

$class=class_basename('Foo\Bar\Baz');

//Baz

Runhtmlentitiesoverthegivenstring,withUTF-8support.

$entities=e('<html>foo</html>');

Determineifthegivenhaystackendswithagivenneedle.

$value=ends_with('Thisismyname','name');

Convertthegivenstringtosnake_case.

$snake=snake_case('fooBar');

//foo_bar

Limitthenumberofcharactersinastring.

str_limit($value,$limit=100,$end='...')

Example:

$value=str_limit('ThePHPframeworkforwebartisans.',7);

//ThePHP...

Determineifthegivenhaystackbeginswiththegivenneedle.

$value=starts_with('Thisismyname','This');

class_basename

e

ends_with

snake_case

str_limit

starts_with

Determineifthegivenhaystackcontainsthegivenneedle.

$value=str_contains('Thisismyname','my');

Addasingleinstanceofthegivenneedletothehaystack.Removeanyextrainstances.

$string=str_finish('this/string','/');

//this/string/

Determineifagivenstringmatchesagivenpattern.Asterisksmaybeusedtoindicatewildcards.

$value=str_is('foo*','foobar');

Convertastringtoitspluralform(Englishonly).

$plural=str_plural('car');

Generatearandomstringofthegivenlength.

$string=str_random(40);

Convertastringtoitssingularform(Englishonly).

$singular=str_singular('cars');

GenerateaURLfriendly"slug"fromagivenstring.

str_slug($title,$separator);

Example:

$title=str_slug("Laravel5Framework","-");

str_contains

str_finish

str_is

str_plural

str_random

str_singular

str_slug

//laravel-5-framework

ConvertthegivenstringtoStudlyCase.

$value=studly_case('foo_bar');

//FooBar

Translateagivenlanguageline.AliasofLang::get.

$value=trans('validation.required'):

Translateagivenlanguagelinewithinflection.AliasofLang::choice.

$value=trans_choice('foo.bar',$count);

GenerateaURLforagivencontrolleraction.

$url=action('HomeController@getIndex',$params);

GenerateaURLforagivennamedroute.

$url=route('routeName',$params);

GenerateaURLforanasset.

$url=asset('img/photo.jpg');

GenerateaHTMLlinktothegivenURL.

echolink_to('foo/bar',$title,$attributes=array(),$secure=null);

studly_case

trans

trans_choice

URLs

action

route

asset

link_to

GenerateaHTMLlinktothegivenasset.

echolink_to_asset('foo/bar.zip',$title,$attributes=array(),$secure=null);

GenerateaHTMLlinktothegivenroute.

echolink_to_route('route.name',$title,$parameters=array(),$attributes=array());

GenerateaHTMLlinktothegivencontrolleraction.

echolink_to_action('HomeController@getIndex',$title,$parameters=array(),$attributes=array());

GenerateaHTMLlinktothegivenassetusingHTTPS.

echosecure_asset('foo/bar.zip',$title,$attributes=array());

GenerateafullyqualifiedURLtoagivenpathusingHTTPS.

echosecure_url('foo/bar',$parameters=array());

GenerateafullyqualifiedURLtothegivenpath.

echourl('foo/bar',$parameters=array(),$secure=null);

GetthevalueofthecurrentCSRFtoken.

$token=csrf_token();

link_to_asset

link_to_route

link_to_action

secure_asset

secure_url

url

Miscellaneous

csrf_token

dd

Dumpthegivenvariableandendexecutionofthescript.

dd($value);

IfthegivenvalueisaClosure,returnthevaluereturnedbytheClosure.Otherwise,returnthevalue.

$value=value(function(){return'bar';});

Returnthegivenobject.UsefulformethodchainingconstructorsinPHP5.3.x.

$value=with(newFoo)->doWork();

value

with

IntroductionLanguageFilesBasicUsagePluralizationValidationLocalizationOverridingPackageLanguageFiles

TheLaravelLangfacadeprovidesaconvenientwayofretrievingstringsinvariouslanguages,allowingyoutoeasilysupportmultiplelanguageswithinyourapplication.

Languagestringsarestoredinfileswithintheresources/langdirectory.Withinthisdirectorythereshouldbeasubdirectoryforeachlanguagesupportedbytheapplication.

/resources

/lang

/en

messages.php

/es

messages.php

Languagefilessimplyreturnanarrayofkeyedstrings.Forexample:

<?php

returnarray(

'welcome'=>'Welcometoourapplication'

);

Thedefaultlanguageforyourapplicationisstoredintheconfig/app.phpconfigurationfile.YoumaychangetheactivelanguageatanytimeusingtheApp::setLocalemethod:

App::setLocale('es');

Youmayalsoconfigurea"fallbacklanguage",whichwillbeusedwhentheactivelanguagedoesnotcontainagivenlanguageline.Likethedefaultlanguage,thefallbacklanguageisalsoconfiguredintheconfig/app.phpconfigurationfile:

'fallback_locale'=>'en',

Localization

Introduction

LanguageFiles

ExampleLanguageFile

ChangingTheDefaultLanguageAtRuntime

SettingTheFallbackLanguage

echoLang::get('messages.welcome');

Thefirstsegmentofthestringpassedtothegetmethodisthenameofthelanguagefile,andthesecondisthenameofthelinethatshouldberetrieved.

Note:Ifalanguagelinedoesnotexist,thekeywillbereturnedbythegetmethod.

Youmayalsousethetranshelperfunction,whichisanaliasfortheLang::getmethod.

echotrans('messages.welcome');

Youmayalsodefineplace-holdersinyourlanguagelines:

'welcome'=>'Welcome,:name',

Then,passasecondargumentofreplacementstotheLang::getmethod:

echoLang::get('messages.welcome',array('name'=>'Dayle'));

if(Lang::has('messages.welcome'))

{

//

}

Pluralizationisacomplexproblem,asdifferentlanguageshaveavarietyofcomplexrulesforpluralization.Youmayeasilymanagethisinyourlanguagefiles.Byusinga"pipe"character,youmayseparatethesingularandpluralformsofastring:

'apples'=>'Thereisoneapple|Therearemanyapples',

YoumaythenusetheLang::choicemethodtoretrievetheline:

echoLang::choice('messages.apples',10);

Youmayalsosupplyalocaleargumenttospecifythelanguage.Forexample,ifyouwanttousetheRussian(ru)language:

echoLang::choice('товар|товара|товаров',$count,array(),'ru');

BasicUsage

RetrievingLinesFromALanguageFile

MakingReplacementsInLines

DetermineIfALanguageFileContainsALine

Pluralization

SincetheLaraveltranslatorispoweredbytheSymfonyTranslationcomponent,youmayalsocreatemoreexplicitpluralizationruleseasily:

'apples'=>'{0}Therearenone|[1,19]Therearesome|[20,Inf]Therearemany',

Forlocalizationforvalidationerrorsandmessages,takealookatthedocumentationonValidation.

Manypackagesshipwiththeirownlanguagelines.Insteadofhackingthepackage'scorefilestotweaktheselines,youmayoverridethembyplacingfilesintheresources/lang/packages/{locale}/{package}directory.So,forexample,ifyouneedtooverridetheEnglishlanguagelinesinmessages.phpforapackagenamedskyrim/hearthfire,youwouldplacealanguagefileat:resources/lang/packages/en/hearthfire/messages.php.Inthisfileyouwoulddefineonlythelanguagelinesyouwishtooverride.Anylanguagelinesyoudon'toverridewillstillbeloadedfromthepackage'slanguagefiles.

Validation

OverridingPackageLanguageFiles

ConfigurationBasicUsageEmbeddingInlineAttachmentsQueueingMailMail&LocalDevelopment

Laravelprovidesaclean,simpleAPIoverthepopularSwiftMailerlibrary.Themailconfigurationfileisconfig/mail.php,andcontainsoptionsallowingyoutochangeyourSMTPhost,port,andcredentials,aswellassetaglobalfromaddressforallmessagesdeliveredbythelibrary.YoumayuseanySMTPserveryouwish.IfyouwishtousethePHPmailfunctiontosendmail,youmaychangethedrivertomailintheconfigurationfile.Asendmaildriverisalsoavailable.

LaravelalsoincludesdriversfortheMailgunandMandrillHTTPAPIs.TheseAPIsareoftensimplerandquickerthantheSMTPservers.BothofthesedriversrequirethattheGuzzle4HTTPlibrarybeinstalledintoyourapplication.YoucanaddGuzzle4toyourprojectbyaddingthefollowinglinetoyourcomposer.jsonfile:

"guzzlehttp/guzzle":"~4.0"

TousetheMailgundriver,setthedriveroptiontomailguninyourconfig/mail.phpconfigurationfile.Next,createanconfig/services.phpconfigurationfileifonedoesnotalreadyexistforyourproject.Verifythatitcontainsthefollowingoptions:

'mailgun'=>array(

'domain'=>'your-mailgun-domain',

'secret'=>'your-mailgun-key',

),

TousetheMandrilldriver,setthedriveroptiontomandrillinyourconfig/mail.phpconfigurationfile.Next,createanconfig/services.phpconfigurationfileifonedoesnotalreadyexistforyourproject.Verifythatitcontainsthefollowingoptions:

'mandrill'=>array(

'secret'=>'your-mandrill-key',

),

Ifthedriveroptionofyourconfig/mail.phpconfigurationfileissettolog,alle-mailswillbewrittentoyourlogfiles,andwillnotactuallybesenttoanyoftherecipients.Thisisprimarilyusefulforquick,localdebuggingandcontentverification.

Mail

Configuration

APIDrivers

MailgunDriver

MandrillDriver

LogDriver

BasicUsage

TheMail::sendmethodmaybeusedtosendane-mailmessage:

Mail::send('emails.welcome',array('key'=>'value'),function($message)

{

$message->to('foo@example.com','JohnSmith')->subject('Welcome!');

});

Thefirstargumentpassedtothesendmethodisthenameoftheviewthatshouldbeusedasthee-mailbody.Thesecondisthedatatobepassedtotheview,oftenasanassociativearraywherethedataitemsareavailabletotheviewby$key.ThethirdisaClosureallowingyoutospecifyvariousoptionsonthee-mailmessage.

Note:A$messagevariableisalwayspassedtoe-mailviews,andallowstheinlineembeddingofattachments.So,itisbesttoavoidpassingamessagevariableinyourviewpayload.

YoumayalsospecifyaplaintextviewtouseinadditiontoanHTMLview:

Mail::send(array('html.view','text.view'),$data,$callback);

Or,youmayspecifyonlyonetypeofviewusingthehtmlortextkeys:

Mail::send(array('text'=>'view'),$data,$callback);

Youmayspecifyotheroptionsonthee-mailmessagesuchasanycarboncopiesorattachmentsaswell:

Mail::send('emails.welcome',$data,function($message)

{

$message->from('us@example.com','Laravel');

$message->to('foo@example.com')->cc('bar@example.com');

$message->attach($pathToFile);

});

Whenattachingfilestoamessage,youmayalsospecifyaMIMEtypeand/oradisplayname:

$message->attach($pathToFile,array('as'=>$display,'mime'=>$mime));

Ifyoujustneedtoe-mailasimplestringinsteadofanentireview,usetherawmethod:

Mail::raw('Texttoe-mail',function($message)

{

$message->from('us@example.com','Laravel');

$message->to('foo@example.com')->cc('bar@example.com');

});

Note:ThemessageinstancepassedtoaMail::sendClosureextendstheSwiftMailermessageclass,allowingyoutocallanymethodonthatclasstobuildyoure-mailmessages.

Embeddinginlineimagesintoyoure-mailsistypicallycumbersome;however,Laravelprovidesaconvenientwaytoattachimagestoyoure-mailsandretrievingtheappropriateCID.

EmbeddingInlineAttachments

<body>

Hereisanimage:

<imgsrc="<?phpecho$message->embed($pathToFile);?>">

</body>

<body>

Hereisanimagefromrawdata:

<imgsrc="<?phpecho$message->embedData($data,$name);?>">

</body>

Notethatthe$messagevariableisalwayspassedtoe-mailviewsbytheMailfacade.

Sincesendinge-mailmessagescandrasticallylengthentheresponsetimeofyourapplication,manydeveloperschoosetoqueuee-mailmessagesforbackgroundsending.Laravelmakesthiseasyusingitsbuilt-inunifiedqueueAPI.Toqueueamailmessage,simplyusethequeuemethodontheMailfacade:

Mail::queue('emails.welcome',$data,function($message)

{

$message->to('foo@example.com','JohnSmith')->subject('Welcome!');

});

Youmayalsospecifythenumberofsecondsyouwishtodelaythesendingofthemailmessageusingthelatermethod:

Mail::later(5,'emails.welcome',$data,function($message)

{

$message->to('foo@example.com','JohnSmith')->subject('Welcome!');

});

Ifyouwishtospecifyaspecificqueueor"tube"onwhichtopushthemessage,youmaydosousingthequeueOnandlaterOnmethods:

Mail::queueOn('queue-name','emails.welcome',$data,function($message)

{

$message->to('foo@example.com','JohnSmith')->subject('Welcome!');

});

Whendevelopinganapplicationthatsendse-mail,it'susuallydesirabletodisablethesendingofmessagesfromyourlocalordevelopmentenvironment.Todoso,youmayeithercalltheMail::pretendmethod,orsetthepretendoptionintheconfig/mail.phpconfigurationfiletotrue.Whenthemailerisinpretendmode,messageswillbewrittentoyourapplication'slogfilesinsteadofbeingsenttotherecipient.

Ifyouwouldliketoactuallyviewtheteste-mails,considerusingaservicelikeMailTrap.

EmbeddingAnImageInAnE-MailView

EmbeddingRawDataInAnE-MailView

QueueingMail

QueueingAMailMessage

Mail&LocalDevelopment

IntroductionViewsTranslationsConfigurationPublishingFileGroupsRouting

PackagesaretheprimarywayofaddingfunctionalitytoLaravel.PackagesmightbeanythingfromagreatwaytoworkwithdateslikeCarbon,oranentireBDDtestingframeworklikeBehat.

Ofcourse,therearedifferenttypesofpackages.Somepackagesarestand-alone,meaningtheyworkwithanyframework,notjustLaravel.BothCarbonandBehatareexamplesofstand-alonepackages.AnyofthesepackagesmaybeusedwithLaravelbysimplyrequestingtheminyourcomposer.jsonfile.

Ontheotherhand,otherpackagesarespecificallyintendedforusewithLaravel.Thesepackagesmayhaveroutes,controllers,views,andconfigurationspecificallyintendedtoenhanceaLaravelapplication.ThisguideprimarilycoversthedevelopmentofthosethatareLaravelspecific.

AllLaravelpackagesaredistributedviaPackagistandComposer,solearningaboutthesewonderfulPHPpackagedistributiontoolsisessential.

Yourpackage'sinternalstructureisentirelyuptoyou;however,typicallyeachpackagewillcontainoneormoreserviceproviders.TheserviceprovidercontainsanyIoCbindings,aswellasinstructionsastowherepackageconfiguration,views,andtranslationfilesarelocated.

Packageviewsaretypicallyreferencedusingadouble-colon"namespace"syntax:

returnview('package::view.name');

AllyouneedtodoistellLaravelwheretheviewsforagivennamespacearelocated.Forexample,ifyourpackageisnamed"courier",youmightaddthefollowingtoyourserviceprovider'sbootmethod:

publicfunctionboot()

{

$this->loadViewsFrom(__DIR__.'/path/to/views','courier');

}

Nowyoumayloadyourpackageviewsusingthefollowingsyntax:

returnview('courier::view.name');

WhenyouusetheloadViewsFrommethod,Laravelactuallyregisterstwolocationsforyourviews:oneintheapplication'sresources/views/vendordirectoryandoneinthedirectoryyouspecify.So,usingourcourierexample:whenrequestinga

PackageDevelopment

Introduction

Views

Views

packageview,Laravelwillfirstcheckifacustomversionoftheviewhasbeenprovidedbythedeveloperinresources/views/vendor/courier.Then,iftheviewhasnotbeencustomized,LaravelwillsearchthepackageviewdirectoryyouspecifiedinyourcalltoloadViewsFrom.Thismakesiteasyforend-userstocustomize/overrideyourpackage'sviews.

Topublishyourpackage'sviewstotheresources/views/vendordirectory,youshouldusethepublishesmethodfromthebootmethodofyourserviceprovider:

publicfunctionboot()

{

$this->loadViewsFrom(__DIR__.'/path/to/views','courier');

$this->publishes([

__DIR__.'/path/to/views'=>base_path('resources/views/vendor/courier'),

]);

}

Now,whenusersofyourpackageexecuteLaravel'svendor:publishcommand,yourviewsdirectorywillbecopiedtothespecifiedlocation.

Ifyouwouldliketooverwriteexistingfiles,usethe--forceswitch:

phpartisanvendor:publish--force

Note:Youmayusethepublishesmethodtopublishanytypeoffiletoanylocationyouwish.

Packagetranslationfilesaretypicallyreferencedusingadouble-colonsyntax:

returntrans('package::file.line');

AllyouneedtodoistellLaravelwherethetranslationsforagivennamespacearelocated.Forexample,ifyourpackageisnamed"courier",youmightaddthefollowingtoyourserviceprovider'sbootmethod:

publicfunctionboot()

{

$this->loadTranslationsFrom(__DIR__.'/path/to/translations','courier');

}

Notethatwithinyourtranslationsfolder,youwouldhavefurtherdirectoriesforeachlanguage,suchasen,es,ru,etc.

Nowyoumayloadyourpackagetranslationsusingthefollowingsyntax:

returntrans('courier::file.line');

Typically,youwillwanttopublishyourpackage'sconfigurationfiletotheapplication'sownconfigdirectory.Thiswillallowusersofyourpackagetoeasilyoverrideyourdefaultconfigurationoptions.

Topublishaconfigurationfile,justusethepublishesmethodfromthebootmethodofyourserviceprovider:

PublishingViews

Translations

Configuration

$this->publishes([

__DIR__.'/path/to/config/courier.php'=>config_path('courier.php'),

]);

Now,whenusersofyourpackageexecuteLaravel'svendor:publishcommand,yourfilewillbecopiedtothespecifiedlocation.Ofcourse,onceyourconfigurationhasbeenpublished,itcanbeaccessedlikeanyotherconfigurationfile:

$value=config('courier.option');

Youmayalsochoosetomergeyourownpackageconfigurationfilewiththeapplication'scopy.Thisallowsyouruserstoincludeonlytheoptionstheyactuallywanttooverrideinthepublishedcopyoftheconfiguration.Tomergetheconfigurations,usethemergeConfigFrommethodwithinyourserviceprovider'sregistermethod:

$this->mergeConfigFrom(

__DIR__.'/path/to/config/courier.php','courier'

);

Youmaywanttopublishgroupsoffilesseparately.Forinstance,youmightwantyouruserstobeabletopublishyourpackage'sconfigurationfilesandassetfilesseparately.Youcandothisby'tagging'them:

//Publishaconfigfile

$this->publishes([

__DIR__.'/../config/package.php',config_path('package.php')

],'config');

//Publishyourmigrations

$this->publishes([

__DIR__.'/../database/migrations/'=>base_path('/database/migrations')

],'migrations');

Youcanthenpublishthesefilesseparatelybyreferencingtheirtaglikeso:

phpartisanvendor:publish--provider="Vendor\Providers\PackageServiceProvider"--tag="config"

Toloadaroutesfileforyourpackage,simplyincludeitfromwithinyourserviceprovider'sbootmethod.

publicfunctionboot()

{

include__DIR__.'/../../routes.php';

}

Note:Ifyourpackageisusingcontrollers,youwillneedtomakesuretheyareproperlyconfiguredinyourcomposer.jsonfile'sauto-loadsection.

PublishingFileGroups

Routing

IncludingARoutesFileFromAServiceProvider

ConfigurationUsageAppendingToPaginationLinksConvertingToJSON

Inotherframeworks,paginationcanbeverypainful.Laravelmakesitabreeze.Laravelcangenerateanintelligent"range"oflinksbasedonthecurrentpage.ThegeneratedHTMLiscompatiblewiththeBootstrapCSSframework.

Thereareseveralwaystopaginateitems.ThesimplestisbyusingthepaginatemethodonthequerybuilderoranEloquentmodel.

$users=DB::table('users')->paginate(15);

Note:Currently,paginationoperationsthatuseagroupBystatementcannotbeexecutedefficientlybyLaravel.IfyouneedtouseagroupBywithapaginatedresultset,itisrecommendedthatyouquerythedatabaseandcreateapaginatormanually.

Sometimesyoumaywishtocreateapaginationinstancemanually,passingitanarrayofitems.YoumaydosobycreatingeitheranIlluminate\Pagination\PaginatororIlluminate\Pagination\LengthAwarePaginatorinstance,dependingonyourneeds.

YoumayalsopaginateEloquentmodels:

$allUsers=User::paginate(15);

$someUsers=User::where('votes','>',100)->paginate(15);

Theargumentpassedtothepaginatemethodisthenumberofitemsyouwishtodisplayperpage.Onceyouhaveretrievedtheresults,youmaydisplaythemonyourview,andcreatethepaginationlinksusingtherendermethod:

<divclass="container">

<?phpforeach($usersas$user):?>

<?phpecho$user->name;?>

<?phpendforeach;?>

</div>

<?phpecho$users->render();?>

Thisisallittakestocreateapaginationsystem!Notethatwedidnothavetoinformtheframeworkofthecurrentpage.Laravelwilldeterminethisforyouautomatically.

Pagination

Configuration

Usage

PaginatingDatabaseResults

CreatingAPaginatorManually

PaginatingAnEloquentModel

Youmayalsoaccessadditionalpaginationinformationviathefollowingmethods:

currentPage

lastPage

perPage

total

count

Ifyouareonlyshowing"Next"and"Previous"linksinyourpaginationview,youhavetheoptionofusingthesimplePaginatemethodtoperformamoreefficientquery.Thisisusefulforlargerdatasetswhenyoudonotrequirethedisplayofexactpagenumbersonyourview:

$someUsers=User::where('votes','>',100)->simplePaginate(15);

YoumayalsocustomizetheURIusedbythepaginatorviathesetPathmethod:

$users=User::paginate();

$users->setPath('custom/url');

TheexampleabovewillcreateURLslikethefollowing:http://example.com/custom/url?page=2

YoucanaddtothequerystringofpaginationlinksusingtheappendsmethodonthePaginator:

<?phpecho$users->appends(['sort'=>'votes'])->render();?>

ThiswillgenerateURLsthatlooksomethinglikethis:

http://example.com/something?page=2&sort=votes

Ifyouwishtoappenda"hashfragment"tothepaginator'sURLs,youmayusethefragmentmethod:

<?phpecho$users->fragment('foo')->render();?>

ThismethodcallwillgenerateURLsthatlooksomethinglikethis:

http://example.com/something?page=2#foo

ThePaginatorclassimplementstheIlluminate\Contracts\Support\JsonableInterfacecontractandexposesthetoJsonmethod.YoumayalsoconvertaPaginatorinstancetoJSONbyreturningitfromaroute.TheJSON'dformoftheinstancewillincludesome"meta"informationsuchastotal,current_page,andlast_page.Theinstance'sdatawillbeavailable

"SimplePagination"

CustomizingThePaginatorURI

AppendingToPaginationLinks

ConvertingToJSON

viathedatakeyintheJSONarray.

ConfigurationBasicUsageQueueingClosuresRunningTheQueueListenerDaemonQueueWorkerPushQueuesFailedJobs

TheLaravelQueuecomponentprovidesaunifiedAPIacrossavarietyofdifferentqueueservices.Queuesallowyoutodefertheprocessingofatimeconsumingtask,suchassendingane-mail,untilalatertime,thusdrasticallyspeedingupthewebrequeststoyourapplication.

Thequeueconfigurationfileisstoredinconfig/queue.php.Inthisfileyouwillfindconnectionconfigurationsforeachofthequeuedriversthatareincludedwiththeframework,whichincludesadatabase,Beanstalkd,IronMQ,AmazonSQS,Redis,null,andsynchronous(forlocaluse)driver.Thenullqueuedriversimplydiscardsqueuedjobssotheyareneverrun.

Inordertousethedatabasequeuedriver,youwillneedadatabasetabletoholdthejobs.Togenerateamigrationtocreatethistable,runthequeue:tableArtisancommand:

phpartisanqueue:table

Thefollowingdependenciesareneededforthelistedqueuedrivers:

AmazonSQS:aws/aws-sdk-phpBeanstalkd:pda/pheanstalk~3.0IronMQ:iron-io/iron_mqRedis:predis/predis~1.0

AllofthequeueablejobsforyourapplicationarestoredintheApp\Commandsdirectory.YoumaygenerateanewqueuedcommandusingtheArtisanCLI:

phpartisanmake:commandSendEmail--queued

Topushanewjobontothequeue,usetheQueue::pushmethod:

Queue::push(newSendEmail($message));

Queues

Configuration

QueueDatabaseTable

OtherQueueDependencies

BasicUsage

PushingAJobOntoTheQueue

Note:Inthisexample,weareusingtheQueuefacadedirectly;however,typicallyyouwoulddispatchqueuedcommandviatheCommandBus.WewillcontinuetousetheQueuefacadethroughoutthispage;however,familiarizewiththecommandbusaswell,sinceitisusedtodispatchbothqueuedandsynchronouscommandsforyourapplication.

Bydefault,themake:commandArtisancommandgeneratesa"self-handling"command,meaningahandlemethodisaddedtothecommanditself.Thismethodwillbecalledwhenthejobisexecutedbythequeue.Youmaytype-hintanydependenciesyouneedonthehandlemethodandtheIoCcontainerwillautomaticallyinjectthem:

publicfunctionhandle(UserRepository$users)

{

//

}

Ifyouwouldlikeyourcommandtohaveaseparatehandlerclass,youshouldaddthe--handlerflagtothemake:commandcommand:

phpartisanmake:commandSendEmail--queued--handler

ThegeneratedhandlerwillbeplacedinApp\Handlers\CommandsandwillberesolvedoutoftheIoCcontainer.

Youmayalsospecifythequeue/tubeajobshouldbesentto:

Queue::pushOn('emails',newSendEmail($message));

Ifyouneedtopassthesamedatatoseveralqueuejobs,youmayusetheQueue::bulkmethod:

Queue::bulk(array(newSendEmail($message),newAnotherCommand));

Sometimesyoumaywishtodelaytheexecutionofaqueuedjob.Forinstance,youmaywishtoqueueajobthatsendsacustomerane-mail15minutesaftersign-up.YoucanaccomplishthisusingtheQueue::latermethod:

$date=Carbon::now()->addMinutes(15);

Queue::later($date,newSendEmail($message));

Inthisexample,we'reusingtheCarbondatelibrarytospecifythedelaywewishtoassigntothejob.Alternatively,youmaypassthenumberofsecondsyouwishtodelayasaninteger.

Note:TheAmazonSQSservicehasadelaylimitof900seconds(15minutes).

IfyourqueuedjobacceptsanEloquentmodelinitsconstructor,onlytheidentifierforthemodelwillbeserializedontothequeue.Whenthejobisactuallyhandled,thequeuesystemwillautomaticallyre-retrievethefullmodelinstancefromthedatabase.It'salltotallytransparenttoyourapplicationandpreventsissuesthatcanarisefromserializingfullEloquent

SpecifyingTheQueue/TubeForAJob

PassingTheSamePayloadToMultipleJobs

DelayingTheExecutionOfAJob

QueuesAndEloquentModels

modelinstances.

Onceyouhaveprocessedajob,itmustbedeletedfromthequeue.Ifnoexceptionisthrownduringtheexecutionofyourjob,thiswillbedoneautomatically.

Ifyouwouldliketodeleteorreleasethejobmanually,theIlluminate\Queue\InteractsWithQueuetraitprovidesaccesstothequeuejobreleaseanddeletemethods.Thereleasemethodacceptsasinglevalue:thenumberofsecondsyouwishtowaituntilthejobismadeavailableagain.

publicfunctionhandle(SendEmail$command)

{

if(true)

{

$this->release(30);

}

}

IFanexceptionisthrownwhilethejobisbeingprocessed,itwillautomaticallybereleasedbackontothequeuesoitmaybeattemptedagain.Thejobwillcontinuetobereleaseduntilithasbeenattemptedthemaximumnumberoftimesallowedbyyourapplication.Thenumberofmaximumattemptsisdefinedbythe--triesswitchusedonthequeue:listenorqueue:workArtisancommands.

Ifanexceptionoccurswhilethejobisbeingprocessed,itwillautomaticallybereleasedbackontothequeue.Youmaycheckthenumberofattemptsthathavebeenmadetorunthejobusingtheattemptsmethod:

if($this->attempts()>3)

{

//

}

Note:Yourcommand/handlermustusetheIlluminate\Queue\InteractsWithQueuetraitinordertocallthismethod.

YoumayalsopushaClosureontothequeue.Thisisveryconvenientforquick,simpletasksthatneedtobequeued:

Queue::push(function($job)use($id)

{

Account::delete($id);

$job->delete();

});

Note:InsteadofmakingobjectsavailabletoqueuedClosuresviatheusedirective,considerpassingprimarykeysandre-pullingtheassociatedmodelsfromwithinyourqueuejob.Thisoftenavoidsunexpectedserializationbehavior.

WhenusingIron.iopushqueues,youshouldtakeextraprecautionqueueingClosures.Theend-pointthatreceivesyourqueuemessagesshouldcheckforatokentoverifythattherequestisactuallyfromIron.io.Forexample,yourpushqueueend-pointshouldbesomethinglike:https://yourapp.com/queue/receive?token=SecretToken.Youmaythencheckthevalue

DeletingAProcessedJob

ReleasingAJobBackOntoTheQueue

CheckingTheNumberOfRunAttempts

QueueingClosures

PushingAClosureOntoTheQueue

ofthesecrettokeninyourapplicationbeforemarshallingthequeuerequest.

LaravelincludesanArtisantaskthatwillrunnewjobsastheyarepushedontothequeue.Youmayrunthistaskusingthequeue:listencommand:

phpartisanqueue:listen

Youmayalsospecifywhichqueueconnectionthelistenershouldutilize:

phpartisanqueue:listenconnection

Notethatoncethistaskhasstarted,itwillcontinuetorununtilitismanuallystopped.YoumayuseaprocessmonitorsuchasSupervisortoensurethatthequeuelistenerdoesnotstoprunning.

Youmaypassacomma-delimitedlistofqueueconnectionstothelistencommandtosetqueuepriorities:

phpartisanqueue:listen--queue=high,low

Inthisexample,jobsonthehigh-connectionwillalwaysbeprocessedbeforemovingontojobsfromthelow-connection.

Youmayalsosetthelengthoftime(inseconds)eachjobshouldbeallowedtorun:

phpartisanqueue:listen--timeout=60

Inaddition,youmayspecifythenumberofsecondstowaitbeforepollingfornewjobs:

phpartisanqueue:listen--sleep=5

Notethatthequeueonly"sleeps"ifnojobsareonthequeue.Ifmorejobsareavailable,thequeuewillcontinuetoworkthemwithoutsleeping.

Toprocessonlythefirstjobonthequeue,youmayusethequeue:workcommand:

phpartisanqueue:work

Thequeue:workalsoincludesa--daemonoptionforforcingthequeueworkertocontinueprocessingjobswithouteverre-

RunningTheQueueListener

StartingTheQueueListener

SpecifyingTheJobTimeoutParameter

SpecifyingQueueSleepDuration

ProcessingTheFirstJobOnTheQueue

DaemonQueueWorker

bootingtheframework.ThisresultsinasignificantreductionofCPUusagewhencomparedtothequeue:listencommand,butattheaddedcomplexityofneedingtodrainthequeuesofcurrentlyexecutingjobsduringyourdeployments.

Tostartaqueueworkerindaemonmode,usethe--daemonflag:

phpartisanqueue:workconnection--daemon

phpartisanqueue:workconnection--daemon--sleep=3

phpartisanqueue:workconnection--daemon--sleep=3--tries=3

Asyoucansee,thequeue:workcommandsupportsmostofthesameoptionsavailabletoqueue:listen.Youmayusethephpartisanhelpqueue:workcommandtoviewalloftheavailableoptions.

Thesimplestwaytodeployanapplicationusingdaemonqueueworkersistoputtheapplicationinmaintenancemodeatthebeginningofyourdeployment.Thiscanbedoneusingthephpartisandowncommand.Oncetheapplicationisinmaintenancemode,Laravelwillnotacceptanynewjobsoffofthequeue,butwillcontinuetoprocessexistingjobs.

Theeasiestwaytorestartyourworkersistoincludethefollowingcommandinyourdeploymentscript:

phpartisanqueue:restart

Thiscommandwillinstructallqueueworkerstorestartaftertheyfinishprocessingtheircurrentjob.

Note:Thiscommandreliesonthecachesystemtoscheduletherestart.Bydefault,APCudoesnotworkforCLIcommands.IfyouareusingAPCu,addapc.enable_cli=1toyourAPCuconfiguration.

Daemonqueueworkersdonotrestarttheframeworkbeforeprocessingeachjob.Therefore,youshouldbecarefultofreeanyheavyresourcesbeforeyourjobfinishes.Forexample,ifyouaredoingimagemanipulationwiththeGDlibrary,youshouldfreethememorywithimagedestroywhenyouaredone.

Similarly,yourdatabaseconnectionmaydisconnectwhenbeingusedbylong-runningdaemon.YoumayusetheDB::reconnectmethodtoensureyouhaveafreshconnection.

PushqueuesallowyoutoutilizethepowerfulLaravel4queuefacilitieswithoutrunninganydaemonsorbackgroundlisteners.Currently,pushqueuesareonlysupportedbytheIron.iodriver.Beforegettingstarted,createanIron.ioaccount,andaddyourIroncredentialstotheconfig/queue.phpconfigurationfile.

Next,youmayusethequeue:subscribeArtisancommandtoregisteraURLend-pointthatwillreceivenewlypushedqueuejobs:

phpartisanqueue:subscribequeue_namehttp://foo.com/queue/receive

Now,whenyoulogintoyourIrondashboard,youwillseeyournewpushqueue,aswellasthesubscribedURL.YoumaysubscribeasmanyURLsasyouwishtoagivenqueue.Next,createarouteforyourqueue/receiveend-pointandreturntheresponsefromtheQueue::marshalmethod:

DeployingWithDaemonQueueWorkers

CodingForDaemonQueueWorkers

PushQueues

RegisteringAPushQueueSubscriber

Route::post('queue/receive',function()

{

returnQueue::marshal();

});

Themarshalmethodwilltakecareoffiringthecorrectjobhandlerclass.Tofirejobsontothepushqueue,justusethesameQueue::pushmethodusedforconventionalqueues.

Sincethingsdon'talwaysgoasplanned,sometimesyourqueuedjobswillfail.Don'tworry,ithappenstothebestofus!Laravelincludesaconvenientwaytospecifythemaximumnumberoftimesajobshouldbeattempted.Afterajobhasexceededthisamountofattempts,itwillbeinsertedintoafailed_jobstable.Thefailedjobstablenamecanbeconfiguredviatheconfig/queue.phpconfigurationfile.

Tocreateamigrationforthefailed_jobstable,youmayusethequeue:failed-tablecommand:

phpartisanqueue:failed-table

Youcanspecifythemaximumnumberoftimesajobshouldbeattemptedusingthe--triesswitchonthequeue:listencommand:

phpartisanqueue:listenconnection-name--tries=3

Ifyouwouldliketoregisteraneventthatwillbecalledwhenaqueuejobfails,youmayusetheQueue::failingmethod.Thiseventisagreatopportunitytonotifyyourteamviae-mailorHipChat.

Queue::failing(function($connection,$job,$data)

{

//

});

Youmayalsodefineafailedmethoddirectlyonaqueuejobclass,allowingyoutoperformjobspecificactionswhenafailureoccurs:

publicfunctionfailed()

{

//Calledwhenthejobisfailing...

}

Toviewallofyourfailedjobs,youmayusethequeue:failedArtisancommand:

phpartisanqueue:failed

Thequeue:failedcommandwilllistthejobID,connection,queue,andfailuretime.ThejobIDmaybeusedtoretrythefailedjob.Forinstance,toretryafailedjobthathasanIDof5,thefollowingcommandshouldbeissued:

phpartisanqueue:retry5

FailedJobs

RetryingFailedJobs

Ifyouwouldliketodeleteafailedjob,youmayusethequeue:forgetcommand:

phpartisanqueue:forget5

Todeleteallofyourfailedjobs,youmayusethequeue:flushcommand:

phpartisanqueue:flush

ConfigurationSessionUsageFlashDataDatabaseSessionsSessionDrivers

SinceHTTPdrivenapplicationsarestateless,sessionsprovideawaytostoreinformationabouttheuseracrossrequests.Laravelshipswithavarietyofsessionback-endsavailableforusethroughaclean,unifiedAPI.Supportforpopularback-endssuchasMemcached,Redis,anddatabasesisincludedoutofthebox.

Thesessionconfigurationisstoredinconfig/session.php.Besuretoreviewthewelldocumentedoptionsavailabletoyouinthisfile.Bydefault,Laravelisconfiguredtousethefilesessiondriver,whichwillworkwellforthemajorityofapplications.

BeforeusingRedissessionswithLaravel,youwillneedtoinstallthepredis/predispackage(~1.0)viaComposer.

Note:Ifyouneedallstoredsessiondatatobeencrypted,settheencryptconfigurationoptiontotrue.

TheLaravelframeworkusestheflashsessionkeyinternally,soyoushouldnotaddanitemtothesessionbythatname.

Session::put('key','value');

Session::push('user.teams','developers');

$value=Session::get('key');

$value=Session::get('key','default');

$value=Session::get('key',function(){return'default';});

Session

Configuration

ReservedKeys

SessionUsage

StoringAnItemInTheSession

PushAValueOntoAnArraySessionValue

RetrievingAnItemFromTheSession

RetrievingAnItemOrReturningADefaultValue

RetrievingAnItemAndForgettingIt

$value=Session::pull('key','default');

$data=Session::all();

if(Session::has('users'))

{

//

}

Session::forget('key');

Session::flush();

Session::regenerate();

Sometimesyoumaywishtostoreitemsinthesessiononlyforthenextrequest.YoumaydosousingtheSession::flashmethod:

Session::flash('key','value');

Session::reflash();

Session::keep(array('username','email'));

Whenusingthedatabasesessiondriver,youwillneedtosetupatabletocontainthesessionitems.BelowisanexampleSchemadeclarationforthetable:

RetrievingAllDataFromTheSession

DeterminingIfAnItemExistsInTheSession

RemovingAnItemFromTheSession

RemovingAllItemsFromTheSession

RegeneratingTheSessionID

FlashData

ReflashingTheCurrentFlashDataForAnotherRequest

ReflashingOnlyASubsetOfFlashData

DatabaseSessions

Schema::create('sessions',function($table)

{

$table->string('id')->unique();

$table->text('payload');

$table->integer('last_activity');

});

Ofcourse,youmayusethesession:tableArtisancommandtogeneratethismigrationforyou!

phpartisansession:table

composerdump-autoload

phpartisanmigrate

Thesession"driver"defineswheresessiondatawillbestoredforeachrequest.Laravelshipswithseveralgreatdriversoutofthebox:

file-sessionswillbestoredinapp/storage/sessions.cookie-sessionswillbestoredinsecure,encryptedcookies.database-sessionswillbestoredinadatabaseusedbyyourapplication.memcached/redis-sessionswillbestoredinoneofthesefast,cachedbasedstores.array-sessionswillbestoredinasimplePHParrayandwillnotbepersistedacrossrequests.

Note:Thearraydriveristypicallyusedforrunningunittests,sonosessiondatawillbepersisted.

SessionDrivers

BladeTemplatingOtherBladeControlStructuresExtendingBlade

Bladeisasimple,yetpowerfultemplatingengineprovidedwithLaravel.Unlikecontrollerlayouts,Bladeisdrivenbytemplateinheritanceandsections.AllBladetemplatesshouldusethe.blade.phpextension.

<!--Storedinresources/views/layouts/master.blade.php-->

<html>

<body>

@section('sidebar')

Thisisthemastersidebar.

@show

<divclass="container">

@yield('content')

</div>

</body>

</html>

@extends('layouts.master')

@section('sidebar')

@@parent

<p>Thisisappendedtothemastersidebar.</p>

@stop

@section('content')

<p>Thisismybodycontent.</p>

@stop

NotethatviewswhichextendaBladelayoutsimplyoverridesectionsfromthelayout.Contentofthelayoutcanbeincludedinachildviewusingthe@@parentdirectiveinasection,allowingyoutoappendtothecontentsofalayoutsectionsuchasasidebarorfooter.

Sometimes,suchaswhenyouarenotsureifasectionhasbeendefined,youmaywishtopassadefaultvaluetothe@yielddirective.Youmaypassthedefaultvalueasthesecondargument:

@yield('section','DefaultContent')

Hello,{{$name}}.

Templates

BladeTemplating

DefiningABladeLayout

UsingABladeLayout

OtherBladeControlStructures

EchoingData

ThecurrentUNIXtimestampis{{time()}}.

Sometimesyoumaywishtoechoavariable,butyouaren'tsureifthevariablehasbeenset.Basically,youwanttodothis:

{{isset($name)?$name:'Default'}}

However,insteadofwritingaternarystatement,Bladeallowsyoutousethefollowingconvenientshort-cut:

{{$nameor'Default'}}

Ifyouneedtodisplayastringthatiswrappedincurlybraces,youmayescapetheBladebehaviorbyprefixingyourtextwithan@symbol:

@{{ThiswillnotbeprocessedbyBlade}}

Ifyoudon'twantthedatatobeescaped,youmayusethefollowingsyntax:

Hello,{!!$name!!}.

Note:Beverycarefulwhenechoingcontentthatissuppliedbyusersofyourapplication.AlwaysusethedoublecurlybracesyntaxtoescapeanyHTMLentitiesinthecontent.

@if(count($records)===1)

Ihaveonerecord!

@elseif(count($records)>1)

Ihavemultiplerecords!

@else

Idon'thaveanyrecords!

@endif

@unless(Auth::check())

Youarenotsignedin.

@endunless

@for($i=0;$i<10;$i++)

Thecurrentvalueis{{$i}}

@endfor

@foreach($usersas$user)

<p>Thisisuser{{$user->id}}</p>

@endforeach

@forelse($usersas$user)

<li>{{$user->name}}</li>

@empty

<p>Nousers</p>

@endforelse

EchoingDataAfterCheckingForExistence

DisplayingRawTextWithCurlyBraces

IfStatements

Loops

@while(true)

<p>I'mloopingforever.</p>

@endwhile

@include('view.name')

Youmayalsopassanarrayofdatatotheincludedview:

@include('view.name',['some'=>'data'])

Tooverwriteasectionentirely,youmayusetheoverwritestatement:

@extends('list.item.container')

@section('list.item.content')

<p>Thisisanitemoftype{{$item->type}}</p>

@overwrite

@lang('language.line')

@choice('language.line',1)

{{--ThiscommentwillnotbeintherenderedHTML--}}

Bladeevenallowsyoutodefineyourowncustomcontrolstructures.WhenaBladefileiscompiled,eachcustomextensioniscalledwiththeviewcontents,allowingyoutodoanythingfromsimplestr_replacemanipulationstomorecomplexregularexpressions.

TheBladecompilercomeswiththehelpermethodscreateMatcherandcreatePlainMatcher,whichgeneratetheexpressionyouneedtobuildyourowncustomdirectives.

ThecreatePlainMatchermethodisusedfordirectiveswithnoargumentslike@endifand@stop,whilecreateMatcherisusedfordirectiveswitharguments.

Thefollowingexamplecreatesa@datetime($var)directivewhichsimplycalls->format()on$var:

Blade::extend(function($view,$compiler)

{

$pattern=$compiler->createMatcher('datetime');

returnpreg_replace($pattern,'$1<?phpecho$2->format(\'m/d/YH:i\');?>',$view);

});

IncludingSub-Views

OverwritingSections

DisplayingLanguageLines

Comments

ExtendingBlade

IntroductionDefining&RunningTestsTestEnvironmentCallingRoutesFromTestsMockingFacadesFrameworkAssertionsHelperMethodsRefreshingTheApplication

Laravelisbuiltwithunittestinginmind.Infact,supportfortestingwithPHPUnitisincludedoutofthebox,andaphpunit.xmlfileisalreadysetupforyourapplication.

Anexampletestfileisprovidedinthetestsdirectory.AfterinstallinganewLaravelapplication,simplyrunphpunitonthecommandlinetorunyourtests.

Tocreateatestcase,simplycreateanewtestfileinthetestsdirectory.ThetestclassshouldextendTestCase.YoumaythendefinetestmethodsasyounormallywouldwhenusingPHPUnit.

classFooTestextendsTestCase{

publicfunctiontestSomethingIsTrue()

{

$this->assertTrue(true);

}

}

Youmayrunallofthetestsforyourapplicationbyexecutingthephpunitcommandfromyourterminal.

Note:IfyoudefineyourownsetUpmethod,besuretocallparent::setUp.

Whenrunningunittests,Laravelwillautomaticallysettheconfigurationenvironmenttotesting.Also,Laravelincludesconfigurationfilesforsessionandcacheinthetestenvironment.Bothofthesedriversaresettoarraywhileinthetestenvironment,meaningnosessionorcachedatawillbepersistedwhiletesting.Youarefreetocreateothertestingenvironmentconfigurationsasnecessary.

Thetestingenvironmentvariablesmaybeconfiguredinthephpunit.xmlfile.

Testing

Introduction

Defining&RunningTests

AnExampleTestClass

TestEnvironment

CallingRoutesFromTests

CallingARouteFromATest

Youmayeasilycalloneofyourroutesforatestusingthecallmethod:

$response=$this->call('GET','user/profile');

$response=$this->call($method,$uri,$parameters,$files,$server,$content);

YoumaytheninspecttheIlluminate\Http\Responseobject:

$this->assertEquals('HelloWorld',$response->getContent());

Youmayalsocallacontrollerfromatest:

$response=$this->action('GET','HomeController@index');

$response=$this->action('GET','UserController@profile',array('user'=>1));

Note:Youdonotneedtospecifythefullcontrollernamespacewhenusingtheactionmethod.OnlyspecifytheportionoftheclassnamethatfollowstheApp\Http\Controllersnamespace.

ThegetContentmethodwillreturntheevaluatedstringcontentsoftheresponse.IfyourroutereturnsaView,youmayaccessitusingtheoriginalproperty:

$view=$response->original;

$this->assertEquals('John',$view['name']);

TocallaHTTPSroute,youmayusethecallSecuremethod:

$response=$this->callSecure('GET','foo/bar');

Whentesting,youmayoftenwanttomockacalltoaLaravelstaticfacade.Forexample,considerthefollowingcontrolleraction:

publicfunctiongetIndex()

{

Event::fire('foo',['name'=>'Dayle']);

return'Alldone!';

}

WecanmockthecalltotheEventclassbyusingtheshouldReceivemethodonthefacade,whichwillreturnaninstanceofaMockerymock.

publicfunctiontestGetIndex()

{

Event::shouldReceive('fire')->once()->with('foo',['name'=>'Dayle']);

CallingAControllerFromATest

MockingFacades

MockingAFacade

$this->call('GET','/');

}

Note:YoushouldnotmocktheRequestfacade.Instead,passtheinputyoudesireintothecallmethodwhenrunningyourtest.

Laravelshipswithseveralassertmethodstomaketestingalittleeasier:

publicfunctiontestMethod()

{

$this->call('GET','/');

$this->assertResponseOk();

}

$this->assertResponseStatus(403);

$this->assertRedirectedTo('foo');

$this->assertRedirectedToRoute('route.name');

$this->assertRedirectedToAction('Controller@method');

publicfunctiontestMethod()

{

$this->call('GET','/');

$this->assertViewHas('name');

$this->assertViewHas('age',$value);

}

publicfunctiontestMethod()

{

$this->call('GET','/');

$this->assertSessionHas('name');

$this->assertSessionHas('age',$value);

}

publicfunctiontestMethod()

{

FrameworkAssertions

AssertingResponsesAreOK

AssertingResponseStatuses

AssertingResponsesAreRedirects

AssertingAViewHasSomeData

AssertingTheSessionHasSomeData

AssertingTheSessionHasErrors

$this->call('GET','/');

$this->assertSessionHasErrors();

//Assertingthesessionhaserrorsforagivenkey...

$this->assertSessionHasErrors('name');

//Assertingthesessionhaserrorsforseveralkeys...

$this->assertSessionHasErrors(array('name','age'));

}

publicfunctiontestMethod()

{

$this->call('GET','/');

$this->assertHasOldInput();

}

TheTestCaseclasscontainsseveralhelpermethodstomaketestingyourapplicationeasier.

$this->session(['foo'=>'bar']);

$this->flushSession();

Youmaysetthecurrentlyauthenticateduserusingthebemethod:

$user=newUser(array('name'=>'John'));

$this->be($user);

Youmayre-seedyourdatabasefromatestusingtheseedmethod:

$this->seed();

$this->seed($connection);

Moreinformationoncreatingseedsmaybefoundinthemigrationsandseedingsectionofthedocumentation.

Asyoumayalreadyknow,youcanaccessyourLaravelApplication/IoCContainervia$this->appfromanytestmethod.ThisApplicationinstanceisrefreshedforeachtestclass.IfyouwishtomanuallyforcetheApplicationtoberefreshedforagivenmethod,youmayusetherefreshApplicationmethodfromyourtestmethod.Thiswillresetanyextrabindings,suchasmocks,thathavebeenplacedintheIoCcontainersincethetestcasestartedrunning.

AssertingOldInputHasSomeData

HelperMethods

SettingAndFlushingSessionsFromTests

SettingTheCurrentlyAuthenticatedUser

Re-SeedingDatabaseFromTests

RefreshingTheApplication

BasicUsageControllerValidationFormRequestValidationWorkingWithErrorMessagesErrorMessages&ViewsAvailableValidationRulesConditionallyAddingRulesCustomErrorMessagesCustomValidationRules

Laravelshipswithasimple,convenientfacilityforvalidatingdataandretrievingvalidationerrormessagesviatheValidationclass.

$validator=Validator::make(

array('name'=>'Dayle'),

array('name'=>'required|min:5')

);

Thefirstargumentpassedtothemakemethodisthedataundervalidation.Thesecondargumentisthevalidationrulesthatshouldbeappliedtothedata.

Multiplerulesmaybedelimitedusingeithera"pipe"character,orasseparateelementsofanarray.

$validator=Validator::make(

array('name'=>'Dayle'),

array('name'=>array('required','min:5'))

);

$validator=Validator::make(

array(

'name'=>'Dayle',

'password'=>'lamepassword',

'email'=>'email@example.com'

),

array(

'name'=>'required',

'password'=>'required|min:8',

'email'=>'required|email|unique:users'

)

);

OnceaValidatorinstancehasbeencreated,thefails(orpasses)methodmaybeusedtoperformthevalidation.

if($validator->fails())

{

Validation

BasicUsage

BasicValidationExample

UsingArraysToSpecifyRules

ValidatingMultipleFields

//Thegivendatadidnotpassvalidation

}

Ifvalidationhasfailed,youmayretrievetheerrormessagesfromthevalidator.

$messages=$validator->messages();

Youmayalsoaccessanarrayofthefailedvalidationrules,withoutmessages.Todoso,usethefailedmethod:

$failed=$validator->failed();

TheValidatorclassprovidesseveralrulesforvalidatingfiles,suchassize,mimes,andothers.Whenvalidatingfiles,youmaysimplypassthemintothevalidatorwithyourotherdata.

Thevalidatoralsoallowsyoutoattachcallbackstoberunaftervalidationiscompleted.Thisallowsyoutoeasilyperformfurthervalidation,andevenaddmoreerrormessagestothemessagecollection.Togetstarted,usetheaftermethodonavalidatorinstance:

$validator=Validator::make(...);

$validator->after(function($validator)

{

if($this->somethingElseIsInvalid())

{

$validator->errors()->add('field','Somethingiswrongwiththisfield!');

}

});

if($validator->fails())

{

//

}

Youmayaddasmanyaftercallbackstoavalidatorasneeded.

Ofcourse,manuallycreatingandcheckingaValidatorinstanceeachtimeyoudovalidationisaheadache.Don'tworry,youhaveotheroptions!ThebaseApp\Http\Controllers\ControllerclassincludedwithLaravelusesaValidatesRequeststrait.Thistraitprovidesasingle,convenientmethodforvalidatingincomingHTTPrequests.Here'swhatitlookslike:

/**

*Storetheincomingblogpost.

*

*@paramRequest$request

*@returnResponse

*/

publicfunctionstore(Request$request)

{

$this->validate($request,[

'title'=>'required|unique|max:255',

'body'=>'required',

]);

//

}

ValidatingFiles

AfterValidationHook

ControllerValidation

Ifvalidationpasses,yourcodewillkeepexecutingnormally.However,ifvalidationfails,anIlluminate\Contracts\Validation\ValidationExceptionwillbethrown.Thisexceptionisautomaticallycaughtandaredirectisgeneratedtotheuser'spreviouslocation.Thevalidationerrorsareevenautomaticallyflashedtothesession!

IftheincomingrequestwasanAJAXrequest,noredirectwillbegenerated.Instead,anHTTPresponsewitha422statuscodewillbereturnedtothebrowsercontainingaJSONrepresentationofthevalidationerrors.

Forexample,hereistheequivalentcodewrittenmanually:

/**

*Storetheincomingblogpost.

*

*@paramRequest$request

*@returnResponse

*/

publicfunctionstore(Request$request)

{

$v=Validator::make($request->all(),[

'title'=>'required|unique|max:255',

'body'=>'required',

]);

if($v->fails())

{

returnredirect()->back()->withErrors($v->errors());

}

//

}

Ifyouwishtocustomizetheformatofthevalidationerrorsthatareflashedtothesessionwhenvalidationfails,overridetheformatValidationErrorsonyourbasecontroller.Don'tforgettoimporttheIlluminate\Validation\Validatorclassatthetopofthefile:

/**

*{@inheritdoc}

*/

protectedfunctionformatValidationErrors(Validator$validator)

{

return$validator->errors()->all();

}

Formorecomplexvalidationscenarios,youmaywishtocreatea"formrequest".Formrequestsarecustomrequestclassesthatcontainvalidationlogic.Tocreateaformrequestclass,usethemake:requestArtisanCLIcommand:

phpartisanmake:requestStoreBlogPostRequest

Thegeneratedclasswillbeplacedintheapp/Http/Requestsdirectory.Let'saddafewvalidationrulestotherulesmethod:

/**

*Getthevalidationrulesthatapplytotherequest.

*

*@returnarray

*/

publicfunctionrules()

CustomizingTheFlashedErrorFormat

FormRequestValidation

{

return[

'title'=>'required|unique|max:255',

'body'=>'required',

];

}

So,howarethevalidationrulesexecuted?Allyouneedtodoistype-hinttherequestonyourcontrollermethod:

/**

*Storetheincomingblogpost.

*

*@paramStoreBlogPostRequest$request

*@returnResponse

*/

publicfunctionstore(StoreBlogPostRequest$request)

{

//Theincomingrequestisvalid...

}

Theincomingformrequestisvalidatedbeforethecontrollermethodiscalled,meaningyoudonotneedtoclutteryourcontrollerwithanyvalidationlogic.Ithasalreadybeenvalidated!

Ifvalidationfails,aredirectresponsewillbegeneratedtosendtheuserbacktotheirpreviouslocation.Theerrorswillalsobeflashedtothesessionsotheyareavailablefordisplay.IftherequestwasanAJAXrequest,aHTTPresponsewitha422statuscodewillbereturnedtotheuserincludingaJSONrepresentationofthevalidationerrors.

Theformrequestclassalsocontainsanauthorizemethod.Withinthismethod,youmaycheckiftheauthenticateduseractuallyhastheauthoritytoupdateagivenresource.Forexample,ifauserisattemptingtoupdateablogpostcomment,dotheyactuallyownthatcomment?Forexample:

/**

*Determineiftheuserisauthorizedtomakethisrequest.

*

*@returnbool

*/

publicfunctionauthorize()

{

$commentId=$this->route('comment');

returnComment::where('id',$commentId)

->where('user_id',Auth::id())->exists();

}

Notethecalltotheroutemethodintheexampleabove.ThismethodgrantsyouaccesstotheURIparametersdefinedontheroutebeingcalled,suchasthe{comment}parameterintheexamplebelow:

Route::post('comment/{comment}');

Iftheauthorizemethodreturnsfalse,aHTTPresponsewitha403statuscodewillautomaticallybereturnedandyourcontrollermethodwillnotexecute.

Ifyouplantohaveauthorizationlogicinanotherpartofyourapplication,simplyreturntruefromtheauthorizemethod:

/**

*Determineiftheuserisauthorizedtomakethisrequest.

*

*@returnbool

*/

publicfunctionauthorize()

AuthorizingFormRequests

{

returntrue;

}

Ifyouwishtocustomizetheformatofthevalidationerrorsthatareflashedtothesessionwhenvalidationfails,overridetheformatValidationErrorsonyourbaserequest(App\Http\Requests\Request).Don'tforgettoimporttheIlluminate\Validation\Validatorclassatthetopofthefile:

/**

*{@inheritdoc}

*/

protectedfunctionformatErrors(Validator$validator)

{

return$validator->errors()->all();

}

AftercallingthemessagesmethodonaValidatorinstance,youwillreceiveaMessageBaginstance,whichhasavarietyofconvenientmethodsforworkingwitherrormessages.

echo$messages->first('email');

foreach($messages->get('email')as$message)

{

//

}

foreach($messages->all()as$message)

{

//

}

if($messages->has('email'))

{

//

}

echo$messages->first('email','<p>:message</p>');

CustomizingTheFlashedErrorFormat

WorkingWithErrorMessages

RetrievingTheFirstErrorMessageForAField

RetrievingAllErrorMessagesForAField

RetrievingAllErrorMessagesForAllFields

DeterminingIfMessagesExistForAField

RetrievingAnErrorMessageWithAFormat

Note:Bydefault,messagesareformattedusingBootstrapcompatiblesyntax.

foreach($messages->all('<li>:message</li>')as$message)

{

//

}

Onceyouhaveperformedvalidation,youwillneedaneasywaytogettheerrormessagesbacktoyourviews.ThisisconvenientlyhandledbyLaravel.Considerthefollowingroutesasanexample:

Route::get('register',function()

{

returnView::make('user.register');

});

Route::post('register',function()

{

$rules=array(...);

$validator=Validator::make(Input::all(),$rules);

if($validator->fails())

{

returnredirect('register')->withErrors($validator);

}

});

Notethatwhenvalidationfails,wepasstheValidatorinstancetotheRedirectusingthewithErrorsmethod.Thismethodwillflashtheerrormessagestothesessionsothattheyareavailableonthenextrequest.

However,noticethatwedonothavetoexplicitlybindtheerrormessagestotheviewinourGETroute.ThisisbecauseLaravelwillalwayscheckforerrorsinthesessiondata,andautomaticallybindthemtotheviewiftheyareavailable.So,itisimportanttonotethatan$errorsvariablewillalwaysbeavailableinallofyourviews,oneveryrequest,allowingyoutoconvenientlyassumethe$errorsvariableisalwaysdefinedandcanbesafelyused.The$errorsvariablewillbeaninstanceofMessageBag.

So,afterredirection,youmayutilizetheautomaticallybound$errorsvariableinyourview:

<?phpecho$errors->first('email');?>

Ifyouhavemultipleformsonasinglepage,youmaywishtonametheMessageBagoferrors.Thiswillallowyoutoretrievetheerrormessagesforaspecificform.SimplypassanameasthesecondargumenttowithErrors:

returnredirect('register')->withErrors($validator,'login');

YoumaythenaccessthenamedMessageBaginstancefromthe$errorsvariable:

<?phpecho$errors->login->first('email');?>

RetrievingAllErrorMessagesWithAFormat

ErrorMessages&Views

NamedErrorBags

Belowisalistofallavailablevalidationrulesandtheirfunction:

AcceptedActiveURLAfter(Date)AlphaAlphaDashAlphaNumericArrayBefore(Date)BetweenBooleanConfirmedDateDateFormatDifferentDigitsDigitsBetweenE-MailExists(Database)Image(File)InIntegerIPAddressMaxMIMETypesMinNotInNumericRegularExpressionRequiredRequiredIfRequiredWithRequiredWithAllRequiredWithoutRequiredWithoutAllSameSizeStringTimezoneUnique(Database)URL

Thefieldundervalidationmustbeyes,on,or1.Thisisusefulforvalidating"TermsofService"acceptance.

ThefieldundervalidationmustbeavalidURLaccordingtothecheckdnsrrPHPfunction.

Thefieldundervalidationmustbeavalueafteragivendate.ThedateswillbepassedintothePHPstrtotimefunction.

AvailableValidationRules

accepted

active_url

after:date

Thefieldundervalidationmustbeentirelyalphabeticcharacters.

Thefieldundervalidationmayhavealpha-numericcharacters,aswellasdashesandunderscores.

Thefieldundervalidationmustbeentirelyalpha-numericcharacters.

Thefieldundervalidationmustbeoftypearray.

Thefieldundervalidationmustbeavalueprecedingthegivendate.ThedateswillbepassedintothePHPstrtotimefunction.

Thefieldundervalidationmusthaveasizebetweenthegivenminandmax.Strings,numerics,andfilesareevaluatedinthesamefashionasthesizerule.

Thefieldundervalidationmustbeabletobecastasaboolean.Acceptedinputaretrue,false,1,0,"1"and"0".

Thefieldundervalidationmusthaveamatchingfieldoffoo_confirmation.Forexample,ifthefieldundervalidationispassword,amatchingpassword_confirmationfieldmustbepresentintheinput.

ThefieldundervalidationmustbeavaliddateaccordingtothestrtotimePHPfunction.

Thefieldundervalidationmustmatchtheformatdefinedaccordingtothedate_parse_from_formatPHPfunction.

Thegivenfieldmustbedifferentthanthefieldundervalidation.

Thefieldundervalidationmustbenumericandmusthaveanexactlengthofvalue.

Thefieldundervalidationmusthavealengthbetweenthegivenminandmax.

alpha

alpha_dash

alpha_num

array

before:date

between:min,max

boolean

confirmed

date

dateformat:_format

different:field

digits:value

digitsbetween:_min,max

email

Thefieldundervalidationmustbeformattedasane-mailaddress.

Thefieldundervalidationmustexistonagivendatabasetable.

'state'=>'exists:states'

'state'=>'exists:states,abbreviation'

Youmayalsospecifymoreconditionsthatwillbeaddedas"where"clausestothequery:

'email'=>'exists:staff,email,account_id,1'

PassingNULLasa"where"clausevaluewilladdacheckforaNULLdatabasevalue:

'email'=>'exists:staff,email,deleted_at,NULL'

Thefileundervalidationmustbeanimage(jpeg,png,bmp,gif,orsvg)

Thefieldundervalidationmustbeincludedinthegivenlistofvalues.

Thefieldundervalidationmusthaveanintegervalue.

ThefieldundervalidationmustbeformattedasanIPaddress.

Thefieldundervalidationmustbelessthanorequaltoamaximumvalue.Strings,numerics,andfilesareevaluatedinthesamefashionasthesizerule.

ThefileundervalidationmusthaveaMIMEtypecorrespondingtooneofthelistedextensions.

'photo'=>'mimes:jpeg,bmp,png'

exists:table,column

BasicUsageOfExistsRule

SpecifyingACustomColumnName

image

in:foo,bar,...

integer

ip

max:value

mimes:foo,bar,...

BasicUsageOfMIMERule

Thefieldundervalidationmusthaveaminimumvalue.Strings,numerics,andfilesareevaluatedinthesamefashionasthesizerule.

Thefieldundervalidationmustnotbeincludedinthegivenlistofvalues.

Thefieldundervalidationmusthaveanumericvalue.

Thefieldundervalidationmustmatchthegivenregularexpression.

Note:Whenusingtheregexpattern,itmaybenecessarytospecifyrulesinanarrayinsteadofusingpipedelimiters,especiallyiftheregularexpressioncontainsapipecharacter.

Thefieldundervalidationmustbepresentintheinputdata.

Thefieldundervalidationmustbepresentifthefieldfieldisequaltoanyvalue.

Thefieldundervalidationmustbepresentonlyifanyoftheotherspecifiedfieldsarepresent.

Thefieldundervalidationmustbepresentonlyifalloftheotherspecifiedfieldsarepresent.

Thefieldundervalidationmustbepresentonlywhenanyoftheotherspecifiedfieldsarenotpresent.

Thefieldundervalidationmustbepresentonlywhenalloftheotherspecifiedfieldsarenotpresent.

Thegivenfieldmustmatchthefieldundervalidation.

Thefieldundervalidationmusthaveasizematchingthegivenvalue.Forstringdata,valuecorrespondstothenumberofcharacters.Fornumericdata,valuecorrespondstoagivenintegervalue.Forfiles,sizecorrespondstothefilesizeinkilobytes.

Thefieldundervalidationmustbeastringtype.

min:value

notin:_foo,bar,...

numeric

regex:pattern

required

requiredif:_field,value,...

requiredwith:_foo,bar,...

requiredwith_all:_foo,bar,...

requiredwithout:_foo,bar,...

requiredwithout_all:_foo,bar,...

same:field

size:value

string:value

Thefieldundervalidationmustbeavalidtimezoneidentifieraccordingtothetimezone_identifiers_listPHPfunction.

Thefieldundervalidationmustbeuniqueonagivendatabasetable.Ifthecolumnoptionisnotspecified,thefieldnamewillbeused.

'email'=>'unique:users'

'email'=>'unique:users,email_address'

'email'=>'unique:users,email_address,10'

Youmayalsospecifymoreconditionsthatwillbeaddedas"where"clausestothequery:

'email'=>'unique:users,email_address,NULL,id,account_id,1'

Intheruleabove,onlyrowswithanaccount_idof1wouldbeincludedintheuniquecheck.

ThefieldundervalidationmustbeformattedasanURL.

Note:ThisfunctionusesPHP'sfilter_varmethod.

Insomesituations,youmaywishtorunvalidationchecksagainstafieldonlyifthatfieldispresentintheinputarray.Toquicklyaccomplishthis,addthesometimesruletoyourrulelist:

$v=Validator::make($data,array(

'email'=>'sometimes|required|email',

));

Intheexampleabove,theemailfieldwillonlybevalidatedifitispresentinthe$dataarray.

Sometimesyoumaywishtorequireagivenfieldonlyifanotherfieldhasagreatervaluethan100.Oryoumayneedtwofieldstohaveagivenvalueonlywhenanotherfieldispresent.Addingthesevalidationrulesdoesn'thavetobeapain.

timezone

unique:table,column,except,idColumn

BasicUsageOfUniqueRule

SpecifyingACustomColumnName

ForcingAUniqueRuleToIgnoreAGivenID

AddingAdditionalWhereClauses

url

ConditionallyAddingRules

ComplexConditionalValidation

First,createaValidatorinstancewithyourstaticrulesthatneverchange:

$v=Validator::make($data,array(

'email'=>'required|email',

'games'=>'required|numeric',

));

Let'sassumeourwebapplicationisforgamecollectors.Ifagamecollectorregisterswithourapplicationandtheyownmorethan100games,wewantthemtoexplainwhytheyownsomanygames.Forexample,perhapstheyrunagamere-sellshop,ormaybetheyjustenjoycollecting.Toconditionallyaddthisrequirement,wecanusethesometimesmethodontheValidatorinstance.

$v->sometimes('reason','required|max:500',function($input)

{

return$input->games>=100;

});

Thefirstargumentpassedtothesometimesmethodisthenameofthefieldweareconditionallyvalidating.Thesecondargumentistheruleswewanttoadd.IftheClosurepassedasthethirdargumentreturnstrue,theruleswillbeadded.Thismethodmakesitabreezetobuildcomplexconditionalvalidations.Youmayevenaddconditionalvalidationsforseveralfieldsatonce:

$v->sometimes(array('reason','cost'),'required',function($input)

{

return$input->games>=100;

});

Note:The$inputparameterpassedtoyourClosurewillbeaninstanceofIlluminate\Support\Fluentandmaybeusedasanobjecttoaccessyourinputandfiles.

Ifneeded,youmayusecustomerrormessagesforvalidationinsteadofthedefaults.Thereareseveralwaystospecifycustommessages.

$messages=array(

'required'=>'The:attributefieldisrequired.',

);

$validator=Validator::make($input,$rules,$messages);

Note:The:attributeplace-holderwillbereplacedbytheactualnameofthefieldundervalidation.Youmayalsoutilizeotherplace-holdersinvalidationmessages.

$messages=array(

'same'=>'The:attributeand:othermustmatch.',

'size'=>'The:attributemustbeexactly:size.',

'between'=>'The:attributemustbebetween:min-:max.',

'in'=>'The:attributemustbeoneofthefollowingtypes::values',

);

CustomErrorMessages

PassingCustomMessagesIntoValidator

OtherValidationPlace-Holders

Sometimesyoumaywishtospecifyacustomerrormessagesonlyforaspecificfield:

$messages=array(

'email.required'=>'Weneedtoknowyoure-mailaddress!',

);

Insomecases,youmaywishtospecifyyourcustommessagesinalanguagefileinsteadofpassingthemdirectlytotheValidator.Todoso,addyourmessagestocustomarrayintheresources/lang/xx/validation.phplanguagefile.

'custom'=>array(

'email'=>array(

'required'=>'Weneedtoknowyoure-mailaddress!',

),

),

Laravelprovidesavarietyofhelpfulvalidationrules;however,youmaywishtospecifysomeofyourown.OnemethodofregisteringcustomvalidationrulesisusingtheValidator::extendmethod:

Validator::extend('foo',function($attribute,$value,$parameters)

{

return$value=='foo';

});

ThecustomvalidatorClosurereceivesthreearguments:thenameofthe$attributebeingvalidated,the$valueoftheattribute,andanarrayof$parameterspassedtotherule.

YoumayalsopassaclassandmethodtotheextendmethodinsteadofaClosure:

Validator::extend('foo','FooValidator@validate');

Notethatyouwillalsoneedtodefineanerrormessageforyourcustomrules.Youcandosoeitherusinganinlinecustommessagearrayorbyaddinganentryinthevalidationlanguagefile.

InsteadofusingClosurecallbackstoextendtheValidator,youmayalsoextendtheValidatorclassitself.Todoso,writeaValidatorclassthatextendsIlluminate\Validation\Validator.Youmayaddvalidationmethodstotheclassbyprefixingthemwithvalidate:

<?php

classCustomValidatorextendsIlluminate\Validation\Validator{

publicfunctionvalidateFoo($attribute,$value,$parameters)

{

return$value=='foo';

}

SpecifyingACustomMessageForAGivenAttribute

SpecifyingCustomMessagesInLanguageFiles

CustomValidationRules

RegisteringACustomValidationRule

ExtendingTheValidatorClass

}

Next,youneedtoregisteryourcustomValidatorextension:

Validator::resolver(function($translator,$data,$rules,$messages)

{

returnnewCustomValidator($translator,$data,$rules,$messages);

});

Whencreatingacustomvalidationrule,youmaysometimesneedtodefinecustomplace-holderreplacementsforerrormessages.YoumaydosobycreatingacustomValidatorasdescribedabove,andaddingareplaceXXXfunctiontothevalidator.

protectedfunctionreplaceFoo($message,$attribute,$rule,$parameters)

{

returnstr_replace(':foo',$parameters[0],$message);

}

Ifyouwouldliketoaddacustommessage"replacer"withoutextendingtheValidatorclass,youmayusetheValidator::replacermethod:

Validator::replacer('rule',function($message,$attribute,$rule,$parameters)

{

//

});

RegisteringACustomValidatorResolver

BasicUsageConfigurationRead/WriteConnectionsRunningQueriesDatabaseTransactionsAccessingConnectionsQueryLogging

QueryBuilderIntroductionSelectsJoinsAdvancedWheresAggregatesRawExpressionsInsertsUpdatesDeletesUnionsPessimisticLocking

EloquentORMIntroductionBasicUsageMassAssignmentInsert,Update,DeleteSoftDeletingTimestampsQueryScopesGlobalScopesRelationshipsQueryingRelationsEagerLoadingInsertingRelatedModelsTouchingParentTimestampsWorkingWithPivotTablesCollectionsAccessors&MutatorsDateMutatorsAttributeCastingModelEventsModelObserversConvertingToArrays/JSON

SchemaBuilderIntroductionCreating&DroppingTablesAddingColumnsChangingColumnsRenamingColumnsDroppingColumnsCheckingExistenceAddingIndexesForeignKeysDroppingIndexes

Database

DroppingTimestamps&SoftDeletesStorageEngines

Migrations&SeedingIntroductionCreatingMigrationsRunningMigrationsRollingBackMigrationsDatabaseSeeding

RedisIntroductionConfigurationUsagePipelining

ConfigurationRead/WriteConnectionsRunningQueriesDatabaseTransactionsAccessingConnectionsQueryLogging

Laravelmakesconnectingwithdatabasesandrunningqueriesextremelysimple.Thedatabaseconfigurationfileisconfig/database.php.Inthisfileyoumaydefineallofyourdatabaseconnections,aswellasspecifywhichconnectionshouldbeusedbydefault.Examplesforallofthesupporteddatabasesystemsareprovidedinthisfile.

CurrentlyLaravelsupportsfourdatabasesystems:MySQL,Postgres,SQLite,andSQLServer.

SometimesyoumaywishtouseonedatabaseconnectionforSELECTstatements,andanotherforINSERT,UPDATE,andDELETEstatements.Laravelmakesthisabreeze,andtheproperconnectionswillalwaysbeusedwhetheryouareusingrawqueries,thequerybuilder,ortheEloquentORM.

Toseehowread/writeconnectionsshouldbeconfigured,let'slookatthisexample:

'mysql'=>[

'read'=>[

'host'=>'192.168.1.1',

],

'write'=>[

'host'=>'196.168.1.2'

],

'driver'=>'mysql',

'database'=>'database',

'username'=>'root',

'password'=>'',

'charset'=>'utf8',

'collation'=>'utf8_unicode_ci',

'prefix'=>'',

],

Notethattwokeyshavebeenaddedtotheconfigurationarray:readandwrite.Bothofthesekeyshavearrayvaluescontainingasinglekey:host.Therestofthedatabaseoptionsforthereadandwriteconnectionswillbemergedfromthemainmysqlarray.So,weonlyneedtoplaceitemsinthereadandwritearraysifwewishtooverridethevaluesinthemainarray.So,inthiscase,192.168.1.1willbeusedasthe"read"connection,while192.168.1.2willbeusedasthe"write"connection.Thedatabasecredentials,prefix,characterset,andallotheroptionsinthemainmysqlarraywillbesharedacrossbothconnections.

Onceyouhaveconfiguredyourdatabaseconnection,youmayrunqueriesusingtheDBfacade.

$results=DB::select('select*fromuserswhereid=?',[1]);

BasicDatabaseUsage

Configuration

Read/WriteConnections

RunningQueries

RunningASelectQuery

Theselectmethodwillalwaysreturnanarrayofresults.

DB::insert('insertintousers(id,name)values(?,?)',[1,'Dayle']);

DB::update('updateuserssetvotes=100wherename=?',['John']);

DB::delete('deletefromusers');

Note:Theupdateanddeletestatementsreturnthenumberofrowsaffectedbytheoperation.

DB::statement('droptableusers');

YoumaylistenforqueryeventsusingtheDB::listenmethod:

DB::listen(function($sql,$bindings,$time)

{

//

});

Torunasetofoperationswithinadatabasetransaction,youmayusethetransactionmethod:

DB::transaction(function()

{

DB::table('users')->update(['votes'=>1]);

DB::table('posts')->delete();

});

Note:Anyexceptionthrownwithinthetransactionclosurewillcausethetransactiontoberolledbackautomatically.

Sometimesyoumayneedtobeginatransactionyourself:

DB::beginTransaction();

Youcanrollbackatransactionviatherollbackmethod:

RunningAnInsertStatement

RunningAnUpdateStatement

RunningADeleteStatement

RunningAGeneralStatement

ListeningForQueryEvents

DatabaseTransactions

DB::rollback();

Lastly,youcancommitatransactionviathecommitmethod:

DB::commit();

Whenusingmultipleconnections,youmayaccessthemviatheDB::connectionmethod:

$users=DB::connection('foo')->select(...);

Youmayalsoaccesstheraw,underlyingPDOinstance:

$pdo=DB::connection()->getPdo();

Sometimesyoumayneedtoreconnecttoagivendatabase:

DB::reconnect('foo');

IfyouneedtodisconnectfromthegivendatabaseduetoexceedingtheunderlyingPDOinstance'smax_connectionslimit,usethedisconnectmethod:

DB::disconnect('foo');

Bydefault,Laravelkeepsaloginmemoryofallqueriesthathavebeenrunforthecurrentrequest.However,insomecases,suchaswheninsertingalargenumberofrows,thiscancausetheapplicationtouseexcessmemory.Todisablethelog,youmayusethedisableQueryLogmethod:

DB::connection()->disableQueryLog();

Togetanarrayoftheexecutedqueries,youmayusethegetQueryLogmethod:

$queries=DB::getQueryLog();

AccessingConnections

QueryLogging

IntroductionSelectsJoinsAdvancedWheresAggregatesRawExpressionsInsertsUpdatesDeletesUnionsPessimisticLocking

Thedatabasequerybuilderprovidesaconvenient,fluentinterfacetocreatingandrunningdatabasequeries.Itcanbeusedtoperformmostdatabaseoperationsinyourapplication,andworksonallsupporteddatabasesystems.

Note:TheLaravelquerybuilderusesPDOparameterbindingthroughouttoprotectyourapplicationagainstSQLinjectionattacks.Thereisnoneedtocleanstringsbeingpassedasbindings.

$users=DB::table('users')->get();

foreach($usersas$user)

{

var_dump($user->name);

}

DB::table('users')->chunk(100,function($users)

{

foreach($usersas$user)

{

//

}

});

YoumaystopfurtherchunksfrombeingprocessedbyreturningfalsefromtheClosure:

DB::table('users')->chunk(100,function($users)

{

//

returnfalse;

});

QueryBuilder

Introduction

Selects

RetrievingAllRowsFromATable

ChunkingResultsFromATable

RetrievingASingleRowFromATable

$user=DB::table('users')->where('name','John')->first();

var_dump($user->name);

$name=DB::table('users')->where('name','John')->pluck('name');

$roles=DB::table('roles')->lists('title');

Thismethodwillreturnanarrayofroletitles.Youmayalsospecifyacustomkeycolumnforthereturnedarray:

$roles=DB::table('roles')->lists('title','name');

$users=DB::table('users')->select('name','email')->get();

$users=DB::table('users')->distinct()->get();

$users=DB::table('users')->select('nameasuser_name')->get();

$query=DB::table('users')->select('name');

$users=$query->addSelect('age')->get();

$users=DB::table('users')->where('votes','>',100)->get();

$users=DB::table('users')

->where('votes','>',100)

->orWhere('name','John')

->get();

$users=DB::table('users')

->whereBetween('votes',array(1,100))->get();

RetrievingASingleColumnFromARow

RetrievingAListOfColumnValues

SpecifyingASelectClause

AddingASelectClauseToAnExistingQuery

UsingWhereOperators

OrStatements

UsingWhereBetween

UsingWhereNotBetween

$users=DB::table('users')

->whereNotBetween('votes',array(1,100))->get();

$users=DB::table('users')

->whereIn('id',array(1,2,3))->get();

$users=DB::table('users')

->whereNotIn('id',array(1,2,3))->get();

$users=DB::table('users')

->whereNull('updated_at')->get();

$users=DB::table('users')

->orderBy('name','desc')

->groupBy('count')

->having('count','>',100)

->get();

$users=DB::table('users')->skip(10)->take(5)->get();

Thequerybuildermayalsobeusedtowritejoinstatements.Takealookatthefollowingexamples:

DB::table('users')

->join('contacts','users.id','=','contacts.user_id')

->join('orders','users.id','=','orders.user_id')

->select('users.id','contacts.phone','orders.price')

->get();

DB::table('users')

->leftJoin('posts','users.id','=','posts.user_id')

->get();

Youmayalsospecifymoreadvancedjoinclauses:

DB::table('users')

->join('contacts',function($join)

{

$join->on('users.id','=','contacts.user_id')->orOn(...);

})

UsingWhereInWithAnArray

UsingWhereNullToFindRecordsWithUnsetValues

OrderBy,GroupBy,AndHaving

Offset&Limit

Joins

BasicJoinStatement

LeftJoinStatement

->get();

Ifyouwouldliketousea"where"styleclauseonyourjoins,youmayusethewhereandorWheremethodsonajoin.Insteadofcomparingtwocolumns,thesemethodswillcomparethecolumnagainstavalue:

DB::table('users')

->join('contacts',function($join)

{

$join->on('users.id','=','contacts.user_id')

->where('contacts.user_id','>',5);

})

->get();

Sometimesyoumayneedtocreatemoreadvancedwhereclausessuchas"whereexists"ornestedparametergroupings.TheLaravelquerybuildercanhandletheseaswell:

DB::table('users')

->where('name','=','John')

->orWhere(function($query)

{

$query->where('votes','>',100)

->where('title','<>','Admin');

})

->get();

ThequeryabovewillproducethefollowingSQL:

select*fromuserswherename='John'or(votes>100andtitle<>'Admin')

DB::table('users')

->whereExists(function($query)

{

$query->select(DB::raw(1))

->from('orders')

->whereRaw('orders.user_id=users.id');

})

->get();

ThequeryabovewillproducethefollowingSQL:

select*fromusers

whereexists(

select1fromorderswhereorders.user_id=users.id

)

Thequerybuilderalsoprovidesavarietyofaggregatemethods,suchascount,max,min,avg,andsum.

AdvancedWheres

ParameterGrouping

ExistsStatements

Aggregates

$users=DB::table('users')->count();

$price=DB::table('orders')->max('price');

$price=DB::table('orders')->min('price');

$price=DB::table('orders')->avg('price');

$total=DB::table('users')->sum('votes');

Sometimesyoumayneedtousearawexpressioninaquery.Theseexpressionswillbeinjectedintothequeryasstrings,sobecarefulnottocreateanySQLinjectionpoints!Tocreatearawexpression,youmayusetheDB::rawmethod:

$users=DB::table('users')

->select(DB::raw('count(*)asuser_count,status'))

->where('status','<>',1)

->groupBy('status')

->get();

DB::table('users')->insert(

array('email'=>'john@example.com','votes'=>0)

);

Ifthetablehasanauto-incrementingid,useinsertGetIdtoinsertarecordandretrievetheid:

$id=DB::table('users')->insertGetId(

array('email'=>'john@example.com','votes'=>0)

);

Note:WhenusingPostgreSQLtheinsertGetIdmethodexpectstheauto-incrementingcolumntobenamed"id".

DB::table('users')->insert(array(

array('email'=>'taylor@example.com','votes'=>0),

array('email'=>'dayle@example.com','votes'=>0),

));

UsingAggregateMethods

RawExpressions

UsingARawExpression

Inserts

InsertingRecordsIntoATable

InsertingRecordsIntoATableWithAnAuto-IncrementingID

InsertingMultipleRecordsIntoATable

Updates

UpdatingRecordsInATable

DB::table('users')

->where('id',1)

->update(array('votes'=>1));

DB::table('users')->increment('votes');

DB::table('users')->increment('votes',5);

DB::table('users')->decrement('votes');

DB::table('users')->decrement('votes',5);

Youmayalsospecifyadditionalcolumnstoupdate:

DB::table('users')->increment('votes',1,array('name'=>'John'));

DB::table('users')->where('votes','<',100)->delete();

DB::table('users')->delete();

DB::table('users')->truncate();

Thequerybuilderalsoprovidesaquickwayto"union"twoqueriestogether:

$first=DB::table('users')->whereNull('first_name');

$users=DB::table('users')->whereNull('last_name')->union($first)->get();

TheunionAllmethodisalsoavailable,andhasthesamemethodsignatureasunion.

Thequerybuilderincludesafewfunctionstohelpyoudo"pessimisticlocking"onyourSELECTstatements.

ToruntheSELECTstatementwitha"sharedlock",youmayusethesharedLockmethodonaquery:

Incrementingordecrementingavalueofacolumn

Deletes

DeletingRecordsInATable

DeletingAllRecordsFromATable

TruncatingATable

Unions

PessimisticLocking

DB::table('users')->where('votes','>',100)->sharedLock()->get();

To"lockforupdate"onaSELECTstatement,youmayusethelockForUpdatemethodonaquery:

DB::table('users')->where('votes','>',100)->lockForUpdate()->get();

IntroductionBasicUsageMassAssignmentInsert,Update,DeleteSoftDeletingTimestampsQueryScopesGlobalScopesRelationshipsQueryingRelationsEagerLoadingInsertingRelatedModelsTouchingParentTimestampsWorkingWithPivotTablesCollectionsAccessors&MutatorsDateMutatorsAttributeCastingModelEventsModelObserversConvertingToArrays/JSON

TheEloquentORMincludedwithLaravelprovidesabeautiful,simpleActiveRecordimplementationforworkingwithyourdatabase.Eachdatabasetablehasacorresponding"Model"whichisusedtointeractwiththattable.

Beforegettingstarted,besuretoconfigureadatabaseconnectioninconfig/database.php.

Togetstarted,createanEloquentmodel.Modelstypicallyliveintheappdirectory,butyouarefreetoplacethemanywherethatcanbeauto-loadedaccordingtoyourcomposer.jsonfile.AllEloquentmodelsextendIlluminate\Database\Eloquent\Model.

classUserextendsModel{}

YoumayalsogenerateEloquentmodelsusingthemake:modelcommand:

phpartisanmake:modelUser

NotethatwedidnottellEloquentwhichtabletouseforourUsermodel.Thelower-case,pluralnameoftheclasswillbeusedasthetablenameunlessanothernameisexplicitlyspecified.So,inthiscase,EloquentwillassumetheUsermodelstoresrecordsintheuserstable.Youmayspecifyacustomtablebydefiningatablepropertyonyourmodel:

classUserextendsModel{

EloquentORM

Introduction

BasicUsage

DefiningAnEloquentModel

protected$table='my_users';

}

Note:Eloquentwillalsoassumethateachtablehasaprimarykeycolumnnamedid.YoumaydefineaprimaryKeypropertytooverridethisconvention.Likewise,youmaydefineaconnectionpropertytooverridethenameofthedatabaseconnectionthatshouldbeusedwhenutilizingthemodel.

Onceamodelisdefined,youarereadytostartretrievingandcreatingrecordsinyourtable.Notethatyouwillneedtoplaceupdated_atandcreated_atcolumnsonyourtablebydefault.Ifyoudonotwishtohavethesecolumnsautomaticallymaintained,setthe$timestampspropertyonyourmodeltofalse.

$users=User::all();

$user=User::find(1);

var_dump($user->name);

Note:AllmethodsavailableonthequerybuilderarealsoavailablewhenqueryingEloquentmodels.

Sometimesyoumaywishtothrowanexceptionifamodelisnotfound,allowingyoutocatchtheexceptionsusinganApp::errorhandleranddisplaya404page.

$model=User::findOrFail(1);

$model=User::where('votes','>',100)->firstOrFail();

Toregistertheerrorhandler,listenfortheModelNotFoundException

useIlluminate\Database\Eloquent\ModelNotFoundException;

App::error(function(ModelNotFoundException$e)

{

returnResponse::make('NotFound',404);

});

$users=User::where('votes','>',100)->take(10)->get();

foreach($usersas$user)

{

var_dump($user->name);

}

Ofcourse,youmayalsousethequerybuilderaggregatefunctions.

RetrievingAllModels

RetrievingARecordByPrimaryKey

RetrievingAModelByPrimaryKeyOrThrowAnException

QueryingUsingEloquentModels

EloquentAggregates

$count=User::where('votes','>',100)->count();

Ifyouareunabletogeneratethequeryyouneedviathefluentinterface,feelfreetousewhereRaw:

$users=User::whereRaw('age>?andvotes=100',array(25))->get();

Ifyouneedtoprocessalot(thousands)ofEloquentrecords,usingthechunkcommandwillallowyoutodowithouteatingallofyourRAM:

User::chunk(200,function($users)

{

foreach($usersas$user)

{

//

}

});

Thefirstargumentpassedtothemethodisthenumberofrecordsyouwishtoreceiveper"chunk".TheClosurepassedasthesecondargumentwillbecalledforeachchunkthatispulledfromthedatabase.

YoumayalsospecifywhichdatabaseconnectionshouldbeusedwhenrunninganEloquentquery.Simplyusetheonmethod:

$user=User::on('connection-name')->find(1);

Ifyouareusingread/writeconnections,youmayforcethequerytousethe"write"connectionwiththefollowingmethod:

$user=User::onWriteConnection()->find(1);

Whencreatinganewmodel,youpassanarrayofattributestothemodelconstructor.Theseattributesarethenassignedtothemodelviamass-assignment.Thisisconvenient;however,canbeaserioussecurityconcernwhenblindlypassinguserinputintoamodel.Ifuserinputisblindlypassedintoamodel,theuserisfreetomodifyanyandallofthemodel'sattributes.Forthisreason,allEloquentmodelsprotectagainstmass-assignmentbydefault.

Togetstarted,setthefillableorguardedpropertiesonyourmodel.

Thefillablepropertyspecifieswhichattributesshouldbemass-assignable.Thiscanbesetattheclassorinstancelevel.

classUserextendsModel{

protected$fillable=array('first_name','last_name','email');

}

ChunkingResults

SpecifyingTheQueryConnection

MassAssignment

DefiningFillableAttributesOnAModel

Inthisexample,onlythethreelistedattributeswillbemass-assignable.

Theinverseoffillableisguarded,andservesasa"black-list"insteadofa"white-list":

classUserextendsModel{

protected$guarded=array('id','password');

}

Note:Whenusingguarded,youshouldstillneverpassInput::get()oranyrawarrayofusercontrolledinputintoasaveorupdatemethod,asanycolumnthatisnotguardedmaybeupdated.

Intheexampleabove,theidandpasswordattributesmaynotbemassassigned.Allotherattributeswillbemassassignable.Youmayalsoblockallattributesfrommassassignmentusingtheguardproperty:

protected$guarded=array('*');

Tocreateanewrecordinthedatabasefromamodel,simplycreateanewmodelinstanceandcallthesavemethod.

$user=newUser;

$user->name='John';

$user->save();

Note:Typically,yourEloquentmodelswillhaveauto-incrementingkeys.However,ifyouwishtospecifyyourownkeys,settheincrementingpropertyonyourmodeltofalse.

Youmayalsousethecreatemethodtosaveanewmodelinasingleline.Theinsertedmodelinstancewillbereturnedtoyoufromthemethod.However,beforedoingso,youwillneedtospecifyeitherafillableorguardedattributeonthemodel,asallEloquentmodelsprotectagainstmass-assignment.

Aftersavingorcreatinganewmodelthatusesauto-incrementingIDs,youmayretrievetheIDbyaccessingtheobject'sidattribute:

$insertedId=$user->id;

classUserextendsModel{

protected$guarded=array('id','account_id');

}

DefiningGuardedAttributesOnAModel

BlockingAllAttributesFromMassAssignment

Insert,Update,Delete

SavingANewModel

SettingTheGuardedAttributesOnTheModel

//Createanewuserinthedatabase...

$user=User::create(array('name'=>'John'));

//Retrievetheuserbytheattributes,orcreateitifitdoesn'texist...

$user=User::firstOrCreate(array('name'=>'John'));

//Retrievetheuserbytheattributes,orinstantiateanewinstance...

$user=User::firstOrNew(array('name'=>'John'));

Toupdateamodel,youmayretrieveit,changeanattribute,andusethesavemethod:

$user=User::find(1);

$user->email='john@foo.com';

$user->save();

Sometimesyoumaywishtosavenotonlyamodel,butalsoallofitsrelationships.Todoso,youmayusethepushmethod:

$user->push();

Youmayalsorunupdatesasqueriesagainstasetofmodels:

$affectedRows=User::where('votes','>',100)->update(array('status'=>2));

Note:NomodeleventsarefiredwhenupdatingasetofmodelsviatheEloquentquerybuilder.

Todeleteamodel,simplycallthedeletemethodontheinstance:

$user=User::find(1);

$user->delete();

User::destroy(1);

User::destroy(array(1,2,3));

User::destroy(1,2,3);

Ofcourse,youmayalsorunadeletequeryonasetofmodels:

$affectedRows=User::where('votes','>',100)->delete();

UsingTheModelCreateMethod

UpdatingARetrievedModel

SavingAModelAndRelationships

DeletingAnExistingModel

DeletingAnExistingModelByKey

Ifyouwishtosimplyupdatethetimestampsonamodel,youmayusethetouchmethod:

$user->touch();

Whensoftdeletingamodel,itisnotactuallyremovedfromyourdatabase.Instead,adeleted_attimestampissetontherecord.Toenablesoftdeletesforamodel,applytheSoftDeletestothemodel:

useIlluminate\Database\Eloquent\SoftDeletes;

classUserextendsModel{

useSoftDeletes;

protected$dates=['deleted_at'];

}

Toaddadeleted_atcolumntoyourtable,youmayusethesoftDeletesmethodfromamigration:

$table->softDeletes();

Now,whenyoucallthedeletemethodonthemodel,thedeleted_atcolumnwillbesettothecurrenttimestamp.Whenqueryingamodelthatusessoftdeletes,the"deleted"modelswillnotbeincludedinqueryresults.

Toforcesoftdeletedmodelstoappearinaresultset,usethewithTrashedmethodonthequery:

$users=User::withTrashed()->where('account_id',1)->get();

ThewithTrashedmethodmaybeusedonadefinedrelationship:

$user->posts()->withTrashed()->get();

Ifyouwishtoonlyreceivesoftdeletedmodelsinyourresults,youmayusetheonlyTrashedmethod:

$users=User::onlyTrashed()->where('account_id',1)->get();

Torestoreasoftdeletedmodelintoanactivestate,usetherestoremethod:

$user->restore();

Youmayalsousetherestoremethodonaquery:

User::withTrashed()->where('account_id',1)->restore();

UpdatingOnlyTheModel'sTimestamps

SoftDeleting

ForcingSoftDeletedModelsIntoResults

LikewithwithTrashed,therestoremethodmayalsobeusedonrelationships:

$user->posts()->restore();

Ifyouwishtotrulyremoveamodelfromthedatabase,youmayusetheforceDeletemethod:

$user->forceDelete();

TheforceDeletemethodalsoworksonrelationships:

$user->posts()->forceDelete();

Todetermineifagivenmodelinstancehasbeensoftdeleted,youmayusethetrashedmethod:

if($user->trashed())

{

//

}

Bydefault,Eloquentwillmaintainthecreated_atandupdated_atcolumnsonyourdatabasetableautomatically.SimplyaddthesetimestampcolumnstoyourtableandEloquentwilltakecareoftherest.IfyoudonotwishforEloquenttomaintainthesecolumns,addthefollowingpropertytoyourmodel:

classUserextendsModel{

protected$table='users';

public$timestamps=false;

}

Ifyouwishtocustomizetheformatofyourtimestamps,youmayoverridethegetDateFormatmethodinyourmodel:

classUserextendsModel{

protectedfunctiongetDateFormat()

{

return'U';

}

}

Timestamps

DisablingAutoTimestamps

ProvidingACustomTimestampFormat

QueryScopes

DefiningAQueryScope

Scopesallowyoutoeasilyre-usequerylogicinyourmodels.Todefineascope,simplyprefixamodelmethodwithscope:

classUserextendsModel{

publicfunctionscopePopular($query)

{

return$query->where('votes','>',100);

}

publicfunctionscopeWomen($query)

{

return$query->whereGender('W');

}

}

$users=User::popular()->women()->orderBy('created_at')->get();

Sometimesyoumaywishtodefineascopethatacceptsparameters.Justaddyourparameterstoyourscopefunction:

classUserextendsModel{

publicfunctionscopeOfType($query,$type)

{

return$query->whereType($type);

}

}

Thenpasstheparameterintothescopecall:

$users=User::ofType('member')->get();

Sometimesyoumaywishtodefineascopethatappliestoallqueriesperformedonamodel.Inessence,thisishowEloquent'sown"softdelete"featureworks.GlobalscopesaredefinedusingacombinationofPHPtraitsandanimplementationofIlluminate\Database\Eloquent\ScopeInterface.

First,let'sdefineatrait.Forthisexample,we'llusetheSoftDeletesthatshipswithLaravel:

traitSoftDeletes{

/**

*Bootthesoftdeletingtraitforamodel.

*

*@returnvoid

*/

publicstaticfunctionbootSoftDeletes()

{

static::addGlobalScope(newSoftDeletingScope);

}

}

UtilizingAQueryScope

DynamicScopes

GlobalScopes

IfanEloquentmodelusesatraitthathasamethodmatchingthebootNameOfTraitnamingconvention,thattraitmethodwillbecalledwhentheEloquentmodelisbooted,givingyouanopportunitytoregisteraglobalscope,ordoanythingelseyouwant.AscopemustimplementScopeInterface,whichspecifiestwomethods:applyandremove.

TheapplymethodreceivesanIlluminate\Database\Eloquent\Builderquerybuilderobject,andisresponsibleforaddinganyadditionalwhereclausesthatthescopewishestoadd.TheremovemethodalsoreceivesaBuilderobjectandisresponsibleforreversingtheactiontakenbyapply.Inotherwords,removeshouldremovethewhereclause(oranyotherclause)thatwasadded.So,forourSoftDeletingScope,themethodslooksomethinglikethis:

/**

*ApplythescopetoagivenEloquentquerybuilder.

*

*@param\Illuminate\Database\Eloquent\Builder$builder

*@returnvoid

*/

publicfunctionapply(Builder$builder)

{

$model=$builder->getModel();

$builder->whereNull($model->getQualifiedDeletedAtColumn());

}

/**

*RemovethescopefromthegivenEloquentquerybuilder.

*

*@param\Illuminate\Database\Eloquent\Builder$builder

*@returnvoid

*/

publicfunctionremove(Builder$builder)

{

$column=$builder->getModel()->getQualifiedDeletedAtColumn();

$query=$builder->getQuery();

foreach((array)$query->wheresas$key=>$where)

{

//Ifthewhereclauseisasoftdeletedateconstraint,wewillremoveitfrom

//thequeryandresetthekeysonthewheres.Thisallowsthisdeveloperto

//includedeletedmodelinarelationshipresultsetthatislazyloaded.

if($this->isSoftDeleteConstraint($where,$column))

{

unset($query->wheres[$key]);

$query->wheres=array_values($query->wheres);

}

}

}

Ofcourse,yourdatabasetablesareprobablyrelatedtooneanother.Forexample,ablogpostmayhavemanycomments,oranordercouldberelatedtotheuserwhoplacedit.Eloquentmakesmanagingandworkingwiththeserelationshipseasy.Laravelsupportsmanytypesofrelationships:

OneToOneOneToManyManyToManyHasManyThroughPolymorphicRelationsManyToManyPolymorphicRelations

Aone-to-onerelationshipisaverybasicrelation.Forexample,aUsermodelmighthaveonePhone.Wecandefinethis

Relationships

OneToOne

DefiningAOneToOneRelation

relationinEloquent:

classUserextendsModel{

publicfunctionphone()

{

return$this->hasOne('App\Phone');

}

}

ThefirstargumentpassedtothehasOnemethodisthenameoftherelatedmodel.Oncetherelationshipisdefined,wemayretrieveitusingEloquent'sdynamicproperties:

$phone=User::find(1)->phone;

TheSQLperformedbythisstatementwillbeasfollows:

select*fromuserswhereid=1

select*fromphoneswhereuser_id=1

TakenotethatEloquentassumestheforeignkeyoftherelationshipbasedonthemodelname.Inthiscase,Phonemodelisassumedtouseauser_idforeignkey.Ifyouwishtooverridethisconvention,youmaypassasecondargumenttothehasOnemethod.Furthermore,youmaypassathirdargumenttothemethodtospecifywhichlocalcolumnthatshouldbeusedfortheassociation:

return$this->hasOne('App\Phone','foreign_key');

return$this->hasOne('App\Phone','foreign_key','local_key');

TodefinetheinverseoftherelationshiponthePhonemodel,weusethebelongsTomethod:

classPhoneextendsModel{

publicfunctionuser()

{

return$this->belongsTo('App\User');

}

}

Intheexampleabove,Eloquentwilllookforauser_idcolumnonthephonestable.Ifyouwouldliketodefineadifferentforeignkeycolumn,youmaypassitasthesecondargumenttothebelongsTomethod:

classPhoneextendsModel{

publicfunctionuser()

{

return$this->belongsTo('App\User','local_key');

}

}

Additionally,youpassathirdparameterwhichspecifiesthenameoftheassociatedcolumnontheparenttable:

DefiningTheInverseOfARelation

classPhoneextendsModel{

publicfunctionuser()

{

return$this->belongsTo('App\User','local_key','parent_key');

}

}

Anexampleofaone-to-manyrelationisablogpostthat"hasmany"comments.Wecanmodelthisrelationlikeso:

classPostextendsModel{

publicfunctioncomments()

{

return$this->hasMany('App\Comment');

}

}

Nowwecanaccessthepost'scommentsthroughthedynamicproperty:

$comments=Post::find(1)->comments;

Ifyouneedtoaddfurtherconstraintstowhichcommentsareretrieved,youmaycallthecommentsmethodandcontinuechainingconditions:

$comments=Post::find(1)->comments()->where('title','=','foo')->first();

Again,youmayoverridetheconventionalforeignkeybypassingasecondargumenttothehasManymethod.And,likethehasOnerelation,thelocalcolumnmayalsobespecified:

return$this->hasMany('App\Comment','foreign_key');

return$this->hasMany('App\Comment','foreign_key','local_key');

TodefinetheinverseoftherelationshipontheCommentmodel,weusethebelongsTomethod:

classCommentextendsModel{

publicfunctionpost()

{

return$this->belongsTo('App\Post');

}

}

Many-to-manyrelationsareamorecomplicatedrelationshiptype.Anexampleofsucharelationshipisauserwithmanyroles,wheretherolesarealsosharedbyotherusers.Forexample,manyusersmayhavetheroleof"Admin".Threedatabasetablesareneededforthisrelationship:users,roles,androle_user.Therole_usertableisderivedfromthe

OneToMany

DefiningTheInverseOfARelation

ManyToMany

alphabeticalorderoftherelatedmodelnames,andshouldhaveuser_idandrole_idcolumns.

Wecandefineamany-to-manyrelationusingthebelongsToManymethod:

classUserextendsModel{

publicfunctionroles()

{

return$this->belongsToMany('App\Role');

}

}

Now,wecanretrievetherolesthroughtheUsermodel:

$roles=User::find(1)->roles;

Ifyouwouldliketouseanunconventionaltablenameforyourpivottable,youmaypassitasthesecondargumenttothebelongsToManymethod:

return$this->belongsToMany('App\Role','user_roles');

Youmayalsooverridetheconventionalassociatedkeys:

return$this->belongsToMany('App\Role','user_roles','user_id','foo_id');

Ofcourse,youmayalsodefinetheinverseoftherelationshipontheRolemodel:

classRoleextendsModel{

publicfunctionusers()

{

return$this->belongsToMany('App\User');

}

}

The"hasmanythrough"relationprovidesaconvenientshort-cutforaccessingdistantrelationsviaanintermediaterelation.Forexample,aCountrymodelmighthavemanyPostthroughaUsermodel.Thetablesforthisrelationshipwouldlooklikethis:

countries

id-integer

name-string

users

id-integer

country_id-integer

name-string

posts

id-integer

user_id-integer

title-string

Eventhoughthepoststabledoesnotcontainacountry_idcolumn,thehasManyThroughrelationwillallowustoaccessa

HasManyThrough

country'spostsvia$country->posts.Let'sdefinetherelationship:

classCountryextendsModel{

publicfunctionposts()

{

return$this->hasManyThrough('App\Post','User');

}

}

Ifyouwouldliketomanuallyspecifythekeysoftherelationship,youmaypassthemasthethirdandfourthargumentstothemethod:

classCountryextendsModel{

publicfunctionposts()

{

return$this->hasManyThrough('App\Post','User','country_id','user_id');

}

}

Polymorphicrelationsallowamodeltobelongtomorethanoneothermodel,onasingleassociation.Forexample,youmighthaveaphotomodelthatbelongstoeitherastaffmodeloranordermodel.Wewoulddefinethisrelationlikeso:

classPhotoextendsModel{

publicfunctionimageable()

{

return$this->morphTo();

}

}

classStaffextendsModel{

publicfunctionphotos()

{

return$this->morphMany('App\Photo','imageable');

}

}

classOrderextendsModel{

publicfunctionphotos()

{

return$this->morphMany('App\Photo','imageable');

}

}

Now,wecanretrievethephotosforeitherastaffmemberoranorder:

$staff=Staff::find(1);

foreach($staff->photosas$photo)

{

//

}

PolymorphicRelations

RetrievingAPolymorphicRelation

However,thetrue"polymorphic"magiciswhenyouaccessthestaffororderfromthePhotomodel:

$photo=Photo::find(1);

$imageable=$photo->imageable;

TheimageablerelationonthePhotomodelwillreturneitheraStafforOrderinstance,dependingonwhichtypeofmodelownsthephoto.

Tohelpunderstandhowthisworks,let'sexplorethedatabasestructureforapolymorphicrelation:

staff

id-integer

name-string

orders

id-integer

price-integer

photos

id-integer

path-string

imageable_id-integer

imageable_type-string

Thekeyfieldstonoticeherearetheimageable_idandimageable_typeonthephotostable.TheIDwillcontaintheIDvalueof,inthisexample,theowningstaffororder,whilethetypewillcontaintheclassnameoftheowningmodel.ThisiswhatallowstheORMtodeterminewhichtypeofowningmodeltoreturnwhenaccessingtheimageablerelation.

Inadditiontotraditionalpolymorphicrelations,youmayalsospecifymany-to-manypolymorphicrelations.Forexample,ablogPostandVideomodelcouldshareapolymorphicrelationtoaTagmodel.First,let'sexaminethetablestructure:

posts

id-integer

name-string

videos

id-integer

name-string

tags

id-integer

name-string

taggables

tag_id-integer

taggable_id-integer

taggable_type-string

Next,we'rereadytosetuptherelationshipsonthemodel.ThePostandVideomodelwillbothhaveamorphToManyrelationshipviaatagsmethod:

classPostextendsModel{

RetrievingTheOwnerOfAPolymorphicRelation

PolymorphicRelationTableStructure

ManyToManyPolymorphicRelations

PolymorphicManyToManyRelationTableStructure

publicfunctiontags()

{

return$this->morphToMany('App\Tag','taggable');

}

}

TheTagmodelmaydefineamethodforeachofitsrelationships:

classTagextendsModel{

publicfunctionposts()

{

return$this->morphedByMany('App\Post','taggable');

}

publicfunctionvideos()

{

return$this->morphedByMany('App\Video','taggable');

}

}

Whenaccessingtherecordsforamodel,youmaywishtolimityourresultsbasedontheexistenceofarelationship.Forexample,youwishtopullallblogpoststhathaveatleastonecomment.Todoso,youmayusethehasmethod:

$posts=Post::has('comments')->get();

Youmayalsospecifyanoperatorandacount:

$posts=Post::has('comments','>=',3)->get();

Nestedhasstatementsmayalsobeconstructedusing"dot"notation:

$posts=Post::has('comments.votes')->get();

Ifyouneedevenmorepower,youmayusethewhereHasandorWhereHasmethodstoput"where"conditionsonyourhasqueries:

$posts=Post::whereHas('comments',function($q)

{

$q->where('content','like','foo%');

})->get();

Eloquentallowsyoutoaccessyourrelationsviadynamicproperties.Eloquentwillautomaticallyloadtherelationshipforyou,andisevensmartenoughtoknowwhethertocalltheget(forone-to-manyrelationships)orfirst(forone-to-onerelationships)method.Itwillthenbeaccessibleviaadynamicpropertybythesamenameastherelation.Forexample,withthefollowingmodel$phone:

QueryingRelations

QueryingRelationsWhenSelecting

DynamicProperties

classPhoneextendsModel{

publicfunctionuser()

{

return$this->belongsTo('App\User');

}

}

$phone=Phone::find(1);

Insteadofechoingtheuser'semaillikethis:

echo$phone->user()->first()->email;

Itmaybeshortenedtosimply:

echo$phone->user->email;

Note:RelationshipsthatreturnmanyresultswillreturnaninstanceoftheIlluminate\Database\Eloquent\Collectionclass.

EagerloadingexiststoalleviatetheN+1queryproblem.Forexample,consideraBookmodelthatisrelatedtoAuthor.Therelationshipisdefinedlikeso:

classBookextendsModel{

publicfunctionauthor()

{

return$this->belongsTo('App\Author');

}

}

Now,considerthefollowingcode:

foreach(Book::all()as$book)

{

echo$book->author->name;

}

Thisloopwillexecute1querytoretrieveallofthebooksonthetable,thenanotherqueryforeachbooktoretrievetheauthor.So,ifwehave25books,thisloopwouldrun26queries.

Thankfully,wecanuseeagerloadingtodrasticallyreducethenumberofqueries.Therelationshipsthatshouldbeeagerloadedmaybespecifiedviathewithmethod:

foreach(Book::with('author')->get()as$book)

{

echo$book->author->name;

}

Intheloopabove,onlytwoquerieswillbeexecuted:

EagerLoading

select*frombooks

select*fromauthorswhereidin(1,2,3,4,5,...)

Wiseuseofeagerloadingcandrasticallyincreasetheperformanceofyourapplication.

Ofcourse,youmayeagerloadmultiplerelationshipsatonetime:

$books=Book::with('author','publisher')->get();

Youmayeveneagerloadnestedrelationships:

$books=Book::with('author.contacts')->get();

Intheexampleabove,theauthorrelationshipwillbeeagerloaded,andtheauthor'scontactsrelationwillalsobeloaded.

Sometimesyoumaywishtoeagerloadarelationship,butalsospecifyaconditionfortheeagerload.Here'sanexample:

$users=User::with(array('posts'=>function($query)

{

$query->where('title','like','%first%');

}))->get();

Inthisexample,we'reeagerloadingtheuser'sposts,butonlyifthepost'stitlecolumncontainstheword"first".

Ofcourse,eagerloadingClosuresaren'tlimitedto"constraints".Youmayalsoapplyorders:

$users=User::with(array('posts'=>function($query)

{

$query->orderBy('created_at','desc');

}))->get();

Itisalsopossibletoeagerlyloadrelatedmodelsdirectlyfromanalreadyexistingmodelcollection.Thismaybeusefulwhendynamicallydecidingwhethertoloadrelatedmodelsornot,orincombinationwithcaching.

$books=Book::all();

$books->load('author','publisher');

Youwilloftenneedtoinsertnewrelatedmodels.Forexample,youmaywishtoinsertanewcommentforapost.Insteadofmanuallysettingthepost_idforeignkeyonthemodel,youmayinsertthenewcommentfromitsparentPostmodeldirectly:

EagerLoadConstraints

LazyEagerLoading

InsertingRelatedModels

AttachingARelatedModel

$comment=newComment(array('message'=>'Anewcomment.'));

$post=Post::find(1);

$comment=$post->comments()->save($comment);

Inthisexample,thepost_idfieldwillautomaticallybesetontheinsertedcomment.

Ifyouneedtosavemultiplerelatedmodels:

$comments=array(

newComment(array('message'=>'Anewcomment.')),

newComment(array('message'=>'Anothercomment.')),

newComment(array('message'=>'Thelatestcomment.'))

);

$post=Post::find(1);

$post->comments()->saveMany($comments);

WhenupdatingabelongsTorelationship,youmayusetheassociatemethod.Thismethodwillsettheforeignkeyonthechildmodel:

$account=Account::find(10);

$user->account()->associate($account);

$user->save();

Youmayalsoinsertrelatedmodelswhenworkingwithmany-to-manyrelations.Let'scontinueusingourUserandRolemodelsasexamples.Wecaneasilyattachnewrolestoauserusingtheattachmethod:

$user=User::find(1);

$user->roles()->attach(1);

Youmayalsopassanarrayofattributesthatshouldbestoredonthepivottablefortherelation:

$user->roles()->attach(1,array('expires'=>$expires));

Ofcourse,theoppositeofattachisdetach:

$user->roles()->detach(1);

BothattachanddetachalsotakearraysofIDsasinput:

$user=User::find(1);

$user->roles()->detach([1,2,3]);

AssociatingModels(BelongsTo)

InsertingRelatedModels(ManyToMany)

AttachingManyToManyModels

$user->roles()->attach([1=>['attribute1'=>'value1'],2,3]);

Youmayalsousethesyncmethodtoattachrelatedmodels.ThesyncmethodacceptsanarrayofIDstoplaceonthepivottable.Afterthisoperationiscomplete,onlytheIDsinthearraywillbeontheintermediatetableforthemodel:

$user->roles()->sync(array(1,2,3));

YoumayalsoassociateotherpivottablevalueswiththegivenIDs:

$user->roles()->sync(array(1=>array('expires'=>true)));

Sometimesyoumaywishtocreateanewrelatedmodelandattachitinasinglecommand.Forthisoperation,youmayusethesavemethod:

$role=newRole(array('name'=>'Editor'));

User::find(1)->roles()->save($role);

Inthisexample,thenewRolemodelwillbesavedandattachedtotheusermodel.Youmayalsopassanarrayofattributestoplaceonthejoiningtableforthisoperation:

User::find(1)->roles()->save($role,array('expires'=>$expires));

WhenamodelbelongsToanothermodel,suchasaCommentwhichbelongstoaPost,itisoftenhelpfultoupdatetheparent'stimestampwhenthechildmodelisupdated.Forexample,whenaCommentmodelisupdated,youmaywanttoautomaticallytouchtheupdated_attimestampoftheowningPost.Eloquentmakesiteasy.Justaddatouchespropertycontainingthenamesoftherelationshipstothechildmodel:

classCommentextendsModel{

protected$touches=array('post');

publicfunctionpost()

{

return$this->belongsTo('App\Post');

}

}

Now,whenyouupdateaComment,theowningPostwillhaveitsupdated_atcolumnupdated:

$comment=Comment::find(1);

$comment->text='Edittothiscomment!';

$comment->save();

UsingSyncToAttachManyToManyModels

AddingPivotDataWhenSyncing

TouchingParentTimestamps

Asyouhavealreadylearned,workingwithmany-to-manyrelationsrequiresthepresenceofanintermediatetable.Eloquentprovidessomeveryhelpfulwaysofinteractingwiththistable.Forexample,let'sassumeourUserobjecthasmanyRoleobjectsthatitisrelatedto.Afteraccessingthisrelationship,wemayaccessthepivottableonthemodels:

$user=User::find(1);

foreach($user->rolesas$role)

{

echo$role->pivot->created_at;

}

NoticethateachRolemodelweretrieveisautomaticallyassignedapivotattribute.Thisattributecontainsamodelrepresentingtheintermediatetable,andmaybeusedasanyotherEloquentmodel.

Bydefault,onlythekeyswillbepresentonthepivotobject.Ifyourpivottablecontainsextraattributes,youmustspecifythemwhendefiningtherelationship:

return$this->belongsToMany('App\Role')->withPivot('foo','bar');

NowthefooandbarattributeswillbeaccessibleonourpivotobjectfortheRolemodel.

Ifyouwantyourpivottabletohaveautomaticallymaintainedcreated_atandupdated_attimestamps,usethewithTimestampsmethodontherelationshipdefinition:

return$this->belongsToMany('App\Role')->withTimestamps();

Todeleteallrecordsonthepivottableforamodel,youmayusethedetachmethod:

User::find(1)->roles()->detach();

Notethatthisoperationdoesnotdeleterecordsfromtherolestable,butonlyfromthepivottable.

Sometimesyoumayneedtoupdateyourpivottable,butnotdetachit.IfyouwishtoupdateyourpivottableinplaceyoumayuseupdateExistingPivotmethodlikeso:

User::find(1)->roles()->updateExistingPivot($roleId,$attributes);

LaravelalsoallowsyoutodefineacustomPivotmodel.Todefineacustommodel,firstcreateyourown"Base"modelclassthatextendsEloquent.InyourotherEloquentmodels,extendthiscustombasemodelinsteadofthedefaultEloquentbase.Inyourbasemodel,addthefollowingfunctionthatreturnsaninstanceofyourcustomPivotmodel:

publicfunctionnewPivot(Model$parent,array$attributes,$table,$exists)

{

returnnewYourCustomPivot($parent,$attributes,$table,$exists);

WorkingWithPivotTables

DeletingRecordsOnAPivotTable

UpdatingARecordOnAPivotTable

DefiningACustomPivotModel

}

Allmulti-resultsetsreturnedbyEloquent,eitherviathegetmethodorarelationship,willreturnacollectionobject.ThisobjectimplementstheIteratorAggregatePHPinterfacesoitcanbeiteratedoverlikeanarray.However,thisobjectalsohasavarietyofotherhelpfulmethodsforworkingwithresultsets.

Forexample,wemaydetermineifaresultsetcontainsagivenprimarykeyusingthecontainsmethod:

$roles=User::find(1)->roles;

if($roles->contains(2))

{

//

}

CollectionsmayalsobeconvertedtoanarrayorJSON:

$roles=User::find(1)->roles->toArray();

$roles=User::find(1)->roles->toJson();

Ifacollectioniscasttoastring,itwillbereturnedasJSON:

$roles=(string)User::find(1)->roles;

Eloquentcollectionsalsocontainafewhelpfulmethodsforloopingandfilteringtheitemstheycontain:

$roles=$user->roles->each(function($role)

{

//

});

Whenfilteringcollections,thecallbackprovidedwillbeusedascallbackforarray_filter.

$users=$users->filter(function($user)

{

return$user->isAdmin();

});

Note:WhenfilteringacollectionandconvertingittoJSON,trycallingthevaluesfunctionfirsttoresetthearray'skeys.

$roles=User::find(1)->roles;

Collections

CheckingIfACollectionContainsAKey

IteratingCollections

FilteringCollections

ApplyingACallbackToEachCollectionObject

$roles->each(function($role)

{

//

});

$roles=$roles->sortBy(function($role)

{

return$role->created_at;

});

$roles=$roles->sortBy('created_at');

Sometimes,youmaywishtoreturnacustomCollectionobjectwithyourownaddedmethods.YoumayspecifythisonyourEloquentmodelbyoverridingthenewCollectionmethod:

classUserextendsModel{

publicfunctionnewCollection(array$models=array())

{

returnnewCustomCollection($models);

}

}

Eloquentprovidesaconvenientwaytotransformyourmodelattributeswhengettingorsettingthem.SimplydefineagetFooAttributemethodonyourmodeltodeclareanaccessor.Keepinmindthatthemethodsshouldfollowcamel-casing,eventhoughyourdatabasecolumnsaresnake-case:

classUserextendsModel{

publicfunctiongetFirstNameAttribute($value)

{

returnucfirst($value);

}

}

Intheexampleabove,thefirst_namecolumnhasanaccessor.Notethatthevalueoftheattributeispassedtotheaccessor.

Mutatorsaredeclaredinasimilarfashion:

classUserextendsModel{

SortingACollectionByAValue

SortingACollectionByAValue

ReturningACustomCollectionType

Accessors&Mutators

DefiningAnAccessor

DefiningAMutator

publicfunctionsetFirstNameAttribute($value)

{

$this->attributes['first_name']=strtolower($value);

}

}

Bydefault,Eloquentwillconvertthecreated_atandupdated_atcolumnstoinstancesofCarbon,whichprovidesanassortmentofhelpfulmethods,andextendsthenativePHPDateTimeclass.

Youmaycustomizewhichfieldsareautomaticallymutated,andevencompletelydisablethismutation,byoverridingthegetDatesmethodofthemodel:

publicfunctiongetDates()

{

returnarray('created_at');

}

Whenacolumnisconsideredadate,youmaysetitsvaluetoaUNIXtimestamp,datestring(Y-m-d),date-timestring,andofcourseaDateTime/Carboninstance.

Tototallydisabledatemutations,simplyreturnanemptyarrayfromthegetDatesmethod:

publicfunctiongetDates()

{

returnarray();

}

Ifyouhavesomeattributesthatyouwanttoalwaysconverttoanotherdata-type,youmayaddtheattributetothecastspropertyofyourmodel.Otherwise,youwillhavetodefineamutatorforeachoftheattributes,whichcanbetimeconsuming.Hereisanexampleofusingthecastsproperty:

/**

*Theattributesthatshouldbecastedtonativetypes.

*

*@vararray

*/

protected$casts=[

'is_admin'=>'boolean',

];

Nowtheis_adminattributewillalwaysbecasttoabooleanwhenyouaccessit,eveniftheunderlyingvalueisstoredinthedatabaseasaninteger.Othersupportedcasttypesare:integer,real,float,double,string,boolean,andarray.

ThearraycastisparticularlyusefulforworkingwithcolumnsthatarestoredasserializedJSON.Forexample,ifyourdatabasehasaTEXTtypefieldthatcontainsserializedJSON,addingthearraycasttothatattributewillautomaticallydeserializetheattributetoaPHParraywhenyouaccessitonyourEloquentmodel:

/**

*Theattributesthatshouldbecastedtonativetypes.

*

*@vararray

DateMutators

AttributeCasting

*/

protected$casts=[

'options'=>'array',

];

Now,whenyouutilizetheEloquentmodel:

$user=User::find(1);

//$optionsisanarray...

$options=$user->options;

//optionsisautomaticallyserializedbacktoJSON...

$user->options=['foo'=>'bar'];

Eloquentmodelsfireseveralevents,allowingyoutohookintovariouspointsinthemodel'slifecycleusingthefollowingmethods:creating,created,updating,updated,saving,saved,deleting,deleted,restoring,restored.

Wheneveranewitemissavedforthefirsttime,thecreatingandcreatedeventswillfire.Ifanitemisnotnewandthesavemethodiscalled,theupdating/updatedeventswillfire.Inbothcases,thesaving/savedeventswillfire.

Iffalseisreturnedfromthecreating,updating,saving,ordeletingevents,theactionwillbecancelled:

User::creating(function($user)

{

if(!$user->isValid())returnfalse;

});

YourEventServiceProviderservesasaconvenientplacetoregisteryourmodeleventbindings.Forexample:

/**

*Registeranyothereventsforyourapplication.

*

*@param\Illuminate\Contracts\Events\Dispatcher$events

*@returnvoid

*/

publicfunctionboot(DispatcherContract$events)

{

parent::boot($events);

User::creating(function($user)

{

//

});

}

Toconsolidatethehandlingofmodelevents,youmayregisteramodelobserver.Anobserverclassmayhavemethodsthatcorrespondtothevariousmodelevents.Forexample,creating,updating,savingmethodsmaybeonanobserver,inadditiontoanyothermodeleventname.

So,forexample,amodelobservermightlooklikethis:

ModelEvents

CancellingSaveOperationsViaEvents

WhereToRegisterEventListeners

ModelObservers

classUserObserver{

publicfunctionsaving($model)

{

//

}

publicfunctionsaved($model)

{

//

}

}

Youmayregisteranobserverinstanceusingtheobservemethod:

User::observe(newUserObserver);

WhenbuildingJSONAPIs,youmayoftenneedtoconvertyourmodelsandrelationshipstoarraysorJSON.So,Eloquentincludesmethodsfordoingso.Toconvertamodelanditsloadedrelationshiptoanarray,youmayusethetoArraymethod:

$user=User::with('roles')->first();

return$user->toArray();

Notethatentirecollectionsofmodelsmayalsobeconvertedtoarrays:

returnUser::all()->toArray();

ToconvertamodeltoJSON,youmayusethetoJsonmethod:

returnUser::find(1)->toJson();

Notethatwhenamodelorcollectioniscasttoastring,itwillbeconvertedtoJSON,meaningyoucanreturnEloquentobjectsdirectlyfromyourapplication'sroutes!

Route::get('users',function()

{

returnUser::all();

});

Sometimesyoumaywishtolimittheattributesthatareincludedinyourmodel'sarrayorJSONform,suchaspasswords.

ConvertingToArrays/JSON

ConvertingAModelToAnArray

ConvertingAModelToJSON

ReturningAModelFromARoute

HidingAttributesFromArrayOrJSONConversion

Todoso,addahiddenpropertydefinitiontoyourmodel:

classUserextendsModel{

protected$hidden=array('password');

}

Note:Whenhidingrelationships,usetherelationship'smethodname,notthedynamicaccessorname.

Alternatively,youmayusethevisiblepropertytodefineawhite-list:

protected$visible=array('first_name','last_name');

Occasionally,youmayneedtoaddarrayattributesthatdonothaveacorrespondingcolumninyourdatabase.Todoso,simplydefineanaccessorforthevalue:

publicfunctiongetIsAdminAttribute()

{

return$this->attributes['admin']=='yes';

}

Onceyouhavecreatedtheaccessor,justaddthevaluetotheappendspropertyonthemodel:

protected$appends=array('is_admin');

Oncetheattributehasbeenaddedtotheappendslist,itwillbeincludedinboththemodel'sarrayandJSONforms.Attributesintheappendsarrayrespectthevisibleandhiddenconfigurationonthemodel.

IntroductionCreating&DroppingTablesAddingColumnsChangingColumnsRenamingColumnsDroppingColumnsCheckingExistenceAddingIndexesForeignKeysDroppingIndexesDroppingTimestamps&SoftDeletesStorageEngines

TheLaravelSchemaclassprovidesadatabaseagnosticwayofmanipulatingtables.ItworkswellwithallofthedatabasessupportedbyLaravel,andhasaunifiedAPIacrossallofthesesystems.

Tocreateanewdatabasetable,theSchema::createmethodisused:

Schema::create('users',function($table)

{

$table->increments('id');

});

Thefirstargumentpassedtothecreatemethodisthenameofthetable,andthesecondisaClosurewhichwillreceiveaBlueprintobjectwhichmaybeusedtodefinethenewtable.

Torenameanexistingdatabasetable,therenamemethodmaybeused:

Schema::rename($from,$to);

Tospecifywhichconnectiontheschemaoperationshouldtakeplaceon,usetheSchema::connectionmethod:

Schema::connection('foo')->create('users',function($table)

{

$table->increments('id');

});

Todropatable,youmayusetheSchema::dropmethod:

Schema::drop('users');

Schema::dropIfExists('users');

SchemaBuilder

Introduction

Creating&DroppingTables

AddingColumns

Toupdateanexistingtable,wewillusetheSchema::tablemethod:

Schema::table('users',function($table)

{

$table->string('email');

});

Thetablebuildercontainsavarietyofcolumntypesthatyoumayusewhenbuildingyourtables:

Command Description

$table->bigIncrements('id'); IncrementingIDusinga"biginteger"equivalent.

$table->bigInteger('votes'); BIGINTequivalenttothetable

$table->binary('data'); BLOBequivalenttothetable

$table->boolean('confirmed'); BOOLEANequivalenttothetable

$table->char('name',4); CHARequivalentwithalength

$table->date('created_at'); DATEequivalenttothetable

$table->dateTime('created_at'); DATETIMEequivalenttothetable

$table->decimal('amount',5,2); DECIMALequivalentwithaprecisionandscale

$table->double('column',15,8);DOUBLEequivalentwithprecision,15digitsintotaland8afterthedecimalpoint

$table->enum('choices',array('foo',

'bar'));ENUMequivalenttothetable

$table->float('amount'); FLOATequivalenttothetable

$table->increments('id'); IncrementingIDtothetable(primarykey).

$table->integer('votes'); INTEGERequivalenttothetable

$table->json('options'); JSONequivalenttothetable

$table->longText('description'); LONGTEXTequivalenttothetable

$table->mediumInteger('numbers'); MEDIUMINTequivalenttothetable

$table->mediumText('description'); MEDIUMTEXTequivalenttothetable

$table->morphs('taggable'); AddsINTEGERtaggable_idandSTRINGtaggable_type

$table->nullableTimestamps(); Sameastimestamps(),exceptallowsNULLs

$table->smallInteger('votes'); SMALLINTequivalenttothetable

$table->tinyInteger('numbers'); TINYINTequivalenttothetable

$table->softDeletes(); Addsdeleted_atcolumnforsoftdeletes

$table->string('email'); VARCHARequivalentcolumn

$table->string('name',100); VARCHARequivalentwithalength

$table->text('description'); TEXTequivalenttothetable

$table->time('sunrise'); TIMEequivalenttothetable

$table->timestamp('added_on'); TIMESTAMPequivalenttothetable

$table->timestamps(); Addscreated_atandupdated_atcolumns

$table->rememberToken(); Addsremember_tokenasVARCHAR(100)NULL

->nullable() DesignatethatthecolumnallowsNULLvalues

->default($value) Declareadefaultvalueforacolumn

->unsigned() SetINTEGERtoUNSIGNED

IfyouareusingtheMySQLdatabase,youmayusetheaftermethodtospecifytheorderofcolumns:

$table->string('name')->after('email');

Sometimesyoumayneedtomodifyanexistingcolumn.Forexample,youmaywishtoincreasethesizeofastringcolumn.Thechangemethodmakesiteasy!Forexample,let'sincreasethesizeofthenamecolumnfrom25to50:

Schema::table('users',function($table)

{

$table->string('name',50)->change();

});

Wecouldalsomodifyacolumntobenullable:

Schema::table('users',function($table)

{

$table->string('name',50)->nullable()->change();

});

Torenameacolumn,youmayusetherenameColumnmethodontheSchemabuilder.Beforerenamingacolumn,besuretoaddthedoctrine/dbaldependencytoyourcomposer.jsonfile.

Schema::table('users',function($table)

{

$table->renameColumn('from','to');

});

Note:Renamingenumcolumntypesisnotsupported.

Todropacolumn,youmayusethedropColumnmethodontheSchemabuilder.Beforedroppingacolumn,besuretoaddthedoctrine/dbaldependencytoyourcomposer.jsonfile.

Schema::table('users',function($table)

{

$table->dropColumn('votes');

});

UsingAfterOnMySQL

ChangingColumns

RenamingColumns

DroppingColumns

DroppingAColumnFromADatabaseTable

DroppingMultipleColumnsFromADatabaseTable

Schema::table('users',function($table)

{

$table->dropColumn(array('votes','avatar','location'));

});

YoumayeasilycheckfortheexistenceofatableorcolumnusingthehasTableandhasColumnmethods:

if(Schema::hasTable('users'))

{

//

}

if(Schema::hasColumn('users','email'))

{

//

}

Theschemabuildersupportsseveraltypesofindexes.Therearetwowaystoaddthem.First,youmayfluentlydefinethemonacolumndefinition,oryoumayaddthemseparately:

$table->string('email')->unique();

Or,youmaychoosetoaddtheindexesonseparatelines.Belowisalistofallavailableindextypes:

Command Description

$table->primary('id'); Addingaprimarykey

$table->primary(array('first','last')); Addingcompositekeys

$table->unique('email'); Addingauniqueindex

$table->index('state'); Addingabasicindex

Laravelalsoprovidessupportforaddingforeignkeyconstraintstoyourtables:

$table->integer('user_id')->unsigned();

$table->foreign('user_id')->references('id')->on('users');

Inthisexample,wearestatingthattheuser_idcolumnreferencestheidcolumnontheuserstable.Makesuretocreatetheforeignkeycolumnfirst!

Youmayalsospecifyoptionsforthe"ondelete"and"onupdate"actionsoftheconstraint:

CheckingExistence

CheckingForExistenceOfTable

CheckingForExistenceOfColumns

AddingIndexes

ForeignKeys

$table->foreign('user_id')

->references('id')->on('users')

->onDelete('cascade');

Todropaforeignkey,youmayusethedropForeignmethod.Asimilarnamingconventionisusedforforeignkeysasisusedforotherindexes:

$table->dropForeign('posts_user_id_foreign');

Note:Whencreatingaforeignkeythatreferencesanincrementinginteger,remembertoalwaysmaketheforeignkeycolumnunsigned.

Todropanindexyoumustspecifytheindex'sname.Laravelassignsareasonablenametotheindexesbydefault.Simplyconcatenatethetablename,thenamesofthecolumnintheindex,andtheindextype.Herearesomeexamples:

Command Description

$table->dropPrimary('users_id_primary'); Droppingaprimarykeyfromthe"users"table

$table->dropUnique('users_email_unique'); Droppingauniqueindexfromthe"users"table

$table->dropIndex('geo_state_index'); Droppingabasicindexfromthe"geo"table

Todropthetimestamps,nullableTimestampsorsoftDeletescolumntypes,youmayusethefollowingmethods:

Command Description

$table->dropTimestamps(); Droppingthecreated_atandupdated_atcolumnsfromthetable

$table->dropSoftDeletes(); Droppingdeleted_atcolumnfromthetable

Tosetthestorageengineforatable,settheenginepropertyontheschemabuilder:

Schema::create('users',function($table)

{

$table->engine='InnoDB';

$table->string('email');

});

DroppingIndexes

DroppingTimestamps&SoftDeletes

StorageEngines

IntroductionCreatingMigrationsRunningMigrationsRollingBackMigrationsDatabaseSeeding

Migrationsareatypeofversioncontrolforyourdatabase.Theyallowateamtomodifythedatabaseschemaandstayuptodateonthecurrentschemastate.MigrationsaretypicallypairedwiththeSchemaBuildertoeasilymanageyourapplication'sschema.

Tocreateamigration,youmayusethemake:migrationcommandontheArtisanCLI:

phpartisanmake:migrationcreate_users_table

Themigrationwillbeplacedinyourdatabase/migrationsfolder,andwillcontainatimestampwhichallowstheframeworktodeterminetheorderofthemigrations.

The--tableand--createoptionsmayalsobeusedtoindicatethenameofthetable,andwhetherthemigrationwillbecreatinganewtable:

phpartisanmake:migrationadd_votes_to_user_table--table=users

phpartisanmake:migrationcreate_users_table--create=users

phpartisanmigrate

Note:Ifyoureceivea"classnotfound"errorwhenrunningmigrations,tryrunningthecomposerdump-autoloadcommand.

Somemigrationoperationsaredestructive,meaningtheymaycauseyoutolosedata.Inordertoprotectyoufromrunningthesecommandsagainstyourproductiondatabase,youwillpromptedforconfirmationbeforethesecommandsareexecuted.Toforcethecommandstorunwithoutaprompt,usethe--forceflag:

phpartisanmigrate--force

Migrations&Seeding

Introduction

CreatingMigrations

RunningMigrations

RunningAllOutstandingMigrations

ForcingMigrationsInProduction

phpartisanmigrate:rollback

phpartisanmigrate:reset

phpartisanmigrate:refresh

phpartisanmigrate:refresh--seed

Laravelalsoincludesasimplewaytoseedyourdatabasewithtestdatausingseedclasses.Allseedclassesarestoredindatabase/seeds.Seedclassesmayhaveanynameyouwish,butprobablyshouldfollowsomesensibleconvention,suchasUserTableSeeder,etc.Bydefault,aDatabaseSeederclassisdefinedforyou.Fromthisclass,youmayusethecallmethodtorunotherseedclasses,allowingyoutocontroltheseedingorder.

classDatabaseSeederextendsSeeder{

publicfunctionrun()

{

$this->call('UserTableSeeder');

$this->command->info('Usertableseeded!');

}

}

classUserTableSeederextendsSeeder{

publicfunctionrun()

{

DB::table('users')->delete();

User::create(array('email'=>'foo@bar.com'));

}

}

Toseedyourdatabase,youmayusethedb:seedcommandontheArtisanCLI:

phpartisandb:seed

Bydefault,thedb:seedcommandrunstheDatabaseSeederclass,whichmaybeusedtocallotherseedclasses.However,youmayusethe--classoptiontospecifyaspecificseederclasstorunindividually:

phpartisandb:seed--class=UserTableSeeder

RollingBackMigrations

RollbackTheLastMigrationOperation

Rollbackallmigrations

Rollbackallmigrationsandrunthemallagain

DatabaseSeeding

ExampleDatabaseSeedClass

Youmayalsoseedyourdatabaseusingthemigrate:refreshcommand,whichwillalsorollbackandre-runallofyourmigrations:

phpartisanmigrate:refresh--seed

IntroductionConfigurationUsagePipelining

Redisisanopensource,advancedkey-valuestore.Itisoftenreferredtoasadatastructureserversincekeyscancontainstrings,hashes,lists,sets,andsortedsets.

BeforeusingRediswithLaravel,youwillneedtoinstallthepredis/predispackage(~1.0)viaComposer.

Note:IfyouhavetheRedisPHPextensioninstalledviaPECL,youwillneedtorenamethealiasforRedisinyourconfig/app.phpfile.

TheRedisconfigurationforyourapplicationisstoredintheconfig/database.phpfile.Withinthisfile,youwillseearedisarraycontainingtheRedisserversusedbyyourapplication:

'redis'=>[

'cluster'=>true,

'default'=>['host'=>'127.0.0.1','port'=>6379],

],

Thedefaultserverconfigurationshouldsufficefordevelopment.However,youarefreetomodifythisarraybasedonyourenvironment.SimplygiveeachRedisserveraname,andspecifythehostandportusedbytheserver.

TheclusteroptionwilltelltheLaravelRedisclienttoperformclient-sideshardingacrossyourRedisnodes,allowingyoutopoolnodesandcreatealargeamountofavailableRAM.However,notethatclient-sideshardingdoesnothandlefailover;therefore,isprimarilysuitedforcacheddatathatisavailablefromanotherprimarydatastore.

IfyourRedisserverrequiresauthentication,youmaysupplyapasswordbyaddingapasswordkey/valuepairtoyourRedisserverconfigurationarray.

YoumaygetaRedisinstancebycallingtheRedis::connectionmethod:

$redis=Redis::connection();

ThiswillgiveyouaninstanceofthedefaultRedisserver.Ifyouarenotusingserverclustering,youmaypasstheservernametotheconnectionmethodtogetaspecificserverasdefinedinyourRedisconfiguration:

$redis=Redis::connection('other');

Redis

Introduction

Configuration

Usage

OnceyouhaveaninstanceoftheRedisclient,wemayissueanyoftheRediscommandstotheinstance.LaravelusesmagicmethodstopassthecommandstotheRedisserver:

$redis->set('name','Taylor');

$name=$redis->get('name');

$values=$redis->lrange('names',5,10);

Noticetheargumentstothecommandaresimplypassedintothemagicmethod.Ofcourse,youarenotrequiredtousethemagicmethods,youmayalsopasscommandstotheserverusingthecommandmethod:

$values=$redis->command('lrange',array(5,10));

Whenyouaresimplyexecutingcommandsagainstthedefaultconnection,justusestaticmagicmethodsontheRedisclass:

Redis::set('name','Taylor');

$name=Redis::get('name');

$values=Redis::lrange('names',5,10);

Note:RediscacheandsessiondriversareincludedwithLaravel.

Pipeliningshouldbeusedwhenyouneedtosendmanycommandstotheserverinoneoperation.Togetstarted,usethepipelinecommand:

Redis::pipeline(function($pipe)

{

for($i=0;$i<1000;$i++)

{

$pipe->set("key:$i",$i);

}

});

Pipelining

PipingManyCommandsToYourServers

OverviewIntroductionUsageCallingCommandsOutsideOfCLISchedulingArtisanCommands

DevelopmentIntroductionBuildingACommandRegisteringCommands

ArtisanCLI

IntroductionUsageCallingCommandsOutsideOfCLISchedulingArtisanCommands

Artisanisthenameofthecommand-lineinterfaceincludedwithLaravel.Itprovidesanumberofhelpfulcommandsforyourusewhiledevelopingyourapplication.ItisdrivenbythepowerfulSymfonyConsolecomponent.

ToviewalistofallavailableArtisancommands,youmayusethelistcommand:

phpartisanlist

Everycommandalsoincludesa"help"screenwhichdisplaysanddescribesthecommand'savailableargumentsandoptions.Toviewahelpscreen,simplyprecedethenameofthecommandwithhelp:

phpartisanhelpmigrate

Youmayspecifytheconfigurationenvironmentthatshouldbeusedwhilerunningacommandusingthe--envswitch:

phpartisanmigrate--env=local

YoumayalsoviewthecurrentversionofyourLaravelinstallationusingthe--versionoption:

phpartisan--version

SometimesyoumaywishtoexecuteanArtisancommandoutsideoftheCLI.Forexample,youmaywishtofireanArtisancommandfromanHTTProute.JustusetheArtisanfacade:

Route::get('/foo',function()

{

$exitCode=Artisan::call('command:name',['--option'=>'foo']);

ArtisanCLI

Introduction

Usage

ListingAllAvailableCommands

ViewingTheHelpScreenForACommand

SpecifyingTheConfigurationEnvironment

DisplayingYourCurrentLaravelVersion

CallingCommandsOutsideOfCLI

//

});

YoumayevenqueueArtisancommandssotheyareprocessedinthebackgroundbyyourqueueworkers:

Route::get('/foo',function()

{

Artisan::queue('command:name',['--option'=>'foo']);

//

});

Inthepast,developershavegeneratedaCronentryforeachconsolecommandtheywishedtoschedule.However,thisisaheadache.Yourconsolescheduleisnolongerinsourcecontrol,andyoumustSSHintoyourservertoaddtheCronentries.Let'smakeourliveseasier.TheLaravelcommandschedulerallowsyoutofluentlyandexpressivelydefineyourcommandschedulewithinLaravelitself,andonlyasingleCronentryisneededonyourserver.

Yourcommandscheduleisstoredintheapp/Console/Kernel.phpfile.Withinthisclassyouwillseeaschedulemethod.Tohelpyougetstarted,asimpleexampleisincludedwiththemethod.YouarefreetoaddasmanyscheduledjobsasyouwishtotheScheduleobject.TheonlyCronentryyouneedtoaddtoyourserveristhis:

*****php/path/to/artisanschedule:run1>>/dev/null2>&1

ThisCronwillcalltheLaravelcommandschedulereveryminute.Then,Laravelevaluatesyourscheduledjobsandrunsthejobsthataredue.Itcouldn'tbeeasier!

Let'slookatafewmoreschedulingexamples:

$schedule->call(function()

{

//Dosometask...

})->hourly();

$schedule->exec('composerself-update')->daily();

$schedule->command('foo')->cron('*****');

$schedule->command('foo')->everyFiveMinutes();

SchedulingArtisanCommands

MoreSchedulingExamples

SchedulingClosures

SchedulingTerminalCommands

ManualCronExpression

FrequentJobs

$schedule->command('foo')->everyTenMinutes();

$schedule->command('foo')->everyThirtyMinutes();

$schedule->command('foo')->daily();

$schedule->command('foo')->dailyAt('15:00');

$schedule->command('foo')->twiceDaily();

$schedule->command('foo')->weekdays();

$schedule->command('foo')->weekly();

//Scheduleweeklyjobforspecificday(0-6)andtime...

$schedule->command('foo')->weeklyOn(1,'8:00');

$schedule->command('foo')->monthly();

$schedule->command('foo')->monthly()->environments('production');

$schedule->command('foo')->monthly()->evenInMaintenanceMode();

$schedule->command('foo')->monthly()->when(function()

{

returntrue;

});

DailyJobs

DailyJobsAtASpecificTime(24HourTime)

TwiceDailyJobs

JobThatRunsEveryWeekday

WeeklyJobs

MonthlyJobs

LimitTheEnvironmentTheJobsShouldRunIn

IndicateTheJobShouldRunEvenWhenApplicationIsInMaintenanceMode

OnlyAllowJobToRunWhenCallbackIsTrue

IntroductionBuildingACommandRegisteringCommands

InadditiontothecommandsprovidedwithArtisan,youmayalsobuildyourowncustomcommandsforworkingwithyourapplication.Youmaystoreyourcustomcommandsintheapp/Console/Commandsdirectory;however,youarefreetochooseyourownstoragelocationaslongasyourcommandscanbeautoloadedbasedonyourcomposer.jsonsettings.

Tocreateanewcommand,youmayusethemake:consoleArtisancommand,whichwillgenerateacommandstubtohelpyougetstarted:

phpartisanmake:consoleFooCommand

Thecommandabovewouldgenerateaclassatapp/Console/FooCommand.php.

Whencreatingthecommand,the--commandoptionmaybeusedtoassigntheterminalcommandname:

phpartisanmake:consoleAssignUsers--command=users:assign

Onceyourcommandisgenerated,youshouldfilloutthenameanddescriptionpropertiesoftheclass,whichwillbeusedwhendisplayingyourcommandonthelistscreen.

Thefiremethodwillbecalledwhenyourcommandisexecuted.Youmayplaceanycommandlogicinthismethod.

ThegetArgumentsandgetOptionsmethodsarewhereyoumaydefineanyargumentsoroptionsyourcommandreceives.Bothofthesemethodsreturnanarrayofcommands,whicharedescribedbyalistofarrayoptions.

Whendefiningarguments,thearraydefinitionvaluesrepresentthefollowing:

array($name,$mode,$description,$defaultValue)

Theargumentmodemaybeanyofthefollowing:InputArgument::REQUIREDorInputArgument::OPTIONAL.

Whendefiningoptions,thearraydefinitionvaluesrepresentthefollowing:

ArtisanDevelopment

Introduction

BuildingACommand

GeneratingTheClass

GenerateANewCommandClass

WritingTheCommand

Arguments&Options

array($name,$shortcut,$mode,$description,$defaultValue)

Foroptions,theargumentmodemaybe:InputOption::VALUE_REQUIRED,InputOption::VALUE_OPTIONAL,InputOption::VALUE_IS_ARRAY,InputOption::VALUE_NONE.

TheVALUE_IS_ARRAYmodeindicatesthattheswitchmaybeusedmultipletimeswhencallingthecommand:

phpartisanfoo--option=bar--option=baz

TheVALUE_NONEoptionindicatesthattheoptionissimplyusedasa"switch":

phpartisanfoo--option

Whileyourcommandisexecuting,youwillobviouslyneedtoaccessthevaluesfortheargumentsandoptionsacceptedbyyourapplication.Todoso,youmayusetheargumentandoptionmethods:

$value=$this->argument('name');

$arguments=$this->argument();

$value=$this->option('name');

$options=$this->option();

Tosendoutputtotheconsole,youmayusetheinfo,comment,questionanderrormethods.EachofthesemethodswillusetheappropriateANSIcolorsfortheirpurpose.

$this->info('Displaythisonthescreen');

$this->error('Somethingwentwrong!');

RetrievingInput

RetrievingTheValueOfACommandArgument

RetrievingAllArguments

RetrievingTheValueOfACommandOption

RetrievingAllOptions

WritingOutput

SendingInformationToTheConsole

SendingAnErrorMessageToTheConsole

Youmayalsousetheaskandconfirmmethodstoprompttheuserforinput:

$name=$this->ask('Whatisyourname?');

$password=$this->secret('Whatisthepassword?');

if($this->confirm('Doyouwishtocontinue?[yes|no]'))

{

//

}

Youmayalsospecifyadefaultvaluetotheconfirmmethod,whichshouldbetrueorfalse:

$this->confirm($question,true);

Sometimesyoumaywishtocallothercommandsfromyourcommand.Youmaydosousingthecallmethod:

$this->call('command:name',['argument'=>'foo','--option'=>'bar']);

Onceyourcommandisfinished,youneedtoregisteritwithArtisansoitwillbeavailableforuse.Thisistypicallydoneintheapp/Console/Kernel.phpfile.Withinthisfile,youwillfindalistofcommandsinthecommandsproperty.Toregisteryourcommand,simplyaddittothislist.WhenArtisanboots,allthecommandslistedinthispropertywillberesolvedbytheIoCcontainerandregisteredwithArtisan.

AskingQuestions

AskingTheUserForInput

AskingTheUserForSecretInput

AskingTheUserForConfirmation

CallingOtherCommands

RegisteringCommands

RegisteringAnArtisanCommand