How to autoload another package with own composer - php

EDIT with important note: The package I want to include does not use composer autoload. I'd have to use their hacky one and I want to avoid that.
I know how composer mostly works and I have package that can be a dependency (that's important, I know how to make this work in one project, but that's not what I'm asking).
What I need?
Somebody requires my package
composer require tomas/my-package
It will install
It will autoload my package with PSR-4
It will autoload 3rd party package as well
I have already tried something like this:
"autoload": {
"psr-4": {
"MyPackage\\": "src",
"PHP_CodeSniffer\\": "../../squizlabs/php_codesniffer/src"
}
}
I've tried that in one of my dependencies and it doesn't work :(.
Also, I've already talked to the package author and he doesn't want to use composer autoloading. He prefers his own.
Thanks for any help!

None if these answer are related to problem I desribed, so I try to post best solution so far:
I got inspired in PHPStan, which has feture to autoload directories, that were missed in composer (practically same issue).
I've added RobotLoader:
composer require nette/robot-loader
Then create LegacyCompatibility class with static method:
use Nette\Loaders\RobotLoader;
// ...
public static function autoloadCodeSniffer(): void
{
$robotLoader = new RobotLoader;
$robotLoader->acceptFiles = '*.php';
$robotLoader->setTempDirectory(sys_get_temp_dir() . '/_robot_loader');
$robotLoader->addDirectory(getcwd() . '/vendor/squizlabs/php_codesniffer/src');
$robotLoader->register();
}
And I call it, when needed:
LegacyCompatibility::autoloadCodeSniffer()
Works like a charm. But still opened to better solutions +1 !
Github Permalink

You are doing one big NO-NO in your composer.json file: You are defining autoloading for code that is not in your package.
This will fail, as you found out already.
And I wonder why you are struggling with integrating the PHP Codesniffer, because that package has a working autoloading definition included. All you'd need to do is "require": { "squizlabs/php_codesniffer": "^3.0#RC" } (if you really need the latest 3.x release candidate, otherwise ^2.8.0 would be a better idea).
If you require PHP_Codesniffer instead of somehow referencing it in your autoloading, then Composer will do everything to integrate that package: download it, add it to the autoloader, and run it's code if necessary. And anyone depending on YOUR package will also get this dependency installed.
The only problem you state is that "it doesn't work", which is no sufficient description of a problem because you lack describing what you did in your code, and what error message you got. Also state what you expected to happen, and what happened instead (and how this deviated from your expectation if this isn't obvious).

Related

PHP error calling a function from a package

I am new to php and have just installed my first package via composer. I'm now trying to call a function from the package I installed as follows:
<?php
require_once 'vendor/autoload.php';
$value = 1;
$aws = AmazonGiftCode::make()->buyGiftCard($value);
echo $aws;
?>
But I get the following error:
PHP Fatal error: Uncaught Error: Class 'AmazonGiftCode' not found in
/public_html/php/test.php:4 Stack trace:
#0 {main} thrown in /public_html/php/test.php on line 4
Based on my (albeit limited) experience with other languages, I'm guessing I have to load the package that contains the class first. The package folder is in the same directory as the test.php file, in the subfolder vendor/kamerk22/AmazonGiftCode/. But I think this is where I don't know enough to troubleshoot it based on the information I could find.
Your directory structure should look like this.
test.php
composer.json
vendor
└───autoload.php
└───kamerk22
└───AmazonGiftCode
Make sure you installed the package using composer, and not by downloading it.
I'm guessing I have to load the package that contains the class first.
Unlike what you would normally expect when importing stuff, when using composer you only have to import the autoload.php file, and composer will take care of loading other packages as needed. By as needed what I mean is that as soon as composer sees you use the AmazonGiftCode class it will import the AmazonGiftCode package, but if one of your REST endpoints doesn't use anything from the AmazonGiftCode package it won't ever load it. This allows you to not have to worry about slowing down the entire application when you want to use a composer package for only a few endpoints. At least that's the way I understand how composer works.
Just run composer dump-autoload once and the class should known then.
You could also get verbose and use kamerk22\AmazonGiftCode\AmazonGiftCode;
But that AmazonGiftCode looks quite Laravel specific... that's why it may still fail, even if it may be found by auto-load. One needs to setup Laravel framework in the first place; just see this query (just in case if you may wonder where all these missing classes may come from).

Trying to use a composer package in laravel

Im using Laravel 5.8.
Im trying to use the following package
https://packagist.org/packages/s1lentium/iptools
To install it i have run:
composer require s1lentium/iptools
Confirmed the require line is in the composer.json
"s1lentium/iptools": "^1.1"
and that the package is in "vendor/s1lentium/iptools/"
How can i reference it in the code (controller or even in a view)??
When I try to use the IP class Laravel cannot find it.
I've researched a lot and but without success. Hope anyone can lead me to the correct step.
Thanks!
Run composer dump-autoload
You must call the IP class with \IPTools\IP, or use it:
use IPTools\IP;
Hope it helps.

Class 'AWeberAPI' not found

I got no clue why AWeberAPI is not found. Any help is appreciated.
php code:
require('vendor/autoload.php');
new PHPExcel;
new AWeberAPI;
composer.json:
{
"require": {
"aweber/aweber": "^1.1",
"phpoffice/phpexcel": "^1.8"
}
}
The problem
The module doesn't appear to be properly configured for use/autoloading with composer. They may have just added the composer configuration to allow you to easily install it, but not to use it within the composer autoloader.
The generic convention for it is that AWeberAPI should match the package's PSR-4 autoloader format, which says "look in aweber_api", then it will look for a class named AWeberAPI.php. You can test this behaviour is correct by adding this file:
<?php
// File: vendor/aweber/aweber/aweber_api/AWeberAPI.php
class AWeberAPI {
public function __construct() {
die('yeah, it works now...');
}
}
Then try your script again, the class will exist now.
What can I do?
Well - you could submit a pull request to their repository to fix it, but it looks like it would involve renaming the classes and filenames which would be a breaking change so I probably wouldn't bother.
You can get it to work by requiring the actual source of the API library instead of the composer autoloader in this case:
require_once 'vendor/aweber/aweber/aweber_api/aweber_api.php';

"Member has private access error" after deleting plugin in CakePHP using PhpStorm

After deleting a plugin from my CakePHP Framework and all the lines of code associated with it I get an error in the getInitializer function of the autoload_static.php in my vendor->composer folder:
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit8835d383dd0f2dc92619594332e8ea7e::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit8835d383dd0f2dc92619594332e8ea7e::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit8835d383dd0f2dc92619594332e8ea7e::$prefixesPsr0;
$loader->classMap = ComposerStaticInit8835d383dd0f2dc92619594332e8ea7e::$classMap;
}, null, ClassLoader::class);
}
All the prefixes and the classMap are underlined and the error message says:
"Member has private access"
I'm fairly new to PHP, so my question would be how to handle this error? I suppose it's not safe to just delete this 4 lines of code.
I already tried to update composer and invalidate caches/restart in PhpStorm.
EDIT 1
I surely shouldn't have deleted the lines of code related to the old plugin manually out of the composer files.
composer diagnose:
Checking composer.json: FAIL
require.cakephp/plugin-installer : unbound version constraints (*) should be avoided
Checking platform settings: FAIL
The OpenSSL library (0.9.8y) used by PHP does not support TLSv1.2 or TLSv1.1.
If possible you should upgrade OpenSSL to version 1.0.1 or above.
Checking git settings: OK
Checking http connectivity to packagist: Warning: Accessing packagist.org over http which is an insecure protocol.
As the project isn't too old, it might be the easiest way just to delete it completely and restart from scratch or is there an easy solution to that?
The lines are technically incorrectly highlighted as errors, and they were highlighted as errors even before you've modified the code.
The code will bind a specific object and scope to a closure, in this case it will bind the $loader object (an instance of ClassLoader) with the ClassLoader::class scope. This will cause the closure to be bound to the $loader object in a way that makes private methods visible to it, and hence things won't error out at runtime.
So the problem is just that the PhpStorm parser isn't smart enough (yet) to recognize this.
See also http://www.php.net/manual/en/closure.bind.php
As far as your other composer problems are concerned, vendor files should always be safe to delete, ie the vendor folder should normally only contain code installed through composer, which means that in case you screw things up big, you should be able to simply delete the vendor folder, fix up your composer.json file (and delete the composer.lock file) if necessary, and then just run the composer update or composer install command again.

Fatal error: Class 'NexmoMessage' not found

I'm using this library to implement the Nexmo SMS service on my server. I required the library using Composer like so:
"require" : {
"prawnsalad/nexmo": "dev-master"
}
which I found here and followed the instructions included in the README like so:
require 'vendor/autoload.php';
use NexmoMessage;
$phone = '123456789';
$sms = new NexmoMessage(NEXMO_KEY, NEXMO_SECRET);//defined in another file
$sms->sendText($phone, 'from', "yo");//$phone is a valid number in actual case
However I keep getting the error in the title of this question. I see that Composer has imported the library successfully and I see the class and constructor for NexmoMessage, yet for some reason this error keeps happening no matter what I do. I'm not sure if this is due to an issue with the library or with how I'm using Composer. I've never had an issue with Composer in the past so I'm boggled why this is happening here. Thanks
Well, that library states that it supports PSR-4, which means they absolutely MUST use PHP namespaces, but they don't. That last commit 8 months ago https://github.com/prawnsalad/Nexmo-PHP-lib/commit/8e422c4f8f43c52acb70ebd5f9e7c6ff81a1f352 broke the autoloading. And nobody noticed up to today.
You can easily tell by looking at the source code: There is no namespace being used.
Your best action now would be to fix this issue and send a pull request! Github allows to edit files in the browser! Second best action would be to create an issue and let the authors know.

Categories