I am working on several projects but each one connects to a REST web service.
I've developed the first one using Laravel, and developed a few classes really useful to communicate with the web services.
I would like to start the second one, and of course, reuse the classes developed for the REST connection.
My problem is, my company wants me to use several git directories for the projects, and each one should be uploaded to a different springloops project.
Springloops is a bit like github, you can upload your code using git.
How would you proceed to avoid copy/paste and use the same laravel code but in different projects (and I guess, in different locations)?
I'm not sure I'm really clear, but don't hesitate to ask me for more information if you need to.
Thanks.
How about creating your own Composer package and store it in a separate (private) Git repo? As far as Composer is concerned it's just like any other package, you may want to check out this section of the docs:
Using private repositories
Exactly the same solution allows you to work with your private
repositories at GitHub and BitBucket:
{
"require": {
"vendor/my-private-repo": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:vendor/my-private-repo.git"
}
]
}
The only requirement is the installation of SSH keys for a git client.
Related
Let's say that there's a CMS made with Laravel. We would be providing different clients with that same CMS, upgrade their CMS on every release we create but have a configuration file that would define what features are available for each client. The entire backoffice (admin panel etc.) would be mostly static and would use Vue only for certain dynamic elements. This solution suits our needs when it comes to the backend.
However, we plan on deploying different end-user frontends for each of these clients. Decoupling those sounds very simple (create a completely separate frontend project and use API endpoints to fetch and render everything dynamically) but if we were to completely decouple the frontend and the backend we would lose the ability to render static pages using Laravel Blade and we need that feature for the certain pages because of the rendering speed, loading times, SEO etc.
The main question is: how to decouple the frontend from the backend for each client without losing the ability to render pages with Laravel and Blade while keeping the development and testing easy?
One of the solutions that comes to my mind is to create a post-build step where we would "merge" the client-specific frontend files into the CMS but this would make the development process very difficult or would even make it all practically impossible to develop and test.
The second solution that comes to my mind would be to:
Keep everything in one Git repository.
Develop the CMS on it's own branch and develop only the backend and backoffice stuff on that branch and it's children.
Create separate branches (What's the best practice for putting multiple projects in a git repository? perhaps some of the solutions presented here?) for different end-user frontends and develop only the end-user frontend on those branches.
Merge the CMS branch into the client branches on each release.
This solution seems viable and would allow us to use Laravel Mix and server-side rendering but it's very prone to human error and it would make it very difficult for us to keep track of these branches after a while. One of the other potential solutions that I've read about is using Git submodules but I simply have difficulty grasping how that works and it seems that it is not as flexible as it should be in this use case.
What would actually be the best architectural solution for us here?
I would think of your CMS as a package, and think of your different front-end pieces as separate projects that each have a dependency on your CMS. For instance, I use Backpack for Laravel for a number of projects: https://github.com/Laravel-Backpack/CRUD which I think is similar to what you're describing - a common set of core functionality with an un-opinionated front-end.
Laravel packages can register routes, publish views and assets, pull in migrations, etc etc - really anything you can do in a Laravel app can be done via a composer package.
So you would take the functionality that is repeated between your builds, and extract that into a "core" package that can be required via composer. Then the front-end stuff can be built in projects that simply require your core codebase. When you update your main core package, you can go into each front-end build and pull in the new version of the core via composer. This would give you an opportunity to roll the new core version out to each project one-by-one, making sure you can resolve issues or adapt to breaking changes on those projects individually.
Your core package can also include any front-end components that are commonly re-used across your client projects, so ideally you aren't re-writing any code between the front end projects.
It can be challenging to make that core code modular enough to be a standalone package, but I think that makes the most sense based on what I understand about your project. Hope it helps.
When you´re decoupling your system I strongly suggest not to pick the easiest solution without first guarantee it can scale and be ( as one of your concerns is ) easy to test.
Let´s call your core product CMS vanilla, it works as supposed and designed to be. Now you have CMS Chocolate wich is slightly different on the frontend, here´s what I did:
Keep UI theme ( template files, images, js, css, etc. ) in one single repository (i.e. yourcompany/cms-front) and each version in its own branch ( v-vanilla, v-chocolate, v-strawberry)
On your UI Theme you will need to include a simple composer.json file to describe the project
On your CMS project give each version its own branch and force version name match its corresponding layout name.
Reference your front repository in your cms composer.json, I´m assuming We´re talking about a private one here otherwise next lines won´t be necesary.
{
"repositories": [
{
"type": "vcs",
"url": "git#github.com:your-company/cms-front.git"
}
],
"config": {
"github-oauth": {
"github.com": "******"
}
}
}
Add yourcompany/cms-front#dev-$version dependencie to your composer.
composer require yourcompany/cms-front#dev-chocolate
You will need a post-build step to copy from vendor/your-company/cms-$version to your project but this is easy
{
"scripts": {
"sync-theme": [
"cp -r vendor/your-company/cms-front/resources app/resources",
"cp -r vendor/your-company/cms-front/public app/public",
],
"post-install-cmd": [
"#sync-theme"
],
"post-update-cmd": [
"#sync-theme"
]
}
}
Add yourcompany/cms-front#dev-$version on your composer dependencies.
Switch between themes whenever you feel to.
I am working on a project with multiple local git repositories that tie together into a single app. Pretty much like Symfony has different components our app is split up similarly.
My question is, what is the proper way to link to these packages?
I know I can do something like this:
"repositories": [
{ "type": "path", "url": "../another-component" },
{ "type": "path", "url": "../yet-another-component" }
]
This still forces me to do composer install to pull in the packages though. It clones the local git repository that I am using for development whenever I run composer install.
Obviously I do not want to do this every single time I adjust a component that makes up a part of my main app to pull in any changes I have done to repositories that make up my main app repository.
Is there a better way to keep development repositories in sync with each other? Or can I tweak this to get what I want?
I am guessing a lot of developers run into this problem so there must be a well thought out solution for this?
Cheers.
Edit
I have also seen this article which goes over the same concept:
http://tech.vg.no/2014/11/25/using-local-packages-as-composer-dependencies/#comment-522050
The problem is that everytime you make changes to one of the repositories that make up your app you have to run: composer update which is a hassle. I am really looking for a way to just keep them properly in sync.
The above solution works fine, I had to delete my lockfile and clear the composer cache though. Instead of cloning a repository composer will make a symlink and your repositories will be kept in sync.
It might not be advisable to delete your lockfile so if anyone has a better suggestion please post a comment.
We currently have Yii2 base project (we can say, like, project root from which we will create other projects). Right now there are several modules, models, controllers and viewers. Everything is fine here but how to deploy (and where) so that when we update base project, all child projects that were using our base project would be updated (best is through Composer with composer update).
For example, Kartik has its plugins/widgets and we can simply update through Composer with command like $ php composer.phar require kartik-v/yii2-grid "#dev".
So we want to have something similar, but not accessible publicly (so that random people couldn't access without some sort of email/username/password). This part is not as important as the first part because in this part we at least can use something like BitBucket. There aren't many possible solutions, most likely a few only, actually, but it's a challenge that we cannot solve right now.
I have tried StackExchange but it's not as popular StackOverflow, so I'm trying to give as much information as I can. Assuming I see this question, this question shouldn't be off-topic either. Thanks!
You could use your own private repository for keeping yii2 app template. To update all your projects use composer. Here's code example:
"repositories": [
{
"type":"package",
"package": {
"name": "repo-name/yii2template",
"version":"master",
"source": {
"url": "https://your-git-server.com/repo-name/yii2template.git",
"type": "git",
"reference":"master"
}
}
}
],
So when you make changes to your template, you just update composer for certain project and get those changes.
P.S. Another idea is Ansible. You can update child projects by this tool, but you have to write playbook manually for your needs.
If you need this template local only, you could use PhpStorm, it can make templates from project.
I have an application server, it is like a blog system (my wordpress killer). It is based in php hosted in github and using composer to manage dependencies. Each installation is hosted in my server (I make the installation for them). When a client requires a new "addon/plugin" I create a new package and host it in a private repository hosting. The problems comes when I need to add new package:
Client 1.
- package for calculate prices
Client 2.
- package for show a welcome message
Client 3.
- package for add a calendar
My application will have every package ready to be used in all instances because I am requiring them via composer:
"require": {
"killer/calculate": "dev-master",
"killer/message": "dev-master",
"killer/calendar": "dev-master"
}
Now image if I have 2K clients and everyone of them are requesting custom packages. How can I provide an application (cloned massively) but just keeping in the each installation just the packages that each client need?
Hypothetical solution
I was searching (if it is possible) for something like the following. For each installation, create a file manually where its content specifies the package to be required. For example, let's say each client's installation has something like this:
//composer.json
"require": {
}
//plugins.json (this file is ignored via .gitignore)
{
"killer/calculate": "dev-master"
}
Then, somehow tells to composer.json to require the data from plugins.json. By this way I am avoiding to create a huge composer.json sharing unnecessary packages for all clients.
There is a feature request for allowing composer.json to extend another file. You should go comment on it to draw some attention to it.
The way you would use that feature is to create a default.json file that contains all your regular composer.json contents, including a require section that lists all the common packages you need.
// default.json
{
"require": {
"php": ">=5.4.0"
}
}
Then have a composer.json file for each project that extends and/or overrides default.json like this:
// composer.json
{
"require": {
"killer/calculate": "dev-master"
},
"extends": "default.json"
}
The final result would be:
{
"require": {
"php": ">=5.4.0",
"killer/calculate": "dev-master"
}
}
If you can't wait on the merge request, then you can go checkout the composer fork from the merge request's author and try it out.
Sounds like you have created your own package ecosystem. So, you could work independently from Packagist and simply host all the packages yourself, probably using Satis.
The main suggestion i have is to introduce your application as a package into this ecosystem.
Your application composer.json contains only the packages relevant for the application itself.
{
"name": "better/application",
"require": {
"another/library": "1.0.0",
"another/framework": "1.2.3",
"another/generator": "2.1.3"
},
"require-dev" : {
"phpunit/phpunit" : "4.*",
}
}
I think, that "cloning" the application for the customer/client is not a good idea, because it ignores that plugins have dependencies on a specific version of your application, which is not always "latest" or "dev-master". Let Composer pull the application by version for each client.
By this way I am avoiding to create a huge composer.json sharing unnecessary packages for all clients.
create one repository per new customer/client
add the application itself and the packages requested by the client inside composer.json
add a client config on top
For instance, the composer.json for Client1:
{
"name": "better/application-for-client1",
"require": {
"better/application": "1.0.0",
"better/app-calculate": "1.2.3"
}
}
For instance, the composer.json for Client2:
{
"name": "better/application-for-client2",
"require": {
"better/application": "1.0.1",
"better/app-calculate": "1.2.4",
"better/app-message": "2.0.0"
}
}
Each customer might have its own setup, requiring different version of your application with different additional application packages/plugins (here indicated by using the prefix "app-").
In the end you have two essential files for a customer: a composer.json and a configuration file.
(How the application detects the available modules is another story. At least, the autoloading will work out of the box, when you register Composers Autoloader during the bootstrap of the application.)
(Sidenote: If your application is a multi-site application, then you might replace "cloning" by "symlinking". With multi-site, i mean an application which runs from one central place using a site id (often customer id). If you have the application folder with all packages for development in one monolithic folder, then build a relase folder by cleaning the development stuff out, so that you get a release version with a blank default config. Then symlink the application, the requested packages to the customer folder and place a configuration on top. This approach might save quite a bit disk space and doesn't involve Composer at all.)
I would also encourage you to use the approach proposed by Jens A. Koch in his answer, having a composer.json file for each customer and requiring the main application and all required plugins. Composer supports this scenario quite well and I want to point you to the starting points:
Composer Types
Composer allows to specify types for packages. You can define your own type to mark plugins for your application as such. Many open-source projects (e.g. Symfony with bundles) have adopted this approach for their plugin eco-system.
Custom Installers
You can register custom installers that can execute for a specific type of composer package (i.e. the type you defined for your plugins). Then you can customize the installation process for your plugins, which means you can:
move your custom plugins to specific locations,
automatically adjust plugin configurations,
and most importantly: provide a mechanism that allows the main application to see which plugins are available.
Hmm.. require all packages ones..
It means one big composer.json for everything is running with your system / is compatible with your system. Maybe you will have to introduce a versioning system too.. So you could end up with v1_composer.json ..
But for each client load only the required packages. For example generate a requires.php for each client with necessary require statements which links to your shared libraries.. This will be the fastest solution and most efficient, because you sharing the code which you can share and you only load it when needed
Conclusion
Share as much code as possible... but don't use it when you don't need it.
I have a git repo that contains a few small and related libraries. Since the platform I am working with lacks proper dependency management, dealing with many git repos is a hassle, hence my team decided to put these into one git repo. I'm now working on having our software being installable via Composer. It is however not clear to me how to register each component in this git repo, as I'm not even sure it is possible to have more then one composer.json file per repo. Is this possible? And if so, how?
"is it possible to have more then one composer.json file per repo."
No.
You can't register the components separately, they will be registered as one big dependency and you will have to import them all into other projects, rather than being able to pull them individually.
However you can register where each component lives in the directory structure so that the autoloader is able to load them correctly.
"autoload": {
"psr-0": {
"Intahwebz\\Component1": "src/Component1",
"Intahwebz\\Component2": "src/Intahwebz/Component2",
"Intahwebz": "src/"
}
}
After including the Composer generated autoloader, creating a new class of type Intahwebz\Component1\TestClass will find it in the correct directory.