0

Let me set the scene:

I have an "Item" class which has different food items (like Carrots, Apples, etc.). This links to the "items" table. All is well here.

In the old framework I am migrating from, I also had a "Complete Protein" class that had an Item object being required in the constructor. This "CompleteProtein" object would then be able to do complex queries and methods, and contain general information about what a "Complete Protein" is.

Where does this fit in Laravel? It doesn't seem like it would be an eloquent model, as it does not directly relate to any table in the database, but it does do database queries. It does have dependency injection (Item), as well as complex methods and constants in the class.

Should I just somehow make these fit into the "Item" class? I feel that would be rather messy.

1
  • Sounds like a "Domain Model", so I'd suggest in models, or create a domains folder Commented Jul 29, 2015 at 22:11

2 Answers 2

6

You don't really need Eloquent models for this. I don't even use Eloquent (but absolutely love the rest of Laravel). I don't even use an ORM (not even Doctrine2). But if you still like to use it, consider it to be part of your infrastructure and not part of your business domain. Make Eloquent calls inside of Repository methods like findByEmail() or save(). Many folks make the repository an interface, so they can swap out implementations in service providers for testing (where you use an in-memory repository implemenation, perhaps just storing stuff in arrays). Again, I wouldn't return Eloquent Models from these repositories, but instead return the hydrated domain object.

What you are describing is an entity in your business domain. It's possible this could be a domain service in your business domain, but sounds more like an entity (in DDD). I would put that entity in a class in a location like this:

app\
  Domain\
     CompleteProteins\
         CompleteProtein.php
         CompleteProteinRepository.php
     Items\
         Item.php
         ItemRepository.php
     (maybe some domain service classes here as well)
  Http\
  Queries\
  Helpers\
  Services\ (<-- maybe application level services here)
  etc...

Now in your CompleteProtein.php write a class that has your needed properties and give it methods (so it's not anemic) to form an entity that represents a well-defined "thing" in your business. Separate out the methods that are needed for "collection" like actions. These are actions where you either pull from something like a database and persist to something like a database. Separate out these special methods and put them into the Repository. Your code will eventually look something like this:

$protein = new CompleteProtein($item, $blah, $blahblah);
$protein->doSomethingWith("Apples");
$proteinRepository->persist($protein);

This is a great way to code and encapsulate rules. It's easy for a new developer to see all the "things" that make up your business. If your developer is looking to do some persistence, then you can instruct him/her to "go to the repository". No one-off queries here and there! No ORM calls sprinkled about (pretending that your relational database is OO)! You can also have a method on your domain objects like markAsDeleted (or better yet markAsErroneous) so that when you send it to the repository with ->persist, the repository can look for a flag on your object and know to delete it. This allows you to add logic to deletes. Look into techniques using PHP's Reflection class for giving Repositories access to hydrate/dehydrate domain objects. Zend framework has a good basic one I like to use. Repositories are also good for mass collection-like calculations.

(Note: There is a folder I listed above called Queries for you to create classes for READ query situations. You don't need to hydrate full entities from your repositories in many cases where you are just wanting to display information on the screen throughout your app. Google "Command Query Separation".)

Sign up to request clarification or add additional context in comments.

Comments

0

It's a service class. Regardless of your choice of framework, I'd name it as such.

Some people prefer a folder (and namespace) called 'Services', others prefer to use a mute domain-driven approach (perhaps a folder named 'Protein' to keep it in?) but that's up to you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.