Read composer extra config in regular code - php

Using composer config extra.foo bar I can set custom data in composer.json and according to the documentation composer scripts can read it using $event->getComposer()->getPackage()->getExtra()
I would like to read it in a regular script (installed as a vendor binary) so the binary can be configured by the user, e.g. the binary requires a configuration file which I would like to put in extra.config.
Does composer support this or do I need to manually locate and parse composer.json? Is there a better solution for letting the user add configuration?

The documentation part you are refering to is about PHP-Scripts that get triggered as event-handler during a composer-invocation. So composer runs and provides the configuration-information while invoking the script.
When I understand your approach right, you want to be able to read the information while running your own script without composer. Then - as composer is not involved - composer can not provide any information.
So what you could do is read the composer.json file, parse it as JSON and get the for you relevant information from it.
But then it's nothing else than reading any other configuration file. So I would use a separate file for configuration. That would allow you to use a config also for projects that don't use composer (whyever one would want to do that...). And separation of concerns is also a good idea!
You perhaps might want to have a look at f.e. phpunit, phpcs or travis on how they handle their specific configuration issues within their scripts.

Related

Can I specify php memory limit requirements in composer json? Perhaps in the "config.platform" node?

I just got a memory limit error and I solved it in my .ini files. No worries. However, I'd like to put something in my package composer.json to indicated that some minimum memory is required. I know how to specify a php version requirement in composer.json - I'm just wondering if other platform requirements can be added/checked by composer.
Composer can check for software to verify if they are corresponding. But, it doesn't check the system (CPU, memory...). You can specify the requirements in a readme.md file.
You can add in your code the memory limit needed in your script. But, in general, the default memory limit is enough. You may be have loops you can optimize by adding yeld or iterators.
The complete list of properties available in composer.json is very well-documented.
The only one which makes requirements on a user's system is the require section. This can include platform dependencies (also discussed on the "basic usage" page) in the form of virtual packages exposing the version of PHP, its extensions and related libraries, and Composer itself. These are resolved as part of the dependency resolution process, and not when the application runs, although you can enable an additional platform check.
Note that the config section configures the behaviour of Composer itself, not the package, and is marked "root-only" - that is, it will not even be read when another project uses your library. The platform option which you've mentioned is the opposite of a platform requirement: it tells Composer to pretend certain constraints are met even when they are not.
If you want to verify at run-time that a particular configuration is in place, rather than merely documenting it, you can easily write your own using functions such as ini_get. This can either be run as part of initialisation of some relevant object or function, or listed as a file include in the autoload section so that it will always be executed as the application starts up.
UPDATE: Although this is the only working solution provided - please read the comment thread. There are good arguments against this. Also, this requires strong working knowledge of writing and deploying vendor packages. Specifically, you'll want to know how to roll this back when a better solution is posted or the problematic package is fixed.
Add a little php file to your composer project or package.
composer.json
{
...
"autoload": {
...
"files": ["tweak_ini.php"]
}
}
tweak_ini.php
Obviously you'll want to add some logic to make sure you aren't downgrading.
ini_set('memory_limit','1000M');
...

About Google Calendar API and PHP

I am trying to write a webpage that will present to the public the contents of one of my Google Calendars. The standard iframe doesn't give me the format I'd like and I also want to embed some schema.org event information, update and submit a sitemap, etc.
As I'm fairly experienced with PHP, I'm trying to extract data from the Google Calendar API. I looked at Google's quickstart https://developers.google.com/calendar/quickstart/php but it assumes a level of knowledge I don't possess.
It seems I need to use something called "composer" and tells me I need to do "composer require google/apiclient:^2.0" but I'm unclear where exactly I type this - I can't see anywhere obvious in cPanel - or maybe it goes at the start of my PHP code?
Also, I note that the sample code is command-line only and I can't find code anywhere that would appear to be capable of running as a PHP web page. Is that because it's just not possible?
Composer is a dependency manager like bower, npm, yarn etc., the list goes on and on. Firstly you'll have to install composer here and add it to your PATH variable (method depends on OS).
Afterwards, when you create a directory for your project in the www-folder of your WAMP/LAMP or another folder acting as webroot, you can execute the composer require command. This will generate a folder called 'vendor' (with your dependency as a subdirectory) and a composer.json & composer.lock file, the latter 2 files will contain all the 'required dependencies' of composer.
You can then include the dependency using the require_once()-function in your PHP-script.
Hopefully this helps.
Cheers.

PHP Composer - How to work with multiple vendors?

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.

How can I safely add to a composer package?

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

How to bundle PHPUnit with my code?

I would like to:
Run tests with PHPUnit regardless of my environment (and if PHPUnit or PEAR is installed or not)
Show test results on screen if possible
How can I do this? I tried downloading the code here and including Autoload.php but it still have some dependencies. Maybe there's some better approach for this than trying to bundle it with my code...?
To include PHPUnit in your projects source files I'd suggest following the guide:
Using PHPUnit From a Git Checkout from the PHPUnit Contributung section.
It tells you about all the packages you need to install and shows you show to build a runner/wrapper script for the phpunit executable.
#!/bin/bash
php -d include_path='.:../phpunit/:../dbunit/:../php-code-coverage/:../php-file-iterator/:../php-invoker/:../php-text-template/:../php-timer:../php-token-stream:../phpunit-mock-objects/:../phpunit-selenium/:../phpunit-story/:/usr/local/lib/php' ../phpunit/phpunit.php $*
You can adapt the path to your need or if you want to wrap it in another script you can also use phpunit somewhat programmatically by
require '/path/to/phpunit/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
This assumes that you ether have a phpunit.xml.dist file or that you use the proper cli parameters when calling your wrapper script.
You can also use the pear packages and unpack all the stable versions instead of working from the git checkout to save some disk and repo space. The wrapper script and all the include path work is the same :)
Related SO questions:
PHP - Is there a portable version of PHPUnit?
PHPUNIT without installation
The dependencies will be dependent on what add-ons you're using, PHPUnit by itself should be self contained. Since there's no particularly consistent package management solution for PHP (and you've eliminated the most viable options aside from wheel reinvention), your best bet would be to include the files in the source tree separate from the application code. Creating a sibling directory from whatever your APPLICATION_ROOT or similar would be that is named "test" and that has a "lib" or similar directory full of PHPUnit and any dependencies you need for it would likely be a good plan. There should be no overlapping and a one way dependency from the test dir to the main application source.
I'm assuming you're looking for a healthcheck automated test page, so you could create the single page that includes what is needed from that test directory. Ideally if you have the web directory which exposes your static resources you could have the PHP file that is in charge of loading the Front Controller for your application by including the application folder from outside of the document root, and then a second file that loads the test suite. That would allow your application directory to remain focused on the application code itself, the test directory to house your testing code, and then the 2 small include files which are in charge of loading the codebases (with any kind of shared constant definitions, etc. also extracted and kept DRY).
There is a consistent package management solution for PHP - http://getComposer.org. It also now has a means to install PHPunit in the usual composer style, http://packagist.org/packages/phpunit/phpunit
With the software installed, it will put the phpunit command line script into the local 'bin/' directory, so you can call it, though you will likely want to have a shell script that also sets the configuration file it will use.
The usual setup is a tests/ subdirectory with the hierarchy of PHPunit-extending classes that run the actual tests.

Categories