At my job, we've been doing a lot of learning and development using Taylor Otwell's Laravel 4 PHP framework. As we've become more familiar with it, we've had to come up with better ways to structure our projects outside of what the documentation indicates and the default distribution that is provided.
If you've been working with Laravel 4 for any amount of time or come with experience from another framework and are just getting started, you've probably noticed that there are a lot of different ways to cut up your projects.
While I can't say the entirety of my advice is in practice throughout the community, I can say that we are starting to use it, and to very good effect at my job. Especially considering that our apps tend to need both web and API front ends, good architecture is a very high priority.
How do you namespace properly? At the root of your project (as in: adjacent to your .git directory), have a directory called "src". Inside of there you might have: "YourOrganization/YourProject", followed by all the necessary namespaces for the guts of your application. Some of which I will be clearly mentioning later in this post.
This is merely laying the groundwork for what's to come, but before we move on, there are two more suggestions I have which some people may disagree with:
If you've been working with Laravel 4 for any amount of time or come with experience from another framework and are just getting started, you've probably noticed that there are a lot of different ways to cut up your projects.
Choice is nice, but sometimes it can be paralysing or misleading.
Concrete Advice
This post is done in such a way that you can just skim the headings, but if you want a detailed explanation in each section, feel free to read in where necessary.While I can't say the entirety of my advice is in practice throughout the community, I can say that we are starting to use it, and to very good effect at my job. Especially considering that our apps tend to need both web and API front ends, good architecture is a very high priority.
Use Namespaces
...properly! I've seen a lot of packages out there that classmap a file with a namespace declaration in it and yes while that's technically viable and nothing will blow up, it's cluttered. The whole idea behind PSR namespace loading is that the files are easy to find and cohesive. Resorting to a "just find it all here under this esoteric name I've given it" approach makes your project more difficult for others to get up to speed with.How do you namespace properly? At the root of your project (as in: adjacent to your .git directory), have a directory called "src". Inside of there you might have: "YourOrganization/YourProject", followed by all the necessary namespaces for the guts of your application. Some of which I will be clearly mentioning later in this post.
This is merely laying the groundwork for what's to come, but before we move on, there are two more suggestions I have which some people may disagree with:
- Never repeat namespace names in classes. So nothing like "YourOrganization\YourProject\Controller\PostController". If you need a different name for the class, alias it in the file where you're using it, where the meaning is really implied.
- Never pluralize your namespaces. It's not necessary and will make sense once you see a complete class name.
Don't use Facades in Namespaced Code
It may seem tempting, but every time you do it, you're turning down an opportunity to make use of the IoC and reap the benefits of a clearer architecture. Instead, define a constructor on your class and list the dependencies there.
Namespace Your Models
It's just going to be more organized that way and you'll be less inclined to abuse them.
First, don't extend "Eloquent", extend the fully namespaced eloquent class "Model" itself.
Second, if you see a package claim along the lines of "oh yes, we will give you slugs, just extend our sluggable base class and away you go!", immediately put on the brakes. Go to that project's github page and open an issue titled: "Use Traits Instead" with the body text "Please see title.", click submit. The response will usually be "oh most people don't have PHP 5.4", at which point you can remind them what year it is and that PHP 5.3 is EoL.
Only Extend Model
I mean this in two ways:First, don't extend "Eloquent", extend the fully namespaced eloquent class "Model" itself.
Second, if you see a package claim along the lines of "oh yes, we will give you slugs, just extend our sluggable base class and away you go!", immediately put on the brakes. Go to that project's github page and open an issue titled: "Use Traits Instead" with the body text "Please see title.", click submit. The response will usually be "oh most people don't have PHP 5.4", at which point you can remind them what year it is and that PHP 5.3 is EoL.
Write Thin Models
...with no external dependencies. That means nothing like:
public function getUrlAttribute() { return $this->urlGeneratorService->generateUrl($this->attributes['name']); }
If you've been paying attention, you'll realize doing this in your model would force it to depend on an external service - and that implies a context, which is undesirable. If you write methods like this in your models, you will have architecture problems down the line.
If there's some kind of transformation you need to perform on model data, it's entirely likely that it is specific to a certain circumstance that model may not always be finding itself in. That circumstance should never be coupled to the model itself, ever.
What can you write in your models? Basically anything that leverages the model itself, its relations, internal PHP methods, scopes or something from the "Illuminate/Database/Eloquent" namespace.
Here's how I like my packages to look:
Alright, that's it for now! New guidelines can come along in another post if I come up with a decent enough list.
I've been tinkering away at this post for a bit and I think what's in here is good enough to share. It's definitely the kind of resource I had hoped for when getting started with Laravel. Please feel free to post a comment with your thoughts or improvements.
Keep in mind that what I've listed here is actually a combination of things I've discovered both on my own as well as through the community.
What can you write in your models? Basically anything that leverages the model itself, its relations, internal PHP methods, scopes or something from the "Illuminate/Database/Eloquent" namespace.
Create Repositories
Repository classes represent the different graphs you'll be requesting from the database. A repository might look as simple as an Eloquent model getter (and seem redundant), but creating this layer will allow you to keep your classes from becoming a dizzy mess of queries.Everything else is a Service
Where something isn't a repository to fetch models from the database, you can create a service. Whether it's a utility to build static CDN URLs, or a social library that you've created. Most everything else in Laravel can be defined and injected as a service to be called. These can either call each other or be mixed and matched at the right level as needed.
Namespace your Controllers
Controllers will depend on services and/or repositories, and services are injected. Best to get them in the structure. Here's where I'd hope to find a controller in your project:- your-project/
- app/
- src/
- YourOrganization
- YourProjectName
- Controller
- Api
- User
- Post
- Social
- Web
- User
- Post
- Admin
- Model
- Repository
- Service
- public/
- vendor/
Notice that I don't repeat names anywhere and everything is split up nicely based on roles. I have clean names to use in my routes and nobody has to go digging to find specific functionality. The separation of concerns in my project is clear based on this namespace structure alone.
Non-Namespaced Files
Migrations, views, routes, and configs are all the kinds of configuration-like framework files that don't need to be namespaced. This is where the facades really come in handy to grant your static code access to the dependency injection container.On Migrations
Don't use the enum type in Laravel 4 migrations currently as you'll lose the ability to alter the table later on down the line. Also, when authoring migrations for a package, write them to exist in the package and not to be copied into the main project by a command. This was something I got tricked into doing and it ended up being unoptimal when the time came for updates.
The More Theoretical
These next few are more to do with how your efforts on a general whole can be improved when working with Laravel 4. I just think they're a little more abstract than "do this with this here and not there".
Don't Subclass Packages
If you see a particular package in the wild and think to yourself "hm, I just need to change this one method on this class...", I urge you to reconsider. Either think about it from the angle of wrapping it with a service, or fork the project and turn the original package into an upstream source. The amount of confusion that can arise just from having multiple service providers attaching to the same realm of functionality as well as any potential model issues will mire you.Write Packages!
...and then open source them! Release them to the community and help the community grow. I have a co-worker who firmly believes that nothing is too small to be a package. With the right designs in mind, I'd say he's right!Here's how I like my packages to look:
- your-package/
- config/
- migrations/
- src/
- YourOrganization/
- YourPackageName/
- {any namespaces needed}/
- ServiceProvider.php
- composer.json
- readme.md
I'm a bit on the fence about putting migrations and config in "src" as I think it should always be the root of a namespaced loader. If you have any thoughts on that, feel free to send me a comment!
Don't Fight It!
I was given some good advice very early on when I started working with Symfony 1.4 which was to never try and fight the framework. Always work with the grain, go with the flow. Given the title of my blog, you can correctly conclude that I tend to challenge convention wherever possible. But that doesn't mean I'm immune to well thought explanations. In this, frameworks shine.
Generally speaking, if a framework is popular and has a strong community, it stands to reason that many eyes have gone over the tools and given them a general "ok" in a broader scale design analysis. I think the irresistable force paradox merits mention here.
Use the Local Development Server
Don't let the vagaries of any environment make you think that Laravel should be expected to behave differently in production. See my previous point. I think you'll find some parallels between this practice and writing tests for your code as well. If you can't download your project, install dependencies and then run artisan, you have a problem.
Be Pragmatic
If you haven't read the Pragmatic Programmer and are not familiar with one of Symfony (1.x or 2.x) or Ruby on Rails, do yourself a favour and read the book. I think a lot of the advice in that book urges us to think more about our work with a longer term focus than is normally seen. What's important is not making decisions out of convenience and being aware of impatient duplication, orthogonality and the broken windows theory. All of these topics are explored to good effect in the book and help us learn a lot about ourselves as developers.Be Still
I have one of my own to add which is to always try and write as little code as possible. Code that conducts excessive checks or produces more data structures than is necessary always has to be balanced somewhere else down the line. All of my advice here in a lot of ways is based on the desire to keep things DRY and simple.Alright, that's it for now! New guidelines can come along in another post if I come up with a decent enough list.
I've been tinkering away at this post for a bit and I think what's in here is good enough to share. It's definitely the kind of resource I had hoped for when getting started with Laravel. Please feel free to post a comment with your thoughts or improvements.
Keep in mind that what I've listed here is actually a combination of things I've discovered both on my own as well as through the community.
This article was written by a real thinking writer. I agree many of the with the solid points made by the writer. I’ll be back. تحويل word الى pdf
ReplyDeleteYour blog is in a convincing manner, thanks for sharing such an information with lots of your effort and time
ReplyDeleteruby on rails training India
ruby on rails training hyderabad
FON PERDE MODELLERİ
ReplyDeleteNumara Onay
türk telekom mobil ödeme bozdurma
nft nasıl alınır
ANKARA EVDEN EVE NAKLİYAT
TRAFİK SİGORTASI
dedektör
web sitesi kurma
aşk kitapları
pendik daikin klima servisi
ReplyDeletetuzla toshiba klima servisi
tuzla beko klima servisi
çekmeköy lg klima servisi
üsküdar beko klima servisi
pendik lg klima servisi
pendik alarko carrier klima servisi
pendik arçelik klima servisi
tuzla samsung klima servisi
I was nervous when I Clicked on this on this blog I felt what im looking for this blogs haves but thank you to the author who has everything in this blog for what im looking for. This blog writer has the best knowledge about laravel.
ReplyDeleteIf you're looking for Laravel Web Development Services in India so, you can visit our CodeKing Solutions for the best offers.