How to configure tcpdf when installing with Composer? - php

Our legacy PHP code includes tcpdf (https://github.com/tecnickcom/TCPDF) as part of the code base.
I am trying to move it out to a vendor folder, so I added Composer to the project, added TCPDF to composer.json and updated.
But the config/tcpdf_config.php file is modified in our code base (custom PDF author name etc.), and rightfully so, according to the docs: http://www.tcpdf.org/installation.php
Now, I'm not sure it's a good idea to modify vendor/tecnick.com/tcpdf/config/tcpdf_config.php because it might be overwritten by Composer any time I update. Also, there is not a word about Composer in the tcpdf docs.
What is the right solution to configure tcpdf (or any third-party library used through Composer, for that matter) while allowing Composer updates?

The way you are supposed to inject your configuration is to define all the constants first before ever touching the first TCPDF class.
Make sure to also set the constant K_TCPDF_EXTERNAL_CONFIG to true. This will prevent the autoconfiguration to search for the file you were talking about. (See line 60 of this file here: http://sourceforge.net/p/tcpdf/code/ci/master/tree/tcpdf_autoconfig.php)
This is well hidden in the documentation, but I found this: http://www.tcpdf.org/doc/code/example__019_8php.html
How to override TCPDF config using Composer
Copy the original tcpdf_config.php somewhere to your project, for example src/tcpdf_config.php.
Add define('K_TCPDF_EXTERNAL_CONFIG', true); at the beginning of your config copy and modify the rest of the config to your needs.
Edit your composer.json and add/update autoload section:
...
"autoload": {
...
"files": [
"src/tcpdf_config.php",
...
]
}
...
Regenerate the composer autoloader using composer dump-autoload.

Related

How to use one module in two different application/project in yii2

I have module created in the basic project of yii2 and now i want to access or use that module another project/application of mine....
How can I achieve this.
please help me out here.
To use module in different apps there are 3 things you need.
The module must not be dependent on classes from core project. For any class that needs to be implemented by core project the module should define interface and depend on that interface instead of class itself.
The module should use different namespace than app and autoloader must know how to load classes from that namespace. (more about that later)
You have to add module in your config in same way you've added it in first project.
The points 1 and 3 are pretty much self-explaining. If are not sure how to add module in config see the yii2 guide.
Now back to the second point. While naive way of copying module over to second project would work it will turn maintaining the module into nightmare because each change would have to be done in each copy of module. So it's better to keep the code of module in one place and make it available for each project. There are multiple ways of doing that.
If you want to, you can turn your module into extension and make it publicly available through packagist as it was suggested by M. Eriksson in comments. After that you would simply add your extension through composer as any other dependency.
Composer also allows you to define and use private repositories if you don't want to publish your module at packagist. See composer documentation for more details.
The most trivial way is to simply put the code into separate folder outside of project. If you do that, you have to make sure that autoloaders in your projects are capable of finding the files locations to load classes. There are two options how to do that. In any case you will want to avoid conflicts with namespaces used by your project, that's why you need to use different namespace.
Let's assume that you've put your module files into folder /path/to/modules/myModule and all classes in your module belongs to namespace modules\myModule. You have to make sure that your webserver can access that folder and that it can run php scripts there.
First option is to use Yii's autoloader. That autoloader uses aliases to look for classes. If you add #modules alias and point it to /path/to/modules folder, the Yii autoloader will try to look for any class from modules\* namespace in /path/to/modules folder. You can add the alias in your config file (web.php, console.php or any other config file you use):
return [
// ...
'aliases' => [
'#modules' => '/path/to/modules',
// ... other aliases ...
],
];
The second option is to use project's composer.json file to set autoloader generated by composer to load your classes.
{
"autoload": {
"psr-4": {
"modules\\": "/path/to/modules"
}
}
}
You can find more info about this in composer's documentation.
Don't forget to run composer dump-autoload after you change autoload settings in your composer.json file to update the generated autoloader.

How to avoid "Could not scan for classes inside" error with Composer?

(I know others have written about this, but the answers don't seem to help in this instance)
I have a WordPress PHP plugin (https://github.com/LiquidChurch/lqd-messages/) which uses WDS-Shortcodes which in turn uses TGM-Plugin-Activation. When I run composer install from within the lqd-messages plugin I get the following error:
In ClassMapGenerator.php line 69:
Could not scan for classes inside "/lqd-messages/vendor/webdevstudios/wds-shortcodes/vendor/tgmpa/tgm-plugin-activation/class-tgm-plugin-activation.php" which does not appear to be a file or folder"
I can then go into /lqd-messages/vendor/webdevstudios/wds-shortcodes/vendor and see that there is no tgmpa folder.
If I then go back to /wds-shortcodes and run composer install, the tgmpa folder will be successfully created.
Obviously, this is less than ideal. Is there a way to get around these extra steps?
This is bug in webdevstudios/wds-shortcodes package - their autoloadig settings are incorrect. Dependencies should not declare loading files from other dependencies inside of vendor directory - this is not their concern (and these files will not exist in some scenarios, like yours).
I can only recommend forking this package and fixing autoloading settings:
"autoload": {
"classmap": ["includes/"]
},
BTW: You've made the same mistake in your package.

Symfony - How to override a vendor component which is not in a bundle

I'm searching for override a file which is in the vendor's directory
but is not a bundle.
I'm working with Symfony 2.7
To be more specific, i'm trying to override a method in this file :
vendor/akeneo/pim-community-dev/src/Pim/Component/Catalog/Updater/ProductUpdater.php
And I'd like to do it in a file like :
src/MyApp/Component/Catalog/Updater/ProductUpdater.php
All the documentation I've found is relied to parts of a Bundle.
So, is it even possible to do that ?
If it is, how to do it ?
There is a way to override a file using composer.
You can add in your composer.json under the autoload->psr-4 key something like this.
"autoload": {
"psr-4": {
"Pim\\Component\\Catalog\\Updater\\": "MyApp/Pim/Component/Catalog/Updater"
},
Where the first part is the namespace of the file you want to override and the second part is the new path.
This can create some issues when you add new packages to composer, so make sure you run composer dump-autoload to recreated the autoload order.
i don't really like this method, but it did save me a couple of times to fix files from bundles without actually forking the bundle, and if nothing else helps this can me used as a last resort.
More about composer autoload here
https://getcomposer.org/doc/01-basic-usage.md#autoloading
Hope this helps,
Alexandru Cosoi

How to check if composer's autoloader is being used?

I'm developing a certain PHP framework for WordPress, and I want to give my users the option to use composer to install it as a package, or to install it manually. If composer is used, then a psr-4 class autoloader handles everything. If not, then all files must be loaded manually during the framework's bootstrapping process.
Is there a safe way to check whether composer's autoloader is being used in a given WordPress environment?
Currently i'm using:
if( !class_exists('Composer\\Autoload\\ClassLoader') )
{
// Manually include files if composer is not used.
require_once 'some/files.php';
}
However, if in a given WordPress environment there is a plugin that uses composer internally, then the above if statement will return true even though other plugins have no access to it.
The solution, as it turns out, is quite simple. You need to create 2 different bootstrapping files, say manual-bootstrap.php and composer-bootstrap.php. Then add the following lines to composer.json:
"autoload": {
"files": ["composer-bootstrap.php"]
}
composer-bootstrap.php will only be called if composer is used to load the framework as a dependency. Users that want to load the framework manually will use manual-bootstrap.php instead.
if(class_exists("\Composer\Autoload\ClassLoader"))
{
// a composer autoload.php has already been included/required
}

Own project via composer

I've got some libraries loaded through composer, and I'm wondering if it's possible to add my own library in the /vendor map, and then to have the composer autoloader load it? The structure would be something like /vendor/mylibrary/ and then a namespace mylibrary.
Would this be possible? Also would it be possible to add a different map to the composer autoloader? Like for example /app/src/ and then to have it load all the classes in that folder? Or do I have to make my own loader for that?
Thanks
Reading the composer documentation:
You can even add your own code to the autoloader by adding an autoload field to composer.json.
{
"autoload": {
"psr-0": {"Acme": "src/"}
}
}
Composer will register a PSR-0 autoloader for the Acme namespace.
You define a mapping from namespaces to directories. The src directory would be in your project root, on the same level as vendor directory is. An example filename would be src/Acme/Foo.php containing an Acme\Foo class.
After adding the autoload field, you have to re-run install to
re-generate the vendor/autoload.php file.
So basically, you just need to follow PSR-0, and tell composer where to find your library, by adding that line to your composer.json
Yes.You can achieve it. Configure your composer.json file as following:
{
"autoload": {
"classmap": [ "classes" ]
}
Here classes is the name of the directory where you have all your application related classes.Vendor related class should be auto detected as well. Just add the following line to achieve both at the same time:
require 'vendor/autoload.php';
And you can use the namesapce to reference your class like the following:
use classes\Model\Article;
Yes, of course it is possible to add own libraries and you should feel highly encouraged to do so. If your library is available publicly, you can simply register it at packagist.org. If not, it's a bit more complicated, but not impossible.
If your project does not follow the PSR-0 standard, composer will create a classmap for you. A custom autoloader is not supported.
I'd recommend you to read the (really excellent) documentation about all this and come back, if you're running into problems.
http://getcomposer.org/doc/

Categories