I'm developing my first Larvel-based package. I want to include the Socialite package, so I put it like this in my composer.json file
"require": {
"laravel/socialite": "^2.0"
},
Now, how do I include the provider and the alias as you'd normally do in /config/app.php ?
I think by now I've read every stackoverflow there is about this matter, but nothing seems to work.
This is my package's serviceprovider:
public function boot()
{
include __DIR__.'/routes.php';
$this->app->register('Laravel\Socialite\SocialiteServiceProvider');
$this->app->alias('Laravel\Socialite\Facades\Socialite', 'Socialite');
$this->loadViewsFrom(__DIR__.'/../views', 'package-name');
$this->loadTranslationsFrom(__DIR__.'/../lang', 'package-name');
$this->publishes([
__DIR__.'/../views' => resource_path('views/vendor/package-name'),
]);
$this->publishes([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'migrations');
}
Result:
Class 'Laravel\Socialite\SocialiteServiceProvider' not found
UPDATE
"psr-4": {
"App\\": "app/",
"Rubenwouters\\CrmLauncher\\": "packages/rubenwouters/crm-launcher/src/"
}
In your package's service provider in register method you can do:
public function boot() {
$this->app->register(ClassOfScialiteServiceProvider);
$this->app->alias(FacedeClass, 'Alias');
}
EDIT
But first of all... To add your package in the right way (to the vendor that you can adding a requirments) you have to some how add it to the main composer.json - required list. You can do it with one of below:
1
Adding you package to the official composer repository (packagist)
2
Make your own composer repository like Satis
3
The easiest way is to add your git repo dependanci inside composer.json like:
"repositories": [
{
"type": "vcs",
"url": "git#your_repo/crm-launcher.git"
},
],
"require": {
(...)
"rubenwouters/crm-launcher": "dev-master"
}
OR
or just move your dependencies ("laravel/socialite": "^2.0") to the main composer.json. :)
Register Laravel\Socialite\SocialiteServiceProvider::class, to Config\app.php as providers and also
Register 'Socialize' => Laravel\Socialite\Facades\Socialite::class, to Config\app.php as aliases.
May be this will solve your problem.
Related
So I'm working on a composer plugin that adds a custom command that can be run after an install or update.
I understand the autoloading configuration, and composer is autoloading all classes but it's also missing a file that just contains namespaced functions.
In my plugin composer.json I have the following:
{
"name": "myco/composer-s3-downloader",
"type": "composer-plugin",
"version": "0.1",
"require": {
"composer-plugin-api": "1.1.*",
"aws/aws-sdk-php": "3.20.*"
},
"autoload": {
"psr-4": {"MyCo\\Composer\\": "MyCo/"}
},
"extra": {
"class": "MyCo\\Composer\\S3Downloader"
}
}
My plugin classes load without a problem. All of the classes for my dependencies also load without a problem. So my plugin command code starts off just fine using the AWS SDK.
The problems comes here, when I try to instantiate an S3Client:
private function initClient() {
if (is_null($this->_s3Client)) {
$this->_s3Client = new \Aws\S3\S3Client([
"version" => "latest",
"region" => 'us-west-2',
"credentials" => [
"key" => $this->_creds['key'],
"secret" => $this->_creds['secret'],
]]);
}
}
I get the following error:
PHP Fatal error: Call to undefined function Aws\manifest()
in .../test/vendor/aws/aws-sdk-php/src/AwsClient.php on line 143
I can see the autoload config in the AWS composer.json and it's correct:
"autoload": {
"psr-4": {
"Aws\\": "src/"
},
"files": ["src/functions.php"]
}
The Aws\manifest function is declared in functions.php. And functions.php is then specified in vendor/composer/autoload_files.php. But near as I can tell that file isn't being loaded. So not all of my dependencies are actually available.
What step am I missing that forces the inclusion of autoload_files.php? I'm not doing a single include for anything in the vendor folder. I'm assuming that composer will handle that for me. But I guess I'm wrong.
So after posting an issue at the Composer Github repo, I did learn that the autoloader that runs during composer execution only includes classes. So if you do need to include loose functions, you'll have to manually run the full autoloader.
I added the following method to my Command class that is loaded by composer and defined in the extra section of the plugin's composer.json.
private function getIncludes() {
$vendorDir = $this->composerInstance->getConfig()->get('vendor-dir');
require $vendorDir . '/autoload.php';
}
I just call it in my plugin constructor and everything I need becomes available.
I'm learning how to make a composer package. So far I've done this:
composer.json
{
"name": "Iv/MyPackage",
"autoload": {
"psr-4": {
"Iv\\MyPackage\\": "src/"
}
},
"require": {
"guzzlehttp/guzzle": "~6.0"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"guzzlehttp/guzzle": "~6.0"
},
"autoload-dev": {
"psr-4": {
"Iv\\MyPackage\\Tests\\": "tests/"
}
}
}
And I have a class under the namespace: namespace Iv\MyPackage\Api; called Consumer and in its __construct method it has this:
public function __construct(array $credentials)
{
$this->client = new Client();
$this->credentials = $credentials;
}
And on the top of that class I have use GuzzleHttp\Client;.
The error I'm getting is:
Fatal error: Class 'GuzzleHttp\Client' not found in path\to\package\Iv\MyPackage\src\Api\Consumer.php on line 27 when I do:
$package = new Iv\MyPackage\Api\Consumer(['user', 'password']);
$query = $api->prepare('/api-endpoint', 'GET');
Edit:
This is what my Consumer class looks like:
<?php
namespace Iv\MyPackage\Api;
use GuzzleHttp\Client;
class Consumer
{
private $credentials = [];
public function __construct(array $credentials)
{
$this->client = new Client();
$this->credentials = $credentials;
}
...
}
Also I'm using PhpStorm, which tells me that I have the GuzzleHttp package, because it autoimports it for me when I type Client() and press ALT + ENTER. Which means I have ran composer install/update.
Edit 2:
I have a file - index.php which has the following:
<?php
include('vendor/autoload.php');
$api = new Iv\MyPackage\Api\Consumer(['user', 'password']);
$query = $api->prepare('/endpoint', 'GET');
var_dump($api->execute($query));
The folder structure is as it follows:
-Iv/
--MyPackage/
---src/
----Api/
----Exceptions/
----vendor/
----tests/
----otherfiles (composer.json, phpunit.xml, etc)
-vendor/
-composer.json
-index.php (I mentioned above)
Edit 3:
The content of my vendor/composer/autoload_psr4.php:
<?php
// autoload_psr4.php #generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Iv\\MyPackage\\Tests\\' => array($baseDir . '/tests'),
'Iv\\MyPackage\\' => array($baseDir . '/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
);
Edit 4:
In the folder where is index.php I have this composer:
{
"name": "Test MyPackage",
"autoload": {
"psr-4": {"Iv\\MyPackage\\": "Iv/MyPackage/src"}
}
}
^^ I saw that on SO in a topic that OP was asking how to test his package before uploading it to packagist/git. I can load the Consumer class, no errors about it, but every dependency is not found. (GuzzleHttp\Client, Symfony\Component\Yaml\Parser, etc)
In the composer.json in the main directory you are missing a reference to your package. You are just autoloading it, but you are not autoloading all of its dependencies.
To do this you have to add a section like this in your composer.json in the main directory:
"repositories": [
{
"url": "path/to/your/package",
"type": "path"
}
]
and add it to the require section, some thing like:
"require": {
"Iv/MyPackage" : "dev-master"
}
Alternatively, you could just move your dependencies from the composer.json inside your package to the one in the main directory
I think you pretty much mixed everything up a bit, but it is solvable.
What I see is that you have an odd directory structure: You have Iv/MyPackage/src/... in your main project (i.e. on the same level there is a file composer.json).
IF you want to use your "Iv/MyPackage" as a Composer package in your main project, you have to add it as a dependency. This means that your package name must appear inside a "require"-Section in the main composer.json file. Currently it is not. Instead of this, you manually added autoloading for the path your package is currently in - without telling Composer that this should be treated as a package, and that it has dependencies that should also be downloaded.
You added the dependencies of your package inside the directory of it, but this is not how Composer works.
To fix it, you have to do two simple things:
Add your package as a dependency in your main composer.json.
If your package is currently hosted in a private repository, you have to add it's URL to the repositories key in composer.json.
The first one is just this:
{
"name": "Test MyPackage",
"require": {
"Iv/MyPackage": "dev-master"
},
"autoload": {
}
}
Remove the autoloading for your package - it is contained inside that package already. If you want Composer to autoload your main project, add that autoloading here (and I suggest you do, because you'd probably cannot write a better autoloader yourself).
Second thing is adding the repository:
{
"name": "Test MyPackage",
"repositories": [
{
"type": "vcs",
"url": "your repo url, either http or ssh"
}
],
"require": {
"Iv/MyPackage": "dev-master"
},
"autoload": {
}
}
This tells Composer to look into that repository and see if it can find something. Everything found is added to the collection of known packages (with the default source being Packagist) and used to select the best version matches.
Some corrections you should apply:
Package names should be lower case, so it's better to use iv/mypackage.
If you give a name in your main project, it has to follow the form <vendor>/<package>, not be some random string with a name. Composer will not deny working, but once you get there you will benefit from more of the available infrastructure in the Composer area, and correct names will help you. Otherwise, just leave it out for the moment.
This should set you up and running. I probably can answer more details you didn't even ask, but suggest you read about Composer on the documentation page or here on Stackoverflow, because the common problems usually have already been solved.
My issue is I have a package which isn't a repository and I am trying to get it to play nice with Laravel and composer. It is still located under the vendor folder, the only issue is that if I simply set:
"psr-0": {
"Test\\Test": "vendor/test/test/src/"
}
This will load the service provider but none of the controllers etc will autoload. What is the correct way to implement a package with larval that does not have it's own repository. Or does this go against the nature of packages and this should simply be structured under the applications controllers.
The package was created by me using workbench but I found i did not really need this as a separate repository but it would still be good to keep it as a package. Therefore the structure is exactly the same as a regular package:
vendor
testvendor
testpackage
public
src
tests
.gitignore
composer.json
phpunit.xml
UPDATE:
As a solution for the time being I am using:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php",
"vendor/package"
]
},
As an entry in the class map. Looking forward I will probably refactor this into the app folder or create a repository for this package.
If you have some classes that you're calling "package", you're not supposed to add those files to your vendor folder. This folder is managed by composer and at any time you might loose it. Create a subfolder in your application and put those files there.
You have to be sure your PSR-0 autoloading will work for every single file in your folder structure. So, if your root is vendor/test/test/src/ and your namespace is
Test\\Test
All your files must be in
vendor/test/test/src/Test/Test/ClassFileName.php
PSR-4 is easier to deal and understand, this
"psr-4": {
"Test\\Test\\": "vendor/test/test/src/"
}
Means that your files would have to be like:
vendor/test/test/src/ClassFileName.php
Doublecheck your namespaces. It's easy to make mistakes when using namespaces with PSR-0 and remember that
composer dump-autoload
Must be ran every time you change things in composer.json or create new files. If it's a simple class autoloading, every time you create a file, if it's a PSR-X autoloading, everytime you create or update a namespace in your composer.json file.
If what you have is is really a package you should use Composer: when your package is structured as a composer package (check Laravel's composer.json as an example), the correct way of adding it to your application, if it's not list in Packagist, is via repositories.
You can have (non-packagist) packages in a public VCS repository:
{
"require": {
"monolog/monolog": "dev-bugfix"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/igorw/monolog"
}
]
}
You can have (non-packagist) packages in a protected by password VCS repository (git, bitbucket...):
{
"require": {
"vendor/my-private-repo": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:vendor/my-private-repo.git"
}
]
}
You can have your packages zipped in your hard drive and load them via the artifact repository type:
"repositories": [
{
"type": "artifact",
"url": "path/to/directory/with/zips/"
}
],
Though #Antonio Carlos Ribeiro's answer is really nice, I had problem with installing custom packages locally(which is also stated in the last part of his answer)
Let's assume this is the directory structure of the package we are trying to install:
D:/test_pack
src/
composer.json
If you do not want to upload your custom package (that most likely you have developed, yourself) to online repositories you can use one of the following two methods:
Method I
(You have to specify version for your package, otherwise you'll get this error: The requested package could not be found in any version, there may be a typo in the package name.)
1) In composer.json, Add version to your package. your package's json should look something like this:
{
"name": "gandalf/test_pack",//This is your package's name
"description": "some desc",
"version": "1.0.0",//This is the version that you have to specify
"authors": [
{
"name": "gandalf the grey",
"email": "fake#yahoo.com"
}
],
"minimum-stability": "dev",
"require": {
"laravel/framework": "~5.4"
},
"autoload": {
"psr-4": {
"Gandalf\\BotPack\\": "src/"
}
} }
2) zip your package(let's assume the zip file is in D:/test_pack/test_packa.zip)
3) In laravel's composer.json add your package name (in our case gandalf/test_pack into require part of json) and add the repository array to the composer.json file and in that array specify the directory in which your package's zip file exists(in our case D:/test_pack) . like this
{
...,
"require": {//adding our package name to laravel's composer.json
...,
"gandalf/test_pack": "*"//package's name
},
...,
"repositories": [
{
"type": "artifact",
"url": "D:/test_pack"
}
]
}
Method II(My Favorite method, You have to initialize your package directory as git local repository using git init and then git add . and git commit -m "your message")
1) initialize the package directory as git directory and commit all your changes to the local repository
(let's say D:/test_pack is the directory that contains your package(src/ directory and composer.json))
go to D:/test_pack directory and run these commands
git init
git add .
git commit -m "your message for this commit"
2) In your packages composer.json file add minimum-stability
{
"name": "gandalf/test_pack",
"description": "some desc",
"authors": [
{
"name": "gandalf the grey",
"email": "fake#yahoo.com"
}
],
"minimum-stability": "dev",//setting minimum-stability
"require": {
//dependencies that your package needs
},
"autoload": {
"psr-4": {
"Gandalf\\BotPack\\": "src/"
}
}
}
3)In laravel's composer.json file require the "dev-master" of your package
{
...,
"require": {
...,//some dependencies that laravel needs
"gandalf/test_pack": "dev-master"//requiring dev-master from repository
},
"repositories": [
{
"type": "git",
"url": "D:/test_pack"//path of the local repository directory which contains your package
}
]
}
To any Laravel project load local packages. which is stored in your machine.
In laravel's (Project) composer.json file add
"autoload": {
"psr-4": {
"YourPackage\\Namespace\\": "./local_Package_path/src"
}
},
and fire command in Laravel Project directory
composer dump-autoload
Optional
If package is still not available in your Project. then
Register your package's Service Provider.
To register your service provider, you just need to add an entry to the array of service providers in the config/app.php file.
'providers' => [
/*
* Laravel Framework Service Providers...
*/
...
YourPackage\Namespace\PackageServiceProvider::class,
],
Hope now your package loaded successfully in your laravel project.
Is there a way to make Composer run an installer plugin located in ./src/?
The relevant docs are rather unclear as to how it should be done, assuming it's possible to begin with.
If not, the docs also seem to suggest that it's possible to install a plugin in COMPOSER_HOME, but say essentially nothing as to how this can be done — any pointers would be most welcome.
Just to clarify: the problem isn't about autoloading the class as much as it is making composer load the plugin when running composer install or composer update.
My project setup:
./app
…
./src
./src/Hello
./src/Hello/HelloPlugin.php
./vendor
…
The plugin file:
<?php # ./src/Hello/Hello.php
namespace Hello;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
class HelloPlugin implements PluginInterface
{
public function activate(Composer $composer, IOInterface $io);
{
echo "Hello World!".PHP_EOL;
}
} # END class
The relevant lines of the project's composer.json file:
{
"name": "hello/world",
"type": "project",
"autoload": {
"psr-0": {
"Hello\\": "src/"
}
},
"require": {
"composer/installers": "~1.0",
"composer-plugin-api": "~1.0"
},
"extra": {
"class": ["Hello\\HelloPlugin"]
}
}
The composer autoload is used to load all the namespaces of packages you require in you project and it is not intended to load plugins during the composer install or composer update hook.
The only way to load your own plugin class, is to implement your own composer plugin, a normal package of type composer-plugin, which will be used by composer to load your HelloPlugin class. Otherwise, your plugin class will not be loaded during the composer install hook.
I have built a composer-plugin myself, here you can find it https://github.com/mnsami/composer-custom-directory-installer , for references.
And if you have more questions/or help, please don't hesitate to ask.
"autoload": {
"psr-0": {
"Hello\\": "src/"
}
}
https://getcomposer.org/doc/01-basic-usage.md#autoloading
I want to have controllers in my Laravel 4 package, but I can't get the routing to work.
I've followed the package instructions in the Laravel 4 documentation, and got the routes.php file working with non-controller routes.
Could someone please give me some instructions on how to get package controllers to work in Laravel 4, it would be very much appreciated.
Thanks in advance.
Lars
// EDIT:
// routes.php
Route::get('admin', 'Package::AdminController#index'); // Does not work
Route::get('admin', function(){ // Works fine
return 'Dashboard';
})
I don't know the specifics of your situation, nor do I know if this is the "proper" way to fix this issue, but since I came across the same problem I figured I'd share how I solved it.
I put my package controllers in the controllers subdirectory, so that my directory structure looks like this:
/src
/Vendor
/Package
PackageServiceProvider.php
/config
/controllers
/lang
/migrations
/views
/tests
/public
Then, I added the controllers folder to my package's composer.json autoload class map.
{
"name": "kevin-s-perrine/my-first-packge",
"description": "",
"authors": [
{
"name": "Kevin S. Perrine",
"email": "removed#somewhere.com"
}
],
"require": {
"php": ">=5.3.0",
"illuminate/support": "4.0.x"
},
"autoload": {
"classmap": [
"src/migrations",
"src/controllers"
],
"psr-0": {
"KevinSPerrine\\MyFirstPackage": "src/"
}
},
"minimum-stability": "dev"
}
Finally, I ran composer dump-autoload in the package's root directory, and then reference the controller by name in the routes file.
Route::get('myfirstpackage', 'MyFirstPackageHomeController#getIndex');
You'll need to reference the Controller with it's Namespace too
Route::get('/admin', 'PackageNS\Package\Controllers\AdminController#getIndex');
or even
Route::controller('PackageNS\Package\Controllers\AdminController', 'admin');
In your package's service provider, have you included your routes file? I don't believe L4 loads the route file automatically. You can do it anywhere but I suspect this would be the most appropriate place to do it.
public function register()
{
$this->package('vendor/pkgname');
require __DIR__.'/../routes.php';
}
Did you do this:
composer dump-autoload
The autoloader needs to be told about those shiny new classes. I also suggest you check the webserver logs for errors.