Laravel + Vue frontend decoupling with optional server-side Blade rendering - php

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.

Related

Yii2 Advanced Template use model from frontend in console

I have a long list of models in frontend. Some of these have functions that are required to be run in batch. For this console is fine.
I can include the models by copying over the code, however this is not a decent approach.
What Im looking for a way to import models from the frontend submodule in console command so I can make changes in one place.
To clarify,
the standard way of including
use app\models\Mymodelname;
in the console\model results in the following error
'Class 'app\models\Mymodelname' not found'
use app\models\Mymodelname;
Have not worked with this include statement before. I prefer to use the frontend/backend as is. If I had to make a wild guess though, this looks for models within console. #app is an alias for current application.
Usually, I keep anything used by more than 1 application under common. As you pointed out, maintaining two copies of the same code is not a good practice.
Try using frontend\models\Mymodelname directly if moving to common is not an option
I don't know if you have two separate applications, or could benefit from this, as you are already using submodules, but depending on your desire to separate concerns with some console commands this might be advantageous.
If you are using composer to manage your dependencies then you can create a separate repository in git, for example, and add a new dependency in your project which contains these common models.
Then, include your dependency in both projects. This introduces some troubles while developing since both apps share this dependency and it can be frustrating at times; I have shared common functionality between multiple interval laravel projects in this fashion with great success.
Currently you seem to be using submodules so this might require restructuring which could be difficult or impossible.
Another option if you want to keep to submodules is to keep common models at a higher level (not inside a submodule) so that you can import the models into both submodules and use them in both places. I shared common models between modules with yii 1.1.16 using this strategy over several years with much success.
Both options have their advantages so weigh carefully your desired outcomes. Feel free to ask for clarification.
How to add private github repository as Composer dependency
#app is an alias of current running application. It can be frontend or backend or console. If you want to access model across applications, add it to commen\models. Or change app\models to frontend\models. That way, you can access frontend models on console. Better way is moving it to common\models.

Laravel 5 re-usable project

After some fiddling building a package for a project we've realised there's some issues with doing what we need to achieve as per Laravel 5 package development clarity
Maybe I should rather explain my goal and someone can suggest a direction to head in.
We've built a Laravel 5 application that now needs to be "re-used".
We had to modify Laravel and implement an Eloquent type base model as our data-source is actually C# Web Services. At the point the call would be made to a database we intercept this and make an "API" call to SOAP.
The major difference will be CSS, maybe some JS & content but all the routes/controllers/models will remain the same across all projects. Most configuration comes from endpoints.
Initially we considered creating multiple asset repositories for each site's styling and have a base repo which is the core Laravel project that gets included. This seemed to get quite complex as we couldn't simply just have a repo in a repo due to branching and multiple directory issues.
We then started experimenting with the idea of building the "core" as a Laravel package but we seem to constantly hit walls. The latest problem being including models in the package. For the models to be called we are using the root projects config/composer to access these models instead of just the service provider. It feels like the package is becoming to tightly coupled to the project config.
Are there any better ways of going about what we are trying to achieve?
Edit:
I forgot about the multiple branch solution on 1 repo but wouldn't this get ugly when it comes to feature development? Example:
master (core with releases that get pulled into _site*)
dev (master dev)
feedback-form (eg. master branch feature)
_site1 (root site with releases)
_site1-dev (_site1 dev)
_site1-reskin (eg. _site1 feature)
_site2 (root site with releases)
_site3 (root site with releases)
This leaving quite a bit of destructive merge power in the developers hands? Read access with pull requests maybe a solution to this?
So after some R&D it seems the best solution right now is to have 1 repo with multiple branches. Developers have read access and have each developer creates his own fork. Developers create pull requests and sync to parent repo through "upstream" remote and developers sync each others forks through additional remotes.
Seems a little clumsy but probably "cleanest" option.

Best practice for Laravel 4 + Zurb Foundation 5?

TL;DR: what is the best way to arrange files, package managers and build tools for Laravel 4 + Zurb Foundation 5 combo (with Compass) as one consistent repository with clean public (static) section?
I wanted to start a fresh project, based on latest Laravel on the backend side and using Foundation for the frontend. I am new to both of these and apparently I missed some of the tooling that was developed meanwhile when I wasn't doing PHP for some time.
My confusion:
Laravel uses Composer for installation and dependency/module management. (Ok, I'm new to Composer)
Foundation is available as a Composer module (but then what?), but generally also as a CLI tool that creates a new project and uses bower for module/dependency management. But then I have two repositories.
Is it required for me to expose all my .scss files, or maybe even put the whole Foundation project into laravel's public dir to make all work?
How do people usually approach using these frameworks together? They shouldn't interfere, but they still have totally different tooling.
Where do I put my foundation files? Keep it as composer module or inside public? How to refer to them? How to have one build everything command?
I have the same issue as using Bootstrap SCSS version for Admin & Foundation SCSS for the frontend. I noticed also that both css frameworks come as composer packages however the issue you have with this approach is that you generally use other Javascript files in a development that will be merged also so using the composer versions just adds to the confusion.
The best solution i found was using either gulp or grunt with bower at the top level of your Laravel build. Rather that go through the configuration for you there is a good article at http://blog.elenakolevska.com/using-grunt-with-laravel-and-bootstrap/ that goes over a bootstrap integration but this can be tweaked for Foundation. This solution is good as grunt has many of the other popular javascript libraries that you may use in your project also..
Alternatively you could use an application like codekit and create a compass project to manage the merging & compiling of your assets into the public folder. As a side note if using git again your would need to exclude additional folders from your project.
If you think of your SCSS framework files as development assets there is no real need for them to be in the project as you only really need one version of Foundation on your development machine.
Your custom SCSS changes can be added to your Laravel project as modules ie a navigation module, via a private composer repo for the project or just added to the Compass project at development time. Your public folder should only be referencing the final merged style.css & java.js files for example. Any images from the framework can then just be copied over to the public folder ie icons etc.. Hope that helps..
Personally I have a "static" directory which houses static files. That is where I use SASS watchers, grunt tasks and basically the entire front-end workflow. The results of that front-end build process gets added to a "production" Laravel public directory after getting built, etc.
A pro of this is that everything (static assets and laravel application) is separate.
A con is that updating Laravel views with any updates in HTML templates you may build in the static directory. If you update the templates, you may also need to update the view files, which becomes more tedious as you add more templating logic around the HTML in the views.
Just one suggestion.

Laravel 4 plug-in system

I looking for some plugin structure for Laravel based applications.
For example a forum software, a cms or a e-commerce application can benefit from a plugin structure.
My question is what is the best way to implement this plugin system so that third party plugins can extend the application. The main issue is that it should be dynamically extendible and users should be able to install these plugins easily without messing with the app code.
This question also extends to themes but thats another question. Any ideas?
Laravel is a framework, not a CMS like Wordpress or Joomla, so plugin system that fits everybody may be quite hard to create as Laravel can be used in many ways, but I can really see the benefit of easy packages in some contexts.
The Packagist has been already mentioned and it doesn't solve directly your problem but how about:
Find good usable packages from Packagist for the purposes you need
Define common plugin architecture (common API for binding things together, installer, package format, migration, updates etc) on top of Packagist packages
Create installer that fetches packages via Packagist/Composer and adds sets sane default settings and configuration for the packages and integrates them into the defined plugin architecture
Document and plan this really well and the others will soon follow
I'm a little confused about the question, but I believe what you are looking for is already implemented in Laravel 4. They are just called Packages, and can be found at http://www.packagist.org and easily installed and autoloaded into your application using Composer.

Best way to package a general-purpose zend module

As our company starts using Zend Framework as the base framework for most of our projects, we want to share some common elements across all our projects. I talk about things like:
An implementation of a model (based on doctrine2)
RBAC for the model, including user, group, role models
A xml-based templating engine for ajax backend interfaces
(you name it) ...
Basically, all things to put "zend on rails" and get going. What is the best way to package these components? I see two possibilities:
As modules
We include the necessary functions as separate modules into the modules folder.
Pro:
We can set routes and execute code, which is good for many modules (imaginary example: a paypal module needs some kind of callback url. If our module can set it up on its own, no configuration from the "project developer" is needed).
We can provide real functionality (like the user administration) out of the box
We have a bootstrap to set up autoloading and doctrine etc.
Con:
Bad place? Interferes with the users project
A little harder to share between projects (git submodules instead of classpath)
In the library folder
We put it in the library folder and point the classpath to it.
Pro:
Clean solution
Sharing across projects
Con:
Bootstrap has to be explicitly called
No direct routing or actions - everything has to be proxied through the concrete project
So, how do you solve this? Where do you put your reusable, general purpose stuff in zf?
I think you should use both approaches.
When developing "library-like" code, as in kind of "infrastructure" classes and other things that are reusable (like ZF's own components, Doctrine 2's components etc.), you can put them into the library directory. (or its own entirely separate project)
When developing actual ZF modules (like an auth module for example), then format the code around the ZF module structure.
I think by using this kind of approach you get all the benfits you listed, and pretty much none of the cons :)
As one additional idea, if you develop your architecture parts as "services", you could even keep them running as their own web service endpoints.

Categories