Using a vendor not namespaced into laravel 5.3 - php

There is a vendor that I want to use that was originally created for Symphony and it isn't namespaced into Laravel, I'm not too sure on how to make it work.
Here is the package: https://github.com/caponica/AmazonMwsComplete
I read somewhere that I would have to add psr-0 into composer and I already have the psr-4 default data in composer so I added:
"psr-0": {
"MWS\\": "caponica/amazon-mws-complete"
},
The MWS\\ I just made up since I wasn't too sure what to do and the other portion is the vendor folders, figured that's what I needed.
So, when I tried to call the class into routes for testing I tried:
use MWS\CaponicaAmazonMwsComplete\AmazonClient\MwsProductClient;
and it keeps saying that the MwsProductClient class isn't found.

It happened because you are trying to use wrong path and namespace. Accrording to the source code of package you are trying to use the namespace you want to load is namespace CaponicaAmazonMwsComplete\AmazonClient;
So you need to include this into you composer.json file:
"psr-0": {
"CaponicaAmazonMwsComplete\\": "caponica/amazon-mws-complete/src"
},
I'm not 100% sure but it should work. Don't forget to run composer dump-autoload before using.
If it doesn't work add a comment here and I will check it again.
UPDATE:
So I managed it to work using PSR-4 autoload:
"psr-4": {
"App\\": "app/",
"CaponicaAmazonMwsComplete\\": "vendor/caponica/amazon-mws-complete/src/CaponicaAmazonMwsComplete",
"AmazonPhpClientLibrary\\": "vendor/caponica/amazon-mws-complete/src/AmazonPhpClientLibrary"
}
But note that this library is quite outdated and it's documentation doesn't fits it's code.

Related

Composer class not found even if it exists

I'm developing a Laravel package but I have a problem with composer autoloading.
My package has 2 folders under src folder. One of them is named Laravel and the other one is Telegram. Here is the package structure:
./packages
.../typhoon
...../src
......./Laravel
........./Providers
............LumenServiceProvider.php
............LaravelServiceProvider.php
......./Telegram
..........Api.php
.....composer.json
This package is developed under SaliBhdr/Typhoon namespace.
I have added the packages/typhoon/src directory in Laravel's composer file like so:
"autoload": {
"psr-4": {
"App\\": "app/",
"SaliBhdr\\Typhoon\\" : "packages/typhoon/src/"
}
},
And add the src/ address in package composer.json file like so:
"autoload": {
"psr-4": {
"SaliBhdr\\Typhoon\\": "src/"
}
},
Here is the strange behavior begins. When I execute the php artisan serve command Laravel throws an error that says :
Class 'Salibhdr\Typhoon\Laravel\Providers\LumenServiceProvider' not found
And if I check if the class exists with class_exists('Salibhdr\Typhoon\Laravel\Providers\LumenServiceProvider') function it returns false. But if I check if Salibhdr\Typhoon\Telegram\Api exists it returns true.
I checked the autoload_classmap file and notice that the composer includes all the classes under Telegram subfolder but not Laravel subfolder.
Why composer acts weird like this? why did it include one subfolder and not the other? It is something that I do every day and never seen anything like this.
I desperately need help. Any help would be appreciated
You are trying to initialize Salibhdr\Typhoon\Laravel\Providers\LumenServiceProvider but in your composer it's "SaliBhdr\\Typhoon\\": "src/".
Notice the capital B in your composer. PHP classes are case sensitive so you have to make sure it's either both lowercase or both uppercase.
Also make sure to run composer dumpautoload if you modify composer.json.

Autoloading PHP file in composer package

I'm trying to create a composer package that also contains src/functions.php with some general functions. I have the following in composer.json to make it autoload:
"autoload": {
"files": ["src/functions.php"]
}
When I import this package into a project it will try to load src/functions.php in the current project (local) in stead of the imported package. Is there a way to ensure the correct file is loaded when imported (./vendor/bla/src/functions.php)?
Autoloading is not for loading everything. If src/functions.php contains class just ensure it's properly namespaced and I see no reason why autoloader would pick your local class instead of package's. If you are using the same namespace for the package and for code in your project then basically you should stop doing so.
If src/functions.php is just bunch of functions, then I strognly suggest refactoring the code and wrap them in properly namespaced class. You can make your functions static methods so basically not much would change from usage perspective.
EDIT
Once you finish refactoring, change your composer.json from what you shown in question to:
"autoload": {
"classmap": ["src/"]
}

Composer doesn't autoload packages

I'm currently developing a framework but I couldn't figure out how am I going to set autoloading. First I created a package with sample class and composer.json. I've autoloaded that sample class by:
"autoload": {
"classmap": [
"libs/"
]
}
I've checked /vendor/mypackage/vendor/composer/autoload_classmap.php and confirmed that package's autoloader is working fine. But the problem is I can't reach that package's class from main app unless I directly include that package's autoload.php.
UPDATE
/vendor/foo/mypackage/composer.json
"autoload": {
"psr-4": {
"Http\\": "libs/"
}
}
/vendor/foo/mypackage/libs/Request.php
namespace Http;
class Request {}
First of all, it's often better to use psr-0 or psr-4 autoloading config. With the classmap, you have to redump the autoloader each time you add a new class or rename one.
You always need to include the Composer autoloader by using require 'vendor/autoload.php';. The best place to add such require statement is in your front controller file.
Solved it by myself. I just had to reinstall package whenever I change pacakge's composer.json.

Strategy to override a class in a library installed with Composer

I am using Codeigniter and Composer. One of the requirements is PHPExcel. Now I need to change a function in one of the classes. What should be the best strategy to do it? Should I change the code in the vendor folder? If so, how to maintain the change across all the instances? If not how do I override that particular class. Though I mention PHPExcel I would like a generic solution.
I am not sure if this is the right forum for this question. If not i will remove this. Please let me know if any more details are needed.
Thank You.
In composer.json, under ["autoload"]["psr-4"], add an entry with namespace as the key and path as the value:
{
"autoload": {
"psr-4": {
"BuggyVendor\\Namespace\\": "myfixes/BuggyVendor/Namespace"
}
}
}
Copy files you want to override under that path (keeping sub-namespace directory structure) and edit them there. They will be picked in preference to the library package's original "classpath". It would seem that namespace->path mappings added to composer.json in this manner are considered before those added by required packages. Note: I just tried it and it worked, though I don't know if it is an intended feature or what possible gotchas are.
EDIT: found a gotcha. Sometimes when you subsequently require another package with composer require vendor/package, you will "lose" the override. If this happens, you must issue composer dump-autoload manually. This will restore the correct autoload order honoring your override.
Adding these last 2 lines to the autoload section of my composer.json is what worked for me when I wanted to override just one file within the vendors directory:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
},
"exclude-from-classmap": ["vendor/somepackagehere/blah/Something.php"],
"files": ["app/Overrides/Something.php"]
},
Remember that the namespace within app/Overrides/Something.php needs to match whatever the original was in vendor/somepackagehere/blah/Something.php.
Remember to run composer dump-autoload after editing the composer.json.
Docs: https://getcomposer.org/doc/04-schema.md#files
There is one more option.
In case you need to rewrite the only class you can use files in composer.json like this
"autoload": {
"files": ["path/to/rewritten/Class.php"]
}
So if you want to rewrite class Some\Namespace\MyClass put it like this
#path/to/rewritten/Class.php
namespace Some\Namespace;
class MyClass {
#do whatever you want here
}
Upon each request composer will load that file into memory, so when it comes to use Some\Namespace\MyClass - implementation from path/to/rewritten/Class.php will be used.
Changing an existing class is against OOP and SOLID principles (Open to extension/Closed for modification principle specificaly). So the solution here is not to change the code directly, but to extend the code to add your functionnality.
In an ideal world you should never change a piece of code that you don't own.
In fact, with composer you can't because your change will be overrided when updating dependencies.
A solution in your case is to create a class at the application level, and extend the class you want to change (which is at the library level) to override with your code. Please look at extending a class in PHP if you don't know how.
Then typically, you load your class instead of their class, this way, you add your functionnality on top of their functionnality, and in case of an update, nothing break (in case of a non breaking update).

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