This content is a presentation by Mary Perry at Laracon, exploring how design patterns are deeply embedded within the Laravel framework, enhancing its productivity and maintainability. Perry argues that understanding these patterns, even if not explicitly named, empowers developers to build more robust and communicative solutions.
Mind Map
Click to expand
Click to explore the full interactive mind map • Zoom, pan, and navigate
Um Mary Perry is a dear friend of mine
and I'm very excited for her to be on
the Laracon stage for the first time. Um
a little bit of lure about Mary is um I
I host a podcast a podcast called Mostly
Technical with my friend Ian and Mary
Perry. All right, we got eight fans out
there. I love that. Um Mary Perry had
the first sticker on her laptop uh
thanks to producer Dave. So Mary and I
have been friends for a long time. um
she doesn't work with Laravel
professionally daytoday but she came to
Laracon for the first time 2 years ago
and was just totally floored by the
community and just continues um to
invest and be a part of this community
and that's one of the things I think is
so special about this and um Mary is is
brilliant she's self-taught she's
enthusiastic um generally she's a
database person which a woman after my
own heart but today uh she is coming
from scrant
Pennsylvania to talk to us about design
patterns. Please put your hands together
for Mary Perry. [Applause]
Oh,
uh, hello. I had this, uh, [Music]
I had this whole, um, entrance planned.
It was like really elaborate. There's
going to be choreography. I asked some
people to help me with dancing. There's
like a different song, but I think I
baro something yesterday when I was um
playing golf. Um and uh I needed to have
a more measured entrance. Just get a
little bit of rest. Um I'm just trying
to compose myself because I'm new to
speaking. Um some of these puns are
terri treble. Um I'm actually string you
all along. I can't dance. Um on that new
note, uh what's the good word?
I'm Mary Perry. I'm from Scranton,
Pennsylvania. I don't have too many
interesting hobbies, but um I like
liking things. You may have seen me on
social media saying nice things about a
project that I think is cool. Um my
handle is cifus. Uh the first part is
from the Arabic root cifher, which means
zero or nothing or null. It's also the
root of cipher. Um so I basically think
of it as like false and then I tried to
turn into an adjective. So it's like
kind of falsy. um which I think is an
interesting concept and here's an
example of why. Um you could write a
function that returns a boolean um
checking that an object has an
attribute. But sometimes in real life we
find that true and false don't really
satisfy every relevant case. So we can
define a class that helps us to combine
multiple checks for booleans and make a
more complicated assessment of whether
the evaluation should be true or false.
And this works really well like in
authentication for example. And this is
really all design patterns are named
solutions that you can reuse that you've
reworked to solve cases that h you
haven't encountered yet. Um but instead
of all of this if we were working
together I could just say
let's manage the access with assertions
and then you could say skipping all of
this. Um I think a guard close pattern
would be a better choice. uh because in
some cases true and false and falsy are
all important and so is the way you
handle them and I think the names of
these patterns are really interesting
but maybe you don't and I don't really
think that that matters because if
you've worked with layer you've probably
used a guard class in one of your
applications and if you didn't have to
invent it I'm guessing no matter what
your background is the first time you
used a guard class it worked pretty well
and it didn't take that long
um just really quick uh to see a key for
the uh diagrams that I'm using in this
talk, you can go to ado.larvel.cloud.
It's going to be um more detailed in the
future. It's very very basic right now.
Um and if you want to follow me for
updates, you can check out my pink
carry. I'm at cphrius and all my other
socials are linked there. So without
further ado, this is my talk. Much to do
about naming.
You already know that perhaps the best
reason to use Laravel is its
productivity. And what I mean here when
I say productivity is that many of the
problems that need to be solved when
you're designing a web application um
already solved and given to you for
free. It takes about 10 minutes to set
up a default layer of application with
authorization and even multi-tenency and
also have a coffee. Um and because
you're using Laravel, you probably
already know not to try to solve every
problem with first principles. Laravel
is an entire ecosystem of solutions to
common problems. And when you build with
Laravel in his packages, you're
benefiting from other people's mistakes
and from their experience as experts. So
this means you're probably going to ship
faster while avoiding foot guns. All
that considered, do you need to learn
design patterns?
Probably not. So uh you're already
capturing design experience in a form so
effective you don't really have to think
about it. And just mentioning the names
of these packages that make up the
ecosystem communicates the complexity of
these solutions as well. Layer core is
full of design patterns and your
development experience with Laravel is
full of their benefits. In the source
code, you can look at it. It's concrete,
testable, readable. These patterns are
combined in Laravel's fundamental
solution to the question of web
applications. How to best return a
response to a request? Um, the answer is
from Laravel's perspective the uh
request life cycle. And over the next 20
minutes or so, I would like to take you
on a tour of it and point out some
places in Laravel core where those
patterns are used. Um the index php file
loads the composer generated autoloader
uh definition and then retrieves an
instance of the Laravel application in
bootstrap. So the whole project of this
first step section um is creating an
application and we'll start with a
singleton. The Laravel application is a
singleton because it has a method which
returns a unique instance. Um
application extends container among
other classes and the get instance
function ensures that only one instance
is ever um returned when you ask for it
and when it needs to be created for the
first time set instance takes container
contract and overrides it. A container
contract is the inter interface that
defines the required parts of the
instantiation and your instance of the
container implements it. application
also has other methods that are
inherited and overwritten from these
interfaces and they actually work when
you get your application running. Um, in
the context uh contracts directory in
the container.php file, we're going to
see the container contract which has
bind which doesn't do anything until the
container class overwrites the
definition of a functional method and
the class knows or knows how to find and
return the data it needs which can be
stored and modified without modifying
the singleton itself. And the unique
application object can be returned using
applications get instance method which
we just saw. Um so there can only be one
in a singleton. It uses an interface by
inheriting and overriding it and it
knows it's the only instance. Many of
these surfaces are factories which is a
really good pattern for if you want uh
one of a group of products but you don't
know which one at a given time. So in
this factory um the product uh
ultimately determines through the
creator and the concrete creator how
we're going to get a concrete product
which in this case is going to be
sessions. Um so this is uh where the
session manager is registered and then
the result is going to be um stored in
the service container as a singleton. Um
this is an example in the session
manager where we're taking um a
instantiation of one of those concrete
factories um and creating it with build
session. This kind of cookie cares about
uh this kind of session cares about
cookies and expiration. And there's a
very similar one where we're going to
take a database session handler and it
cares about you know the table and the
connection etc. Um so in general a class
a factory is a class that provides
instances from a group of subasses. They
have a method that's determined at
runtime. Um it has products which are
similar objects produced by a factory
and used by your application. And it
uses an interface or contract to give
instructions of those similarities and
ensure that the similarities are there.
Uh speaking of services, if you need
immediate wormhole like access to the
service in the service container, you
can use a facade. Uh the diagram for a
facade looks different from other
patterns. Generally, facads hide
complexity while providing a few simple
access points like an API or an
interface. Here's a classic example. Um
if you're using a pi compiler, you
pretty much only need the compiler
method. Um unless you're writing one,
but then you'd probably be like using Go
or Rust by the way, and your editor
would probably be neim by the way, and
you'd be running like Arch by the way.
So I'm really just speculating wildly
here. Um, a facade in a word is
encapsulation. Hiding complexity in a
system makes the code which interacts
with that simp system simpler. But
Laravel gives you more than a design
pattern of a facade. They're more
specific and they give you access to a
service provider class from anywhere.
Realtime facads, you could get static
access. You could do custom facads. They
are an awesome vanity plate. They look
fantastic on a hat. And if you learn
them really deeply, then you can stay up
late into the internet on the internet
arguing with strangers about whether
anyone should ever be allowed to use them.
them.
That's not nearly as productive as
actually trying to write code with them
and seeing what the service container is
capable of, but you could.
Um, after first steps, the uh request is
going to be sent through the handle
function of the kernel, either the HTTP
or console. Web requests we're going to
kind of focus on now with the HTTP.
Um, and if you don't use a facade,
Laravel will find the appropriate
classes via inversion of control. This
family of patterns provides instances
without requiring the controller to know
about them or be direct freely
responsible for them.
So um it inverts the control flow,
increases decoupling and frameworks are
really good uh use case for
uh the dependency injection and
inversion of control and so are event
handling systems and event uh Laravevel
has a lot of events. Uh there's four
varieties of inversion of control and
Laravel arguably uses all of them but
we're just going to talk about um
dependency resolution really quick. The
service container uses bind and binding
like strategies to resolve and
autoresolve dependencies for you. So you
never have to experience dependency hell
when you're using Laravel. Um you've
probably seen code like this in a
controller and whenever you call
construct either implicitly or
explicitly in Laravel, it's a hint that
some dependency injection is happening.
Um so anytime a service is resolved um
we can see make or build happening. Um
with make we're going to see the um
dependencies resolved. Laravel will go
through the resolve function and return um
um
and iterate through the dependencies
making sure that they're all created or
throwing an error outside of your
controller. So um you can avoid
catastrophe or ensure in as in most
cases that the object you're trying to
create can be created. um the
method is resolved when the constructure
the controller is actually called and
there's a lot going on behind the
scenes. It's a for a very short amount
of code. I really love to be able to see
the complexities of good the controller
and know what's going on there. It makes
me very happy. Um then there's a builder
pattern I'm going to talk about in terms
of mil uh middleware. Um in the
bootstrapping phase we saw this index
entry point and the project of this
phase is to instantiate an application.
Um so now we're going to talk about how
the middleware gets created. The builder
pattern is a solution when we want to
build a complex object using the same
construction project but get a different
representation every time. The director
in the builder pattern is a method which
works um to build the product. And the
director of this is going to be the
kernel um which is responsible for
passing the request through the
application's middleware stack. And the
plan is to send a request through this
pipe object which is configured with
whatever middleware is going on in the
application. Um the order the middleware
occur is important and when you modify
the kernel you can choose different
orderings um based on the type of
request that you're uh getting. Um the
pipeline needs to send the request
through these middlewares which modifies
the request as it passes through and the
concrete builders or individual
middleware inherit from the middleware
interface and eventually a product is
specifically configured. In this case
it's the request object. If none of the
middleware stop the request from
continuing during this pipeline then the
request can be routed to the appropriate
routing controller with the rate HTTP
verb. So in general um the builder
pattern reuses functions in the same
project for different object
representations, produces complex
objects and the build steps are managed
by a director. Um next the service
providers are loaded.
I assure you this is very important but
I don't have time to elaborate on it
because we're down to eight minutes. So
uh next is routing. During routing
service providers are registered and the
request is going to be handed off to the
router for dispatching. My favorite use
of Laravel is eloquent and a close
second is collections which is also kind
of eloquent. Collections are a type of
iterator and database enjoyers may like
to know that another name for this
pattern is cursor. Uh route collection
provides a lot of functionality on top
of listing the routes in our
application. So here's another diagram.
The client in this case is going to be
um the Laravel routing mechanism and um
our iterator is actually the iterator
aggregate interface that's inherit
that's from PHP in general. This gives
us all kinds of things that we might
want to do with a list. Um the abstract
route collection is going to collect all
of the routes that we have listed in
various route files like web PHP or off
PHP or API PHP if you have one or a
custom one. Um and then we have this
object that um can be returned and get
routes with more specific behaviors that
we have decoupled but can use with that
object. Um that gives us a lot of
additional functionality specifically in
the routes collection. We can use this
to compile routes, support subdomains,
name routes, group routes and
middleware, use fallback routes, all
kinds of things. Um and it's because of
this decoupling. So in general,
iterators uh let you access the elements
of an aggravated object, avoid exposing
the internal structure or bloating the
list too much and traverse the list in
different ways um by defining different
ways of traversal for different purposes.
purposes.
Um it's a combination of the routing and
the verb which determines the request
needs from the container. And that
brings me to the strategy pattern.
Generally a strategy is an interface to
be inherited and it happens in some
context from which it's decoupled. um
the strategy has an interface which
defines some behaviors or attributes and
the the strategies are all supposed to
have and then the concrete strategies
overwrite them and do slightly different
things for different cases. I already
showed you at least three strategies and
you can find this all over layer. It's
generally just a good life choice. Um
in the context of the controller methods
return views and those views are
decoupled from the controller the
request the route and the verb. In the
context of the application, all the
middleware have a handle function and
the behavior is decoupled from the
middleware pipe and the service
container. And in the concept of a
service container, service managers can
build unique sessions by parameterizing
a construction of the concrete factories
with the service manager.
So strategies maintain a reference to a
strategy object in a context. concrete
strategies inherit from the interfaces
in a strategy and then it implements
that behavior as it sits on the strategy
and using interfaces is good.
So we've reached the point of finishing
up where the response travels back
outward through the rout's middleware
and the application has a chance to
modify or examine the outgoing response.
The command also known as the action
pattern takes a behavior um we may have
implemented in a method and stores all
the information we need to execute in
that object which can be parameterized
by the object that executes it. So this
is an example of raification the process
of turning some process into a first
class object. Here's an example. Um the
application receives the action as a
parameter to its destroy method in some
controller and the action instance in
that controller is invoked when the
controller gets hits by a request and
that destroy method includes calling the
handle method on the action which
contains a reference to the part of the
application that knows how to handle the
action. Um in this case it's going to be
a database.
It's typical for a strategy to look like
this. Um the creation of receiver and
then passing the receiver as a reference
um on instantiation of the action. But
in Larbo because of dependency injection
it might actually look like this.
Um so let's look again in the context of
controller it's decoupled from the
service container which functions as a
client in this example. Um the destroy
which shares qualities of the other
actions including a handle function and
that references the receiver of the
action. and the receiver knows how to
actually get the job done. So in this
combination of actions on top of all the
strategies and controllers is very
powerful and flexible if you think about
it. But if you're also seeing this and
you're thinking, well, I've structured
my code like that before and I didn't
mean to use a pattern or know the name
of it. Then welcome in. It is awesome to
feel like you invented a pattern for
yourself. It means you're on to
something and you can use that name to
talk about it with other people who
already understand why you're so excited
about your solution.
Um, the command pattern is useful when
you don't know what the action is going
to be or what the receiver is going to
be. It encapsulates a request as an
object which contains an execute
operation, parameterizes clients with
requests, and supports undoable
operations. It's also super good for logging.
logging.
And then after a request has occurred,
most of the time changes will have
happened in the state of your application.
application.
And the observer pattern lets an object
called the subject update other objects
when changes happen. Subjects need to
have a way to know about and notify
their observers the classes that are
going to be updated. And eloquent models
can attach to observers using um a
static observe method in Laravel and
observers can be a class property. Uh
dispatchers help a specific model like
um team manage their observers when
state changes and they're identified
through uh reflection. They need to have
specifically named functions. Um but
they can access state temporarily for
these per this purpose and define their
own behavior. Um like for example
logging when a team gets created or
deleted. Um so as your request behavior
is ending you have a lot of objects that
weren't directly affected um which are
updated to um when it's a state in a
different object changes. And this
pattern allows you to store those
changes in objects called events which
benefits subsequent storage logging and
other cool stuff.
This is really cohesive. What I find so
beautiful about Laravel is the choice of
patterns it uses. The expertise
demonstrated in the way that it solves
the web's classic problem. How do we
handle a request? The framework is
extensible not just because these
solutions adhere to the terminology of
patterns, but because the code is
implemented in ways that have been
proven to work. And code that is
reusable and has been proven to work
tends to acquire names. These
implementations are not always canonical
or classical, but they are thoughtfully
designed in ways that invite us as a
community to participate, to learn, to
read, and to contribute.
Designing object-oriented pro software
is hard, and designing reusable
object-oriented software is even harder.
Projects and processes are we manipulate
are unique. But experienced developers
who have solved similar problems have
found working solutions in the recurring
patterns of classes and many
object-oriented systems. These
commonalities and the solutions to these
problems allow us to put forth design
patterns and to name them and it gives
us the language to discuss solutions
with other people who know about them
and express and recognize those
solutions more quickly. Um, for example,
there's usually two S's and classes, but
the variances in each system we design
means that the details of our
implementations and their grammar and
the combinations of our business logic
should not and often cannot be classical.
classical.
They help a designer to get a design
right faster. They speed up
communication, reduce complexity,
encourage documentation and readability.
Their definitions describe real systems,
but they're almost never exactly what
they claim to be.
My opinion is this. Learn the names or
don't. The right tool, architecture, and
implementation is always specific to
what you're building. Design patterns
are just one way to talk about design
that we can agree solves some problems.
But whatever you're building, I hope
that you're talking about it because
ever since I started talking about it
and liking liking things online and
posting about it, my life got a lot
better. So, I'll leave you all with a
final blessing. Laravel forever. Thank
you very much. Wow.
Wow.
Are you kidding me? That was incredible.
That was your first big Laracon talk.
That was incredible. And here is your
artisan jacket.
>> Thank you very much.
>> That was unbelievable. Give another
round of applause for Mary Perry.
So, um, couple of questions. The first
is not a question, it's a statement. We
had many people that tweeted about your
puns. So, the puns worked. Everyone
Everyone loved the puns. So, good job
there. I guess
>> to my ears.
>> Yes. My question for you is um what
appeals to you about design patterns
because you've obviously gone super
deep, right? Deeper than probably most
of us have gone. Um what is it about
those that appeal to you and where did
you look to like study and learn those
things such that you could identify them
in Laravel?
>> I like the idea of naming things and of
the ways that we use grammar to name
things. So, I heard Jake Bennett's state
machine talk when it was uh in Nashville
in 2023, and I thought it was so
interesting that we could give a
30-minute talk that I had to spend a
couple hours going back and learning
more about to understand and describe
everything that was going on to people
who already understand it in two words,
just state pattern, you know. So, um I
started really diving deep into it. I
read the Gang of Four book. I read, um a
small talk book, a couple of
a couple of uh articles online,
especially um the uh the inversion
control articles are are better there.
And I just uh kept going with it obsessively.
obsessively.
>> Yeah. Well, it it it worked. That was
the best deep dive into the Laravel life
cycle that I've ever seen. So, well
done. Very proud of you. Y'all give it
up for Mary Perry.
Click on any text or timestamp to jump to that moment in the video
Share:
Most transcripts ready in under 5 seconds
One-Click Copy125+ LanguagesSearch ContentJump to Timestamps
Paste YouTube URL
Enter any YouTube video link to get the full transcript
Transcript Extraction Form
Most transcripts ready in under 5 seconds
Get Our Chrome Extension
Get transcripts instantly without leaving YouTube. Install our Chrome extension for one-click access to any video's transcript directly on the watch page.