sn0opr's avatar

Share models between two Laravel projects

Hi laracasters, this is my first thread :).

We are making a big entreprise application, separated in two laravel projects (currently) to make it easy to manage... They are using the same database, currently we are duplicating the models for each project which is bad. We are searching for a solution to share the models classes between these two projects without duplication.

0 likes
19 replies
Erik's avatar

You can use modules for this. For example

- App A/Models/User.php

- App B/Http/Controllers/AuthController.php

If you want to use User.php from App A in your routes.php from app B you can reference it using the following piece of code.

// AuthController.php
public function postResetPassword($request) {
    AppB\Models\User::findByEmail($request->only('email')); // Or use it on top of the document, you get the point.
}

There is also a great package for this. For this package click here.

1 like
RemiC's avatar

Hello, and welcome here.

I feel there's quite a contradiction in your approach. It would make sense if you use the same database/model to have a single Laravel application. By using two applications you will make things only harder to manage and to maintain. What are the reasons behind this choice ? Maybe we can suggest a better solution ?

sn0opr's avatar

@RemiC thank you for trying to help me. The two applications are different in use but they use the same database/models. It would be hard for us to make all that in single project, (so many views so many controllers etc...).

Let me give you an example similar to our project. A manufacturer have a (Production Application) and (Sales Application), they share the same database (they may have also their own db) they are really different and making them in the same project will be hard at the end of the day.

sn0opr's avatar

@Erik did you mean AppA\Models\User... ? But how is the folder structure ?

Arrilot's avatar

If both application are on the same server you can simply symlink models folder(create it if it doesn't exist) from one app to another.

You can even go futher and make a standalone composer package with you models. Develop it separately and require it in your projects via composer. Seems like a good idea for me.

1 like
RemiC's avatar

@arrilot : as appealing as it may seems, I don't think using symlink is a good idea. What if after 6 months they decide to move the Apps to their own servers to horizontally scale ?

+1 for making a composer package, that's the only way I would suggest for sharing code between applications.

Raph's avatar
Raph
Best Answer
Level 5

I've recently worked on a project that had similar requirements, where we had to have multiple Laravel projects use the same Model layer. My approach was along the lines of what @Arrilot is suggesting: creating a Composer package and then require it in your projects through Composer. In my case, I just had Composer pull in the Git repository

"repositories":[
   {
      "type":"git",
      "url":"git@bitbucket.org:company-git-name/company-shared.git"
   }
],

"require":{
   "laravel/framework":"5.0.*",
   "company-git-name/company-shared":"dev-develop"
},

There's a bit more information about how I went about this here: http://raphaeldavinci.com/laravel-shared-model/

Hopefully this helps!

11 likes
Arrilot's avatar

@RemiC Well they can switch from symlink to a composer package as soon as they need it, no problem here.

Symlink is just the fastest and the easiest way for the simplest scenario

punchi's avatar

Hi @Raph ! trying to make an "admin" here. I have already the "client/app" and the model classes are shared too. However, the method "Auth::loginUsingId();" will be very useful to log as the user and see exactly what's happening, but with your solution, as only the classes are shared, won't be available.

How you handle that? or it's possible what I need?

Thanks! =)

erikwestlund's avatar

Just bumping this to say thanks for the idea. @Raph's method worked for me. Here's my situation:

Laravel install for the main app Lumen as a worker app that handles various tasks behind the scenes. This runs on a separate server.

I share models between these. It worked fine just created them by hand and keeping them in sync but that just seemed so dirty.

I set up a private composer package with App\ as the namespace, added the repo to both my composer.json files, and things work fine.

It's a little annoying to have to commit, push, and run composer update to reflect changes in models, but I only have to do this sometimes.

1 like
sk_fahad's avatar

@raph I am working on a project that has a same requirement. Should I also create a private repository for migration files as well as factory files as they are allow us to create and seed database in single command?

mabreu's avatar

Hi, guys.

This approach, creating a composer package, can be used for other items on a Laravel project, like Controllers, Middlewares, JS files, CSS, views etc?

Thanks.

StephenB's avatar

Hi, Composer is a brilliant solution for this problem, but do be aware that the more shared code you have, the bigger impact it has for deployment and testing if you need to make changes to the core code. If you have 5 apps all pulling in the user model and then we change the user DB Schema. That is 5 apps that need to be changed at same time. You couldn't have 3/5 apps running with old DB Schema once the production DB schema updates.

xsa's avatar

Hi, lets say i have a package name myCore, which contains /Models. that i use in the laravel myFinalProject. The question is : How do you manage the developing/debugging phase of these shared components ? lets say i want to update myCore/Models/HelloWorld. Do you update the code the code in the vendor/myCompany/myCore and, when happy, you copy paste the updated files in the myCore repository and commit ? (it would be quite cumbersome)

I suppose pushing to gitlab (which builds the package), then having to composer update, is the worst solution; but, how do you guys do ?

enes1004's avatar

@xsa

I am someone using private package approach in work.

Short answer would be write tests and have your CI automated

Long answer would be

  1. write both package specific tests in package repo(myCore) and integration tests in the client repo(myFinalProject)
  2. do not use dev-master, release packages in tags for each with a certain amount of increment (not one commit, but maybe a few pull requests merged). Be sure they have tested well (may not be conclusive, coverage would be a good indicator)
  3. update composer in local, run tests for integration to check if it has problems

For 3rd step, you may automate it by CI apps like Renovate. It will create a PR for updated composer.lock.

As a note, if your myFinalProject is too coupled to details of myCore, it is an indication that some of myCore should be migrated to myFinalProject, or maybe myCore should be seperated into smaller and more modular packages. That would decrease the need for new tag release for large unchanging parts ( as they would have their own package ), and frequently changing parts would be merged to myFinalProject or would build some interface to hide changes. The interface would be some Contract implemented by different versions of code which you can replace it by each package releas, or, it would be talk to myFinalProject through an API (microservice)

Hope it helps

Please or to participate in this conversation.