In Prestashop I can write my modules. But I have some code that is framework independent and I want to reuse in other Prestamodules AND in other frameworks I use.
So far so good. My solution was to put an Vendor folder and a composer.json to my Prestamodules to get those libaries I needed.
Now comes the problem that (offcourse) duplicated namespaces get into conflict. Is there a way around for this or should I do a global vendor folder in the root of Presta (what I want to avoid at any cost, I want to decide when I upgrade a single module or not. So the vendors should be per-module)
Vendors can't be per module if they are executed in the same request. You have to use a central vendor folder for all your dependencies - or you avoid using Composer and try to manage individual dependencies yourself - with the same problem as before: You cannot have two versions of the same class in your code.
Which one gets used? The first that the code encounters, depending on how autoloading is configured. Assume "random" order - it will break your code at the most inconvenient time.
Related
My team has recently put together a Laravel codebase that works great for multiple websites. Currently we are running them as an app that installs on a centOS7 profile.
Whenever a new site is required, we fire up a profile, and the code gets cloned in. The codebase depends heavily on packages (custom laravel packages). Currently every site pulls in all of the packages that we have developed. Currently the differences are 1) The .env file. and 2) The theme config files (which come from a package and I'll touch on later).
I want to be able to pull packages based on need, I don't want to pull in every package we've developed. My question is, is there a way around pulling in every package? I was thinking of removing the composer.json file from git and treating it like a config file? I also thought about generating the composer.json file.
Eventually we want to add CI/CD to the process and really automate this thing. I am really fighting to keep the codebase in one repository. Am I wrong? Should we split the codebase up, one repository per project that comes in? But then you have to consider that updates become a nightmare.
Currently, themes are pulled in as packages. Every site has all of the themes in the composer file. The app has admin users that can login and set a theme to active. Still, I'd like if it only pulled in the necessary themes resources.
Sorry if I rambled a bit, but I am wondering how to scale the application properly.
Thanks a bunch!
tldr; How can I run multiple websites using one codebase, while being able to specify different required custom packages?
I haven't actually tested this but you might be able to accomplish what you want by defining multiple composer.json files. Read more on defining other composer.json files
Then, in each composer.json file define a different vendor directory. Example:
{
"config": {
"vendor-dir": "plugins"
}
}
Next, on each install specify which composer.json file to install, From the docs:
By setting the COMPOSER env variable it is possible to set the filename of composer.json to something else.
Example from docs:
COMPOSER=composer-other.json php composer.phar install
Read more on specifying the environment.
Last but not least, you will have to bootstrap your website or application for the specific vendor directory:
require __DIR__.'/../custom-vendor-directory/autoload.php';
This can be customized in your application's index.php file. The original source.
Our current development setup uses a single Subversion repository containing multiple projects, each with branches, tags, and trunk. We then use a "sparse checkout" to select the projects, and branches of those projects, to work with.
The result is that the directory structure of a working copy matches that of the repository, including branch information, and we never use svn switch. (This style of working will probably be familiar to anyone who uses SVN, but may be surprising to those who don't.)
We are thinking of using Composer to manage both external and internal dependencies, but I'm not sure how this can work with the sparse checkout style of working.
I would like some way of using a directory within the existing checkout to satisfy a dependency, rather than each "root project" needing a separate copy.
For example:
sites/Foo/trunk
depends on lib Aaa, so references lib/Aaa/trunk
depends on lib Bbb 1.5.*, so references lib/Bbb/branches/release-1.5
sites/Bar/trunk
depends on lib Aaa 1.0.*, so references lib/Aaa/branches/release-1.0
depends on lib Bbb 1.5.*, so references lib/Bbb/branches/release-1.5
At present, if I edit the code in lib/Bbb/branches/release-1.5, I can test those changes on both sites, without needing to commit one and update the other.
Is there any way of using Composer to manage these dependencies?
(PS: Please don't answer with "give up on SVN, use Git, it is teh awesomez"; that is an answer to a different question.)
No - I do not believe that you can do this with Composer as standard: it expects to copy the files from whichever source (Packagist/VCS/Zips) to the local vendor folder, which is not what you want.
That said, I believe there are two potential ways you could get this working (at least in part):
Autoloader
You could try using the autoload field in the composer.json file to include the correct files into the project. You would still need to manage the checkouts of the relevant branches/versions manually (like I assume you do now), but you would be able to manage the inclusion of the internal libraries through Composer. This will probably require that your libraries are properly namespaced. The paths to the files for each namespace are relative to the root of the project, but can go below the root (via the /../ path) if required.
To be honest though, if you already have an autoloader for these files, there may not be much advantage to this solution. Relevant Docs
Composer Plugin
You could also write a composer plugin/"custom installer" that could probably manage this. This would have the advantage that you could have it manage checking out the correct parts of the sparse repository to have the correct version available, as well as doing correct wildstar version checking, but would be a much more difficult and riskier venture.
The basic process would be that you would define a new package type (e.g. 'internal-svn-package'). You would create the plugin as an external library that gets installed normally via Composer, which declares (via it's composer.json) that it handles this new type of package. Your custom logic would then be used for any packages that are listed with this custom type. I'm not sure how much of the internal composer logic for SVN checkouts you would be able to reuse however. Relevant Docs
The project I'm working on requires using the PHP SDK's from multiple 3rd parties. Two of these are Amazon Web Services and the Google API Client (for Google+), and both of them use Composer to manage their files / dependencies. I'm not sure how to best set it up code / structure wise, though, because I don't need both AWS and Google loaded together. I might need AWS in one area and Google in another, so I don't want to just autoload everything every time and have the additional overhead from libraries I don't need right then. Right now I have the structure set up like this:
awscode.php
googlecode.php
libs
composer.json
composer.lock
vendor
autoload.php
aws
google
So, everything Composer related is in a shared composer.json file, and all vendor files in the single vendor directory. But, I can't seem to find a way to just load up say AWS. It wants me to use the autoload.php from what I can tell, which seems to want to load up everything.
Do I need to set it up more like this if I want control over each library?
awscode.php
googlecode.php
libs
aws
composer.json
composer.lock
vendor
autoload.php
aws
google
composer.json
composer.lock
vendor
autoload.php
google
I'm obviously new to Composer and how to best utilize it, and want to make sure that I am setting it up the best way for both my situation, and for future management.
When using Composer, it only loads the classes when they are actually called in your code. To my knowledge this uses the PHP spl_autoload_register.
So in answer to your question, there won't be a significant extra overhead (if any).
Autoloading means that the file which defines a class gets read when you first use that class.
You should include all your project dependencies in one composer.json, they won't be loaded in files you don't use them in.
I'm encountering a wholly predictable yet incredibly annoying and tough to resolve problem.
I've been working on a PHP framework for developing WordPress plugins. It's using Composer for dependency management. Of course, the problem is if you have two instances of my framework in the same installation of WordPress, you have two vendor folders, and two copies of any packages required by the framework. Which leads to an error.
The framework functions as a separate plugin which is then inherited by any apps/plugins that are build on it.
Move the vendor folder to the core framework folder?
Problems: I don't know what would happen if I have two composer.json files and two composer.phar files writing to the same vendor folder and using the same autoloader. Presumably it wouldn't be good. Besides that, it doesn't solve the problem of collisions with composer packages that could be used by any other script or plugin outside of what I'm trying to handle.
So I'm stuck. Is this a problem that can be solved, or is it just inherent in PHP?
Composer is not really meant to be used multiple times in same project. On other hand there is nothing terribly wrong with it either, however you lose its dependencies features and need to treat this like generic case of dependencies in WordPress environment.
In other words - if you are not doing dependencies Composer way and WordPress is not doing dependencies at all, it becomes your personal problem how to deal with it.
I don't know what would happen if I have two composer.json files and two composer.phar files writing to the same vendor folder and using the same autoloader
I am not following why the vendor folder would be same if you are using multiple composer installs... Could you elaborate on how you structure it and is it meant for public or private use?
I'm not very familar with Composer or the plugin framework you are using, but in general - avoiding function/class name collisions in WordPress plugins is done in the following manner:
Assuming that your plugin (e.g. MyCoolPlugin) is written object-oriented, e.g. as a class named MyCoolPlugin, you may include the helper class/library as a subclass of MyCoolPlugin.
class_exists(), this is PHPs way of finding if a class has been defined. Assuming your helper class the following:
class MyHelperClass{
}
You may use the following check before declaring the class in each of your plugins:
if(!class_exists('MyHelperClass')){
class MyHelperClass{
}
}
Of course, there is a trade-off here, because only the first instance of the class will be used throughour WordPress. E.g. if you have two plugins with two different versions of the helper class - only one of them will be active and available at any given moment.
A global variable - e.g. define('MY_HELPER_IS_LOADED', true); in the helper files (in case you are including them via include() or require()). Then in the beginning of each included helper file check with if(defined('MY_HELPER_IS_LOADED')) return;, which will cause the currently requested file for include/require to NOT be included.
Again the tactics above are used in PHP in general, I am not sure how your plugin framework is set up exactly.
I am using the Composer package Omnipay in my project and I want to add a new class to the package (in my case it is support for a new payment gateway). The naming does not conflict with anything and it follows the same naming and structure conventions as sibling folders. However, when I run composer update it deletes my whole folder of changes even though it didn't need to. Is there a way I can tell composer not to delete that directory?
Leave everything under /vendor alone, don't change any files there. You should treat libraries as external dependencies - don't check them into source control or change them in any way. Just reference them in your own code.
If you need to customize a composer library, you can either work around it in your own code (most PHP libraries support dependency injection, which will let you override any of the libraries' classes), or alternatively you can fork the library on github, then reference your own fork in composer.json, or submit the pull request so everyone can benefit from it.
As far as I'm aware, you cannot add to a Composer package as it is external and therefore out of your control. You should treat the packages as libraries only, and add all classes into your own project, ensuring that the packages you need are still set up in your .json file