I have an app I've been working on for a few weeks; I'm using Vagrant+Homestead for local development, and Forge+Linode for a staging environment; until a few days ago, my workflow was working fine, however now when the deployment script runs in Forge (in particular composer install), it gets an error:
[RuntimeException]
Error Output: PHP Fatal error: Class 'Reputationhub\ReputationhubServiceProvider' not found in /home/vagrant/Sites/reputationhu
b/vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php on line 157
PHP Stack trace:
PHP 1. {main}() /home/vagrant/Sites/reputationhub/artisan:0
PHP 2. require_once() /home/vagrant/Sites/reputationhub/artisan:30
PHP 3. require() /home/vagrant/Sites/reputationhub/bootstrap/start.php:60
PHP 4. Illuminate\Foundation\ProviderRepository->load() /home/vagrant/Sites/reputationhub/vendor/laravel/framework/src/Illumin
ate/Foundation/start.php:210
PHP 5. Illuminate\Foundation\ProviderRepository->compileManifest() /home/vagrant/Sites/reputationhub/vendor/laravel/framework/
src/Illuminate/Foundation/ProviderRepository.php:57
PHP 6. Illuminate\Foundation\ProviderRepository->createProvider() /home/vagrant/Sites/reputationhub/vendor/laravel/framework/s
rc/Illuminate/Foundation/ProviderRepository.php:121
It is actually the subcommand php artisan clear-compiled that composer runs afterward that is failing. If I run that on it's own, same problem. Running composer install --no-script runs ok.
When I look at vendor/composer/autoload_classmap.php, it's missing all sorts of things, and is only a few lines long (it's normally much larger), so whatever Laravel is doing is not properly finding the correct classes.
The odd thing is that running composer dump-autoload -o seems to fix it; the autoload_classmap.php file finds everything, and the app runs fine, until php artisan ... tries to do anything, then it breaks the app.
The end result is that the Forge deployment is broken; I can manually jump onto the server and run composer dump-autoload -o to fix it, but that seems wrong.
I think I've been rather thorough about researching solutions, but so far I can't find anything, so any help would be appreciated.
UPDATE: further clarification
This is Laravel 4.2.
My composer.json autoload section looks like this:
...
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"psr-4": {
"Reputationhub\\": "app/"
},
"files": []
},
...
The provider has been added to the "providers" array in app.php like this:
...
'Reputationhub\ReputationhubServiceProvider',
...
And my provider file (at app/Reputationhub/ReputationhubServiceProvider.php) looks like this:
<?php namespace Reputationhub;
use Reputationhub\EventSubscribers\MetricsEventSubscriber;
use Illuminate\Support\ServiceProvider;
class ReputationhubServiceProvider extends ServiceProvider {
...
}
Update 2: more testing
Not sure what it does, but composer install seems to do something bad that breaks the app. To fix it, rather than using composer install in the deployment script (which will subsequently call php artisan clear-compiled and php artisan optimize, both of which will throw errors), if I use this it will repair itself:
...
composer install --no-scripts
composer dump-autoload -o
php artisan dump-autoload
...
Related
Very recently, my application stopped working properly for some reason and I had to change my application namespace, so it is projectname\Model instead of App\Model.
Now after this change, everything started working normally, except php artisan commands.
When I call php artisan, I can have the lists of artisan commands but none works, I always get [RuntimeException] Unable to detect application namespace..
For exemple, I tried running php artisan make:controller ShoppingCartController and I get this error.
I looked online and a lot of people say it's a problem with the composer.json, but I tried composer diagnose and nothing stands out, and I updated composer and also tried composer dump-autoload.
And in my composer.json, I have this part I changed recently:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"projectName\\": "App/"
}
},
And I carefully looked to be sure there was no extra comma in the .json.
I'd like to still be able to use php artisan commands so I'd like to solve this.
Thanks,
When you rename your default namespace, the second parameter should be the name of the 'app' folder. so instead of
"projectName\\": "App/"
You should have
"projectName\\": "app/"
I am developing a library for Laravel which contains a service provider. I have added this library to another project's composer.json file.
The composer.json file for the "main project" contains the following scripts.
"scripts": {
"post-root-package-install": [
"php -r \"copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"php artisan key:generate"
],
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"pre-update-cmd": [
"php artisan clear-compiled"
],
"post-update-cmd": [
"php artisan optimize"
]
},
I can include the library dependency just fine, except for one thing; the pre-update-cmd and post-update-cmd scripts throw an error and cause me a lot of headaches. When running sudo composer update to update the dependencies, I get the following error.
$ sudo composer update
> php artisan clear-compiled
PHP Fatal error: Class 'MyName\MyProject\MyAwesomeServiceProvider' not found in /Users/Me/dev/MyProject/vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php on line 146
[Symfony\Component\Debug\Exception\FatalErrorException]
Class 'MyName\MyProject\MyAwesomeServiceProvider' not found
Script php artisan clear-compiled handling the pre-update-cmd event returned with an error
[RuntimeException]
Error Output: PHP Fatal error: Class 'MyName\MyProject\MyAwesomeServiceProvider'
not found in /Users/Me/dev/MyProject/vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php on line 146
I have Googled around quite a bit before asking this question and read through pretty much everything related that I could find. Apparently this is a known issue that has been discussed in multiple GitHub issues within the Laravel repository. However, I have yet to find a workaround, even after having tried multiple ones.
It appears that the issue is that the Artisan commands bootstrap Laravel, which leads to an error because the service provider is not available at this point - or something like that. Moving the clear-compiled command to post-update-cmd causes the same error, which surprises me a bit because I thought the service provider would be available at this point.
The only thing that works for me is to manually comment out the line that includes the service provider in config/app.php before running composer update and then adding it again afterwards. I have been doing this for a few hours, and it is already bothering the heck out of me, and I really cannot believe that this issue is around.
Does anyone know how to work around this error so that I don't get the error that my service provider is not found when updating the Composer dependencies for my project?
EDIT:
Here is the composer.json file for the library.
{
"name": "my-name/my-project",
"type": "library",
"authors": [
{
"name": "My Name",
"email": "test#example.com"
}
],
"require": {
"php": ">=5.5.0",
"laravel/framework": "~5.2"
},
"autoload": {
"classmap": [],
"psr-4": {
"MyName\\MyProject\\": "src/"
}
}
}
Edit
This issue has finally been resolved as of laravel/framework:v5.2.25 and laravel/laravel:v5.2.27, and backported to laravel/framework:v5.1.33 and laravel/laravel:v5.1.33.
This fix includes a change to the Laravel application (laravel/laravel), in addition to the Laravel Framework (laravel/framework). To implement, you will need to:
1) Update the scripts section of your composer.json file to match that in the laravel/laravel package. Specifically:
remove the pre-update-cmd section
in the post-install-cmd section, replace "php artisan clear-compiled" with "Illuminate\\Foundation\\ComposerScripts::postInstall"
in the post-update-cmd section, replace "php artisan clear-compiled" with "Illuminate\\Foundation\\ComposerScripts::postUpdate"
2) Once you have updated your composer.json, run a composer update. If you only want to update the framework, you can run composer update laravel/framework.
Original
After looking over the Github issue you posted in the comments, as well as the related issues, you may be in for a bit of a wait. Taylor would like to put a script in vendor/bin and change composer.json to run that, but it looks like they are waiting for a PR from the community, and won't actually implement this themselves.
You haven't done anything wrong; your autoloading is setup correctly. The issue is with Laravel right now.
Moving the command to the post-update-cmd script doesn't work because artisan will always try to load the cache files when they exist. When running the clear-compiled command, artisan loads the cache files (part of startup) before it ever tries to delete them.
Your best bet is to manually delete the cache files before artisan gets run. And, you need to do it outside of Laravel/Artisan. So, you can manually delete the files, or you can create a little script to do it and add that to your composer.json file (for your main project, not your package).
Files to delete:
Laravel 5.2:
bootstrap/cache/compiled.php
bootstrap/cache/services.php
Laravel 5.1:
bootstrap/cache/compiled.php
bootstrap/cache/services.json
Laravel 5.0:
vendor/compiled.php
storage/framework/compiled.php
vendor/services.json
storage/framework/services.json
When using composer install or composer update you can use --no-scripts option to skips execution of scripts defined in composer.json.
e. g.: composer update --no-scripts.
Source: https://getcomposer.org/doc/03-cli.md#install
composer update --no-scripts
this command will ignore command defined in composer.json,otherwise it will excute laravel command which will check if serviceProvider is loaded.
It looks like you're simply not including your ServiceProvider. Put this in your root project's composer.json:
{
"autoload": {
"psr-4": {
"App\\": "app/",
"MyName\\MyProject\\": "../relative/path/to/serviceprovider/"
}
}
}
Run This
composer install --ignore-platform-reqs
I have built some migration classes in my application to create the tables I need, but I keep getting errors. I need to run this command:
composer dump-autoload
Only then it works again as expected. Am I doing something wrong that generates this error or this is a normal behaviour with migrations?
Below is the error that I get when running the migration process:
[Symfony\Component\Debug\Exception\FatalErrorException]
Class 'CreateVideoStatusTable' not found
OK so I think i know the issue you're having.
Basically, because Composer can't see the migration files you are creating, you are having to run the dump-autoload command which won't download anything new, but looks for all of the classes it needs to include again. It just regenerates the list of all classes that need to be included in the project (autoload_classmap.php), and this is why your migration is working after you run that command.
How to fix it (possibly)
You need to add some extra information to your composer.json file.
"autoload": {
"classmap": [
"PATH TO YOUR MIGRATIONS FOLDER"
],
}
You need to add the path to your migrations folder to the classmap array. Then run the following three commands...
php artisan clear-compiled
composer dump-autoload
php artisan optimize
This will clear the current compiled files, update the classes it needs and then write them back out so you don't have to do it again.
Ideally, you execute composer dump-autoload -o , for a faster load of your webpages. The only reason it is not default, is because it takes a bit longer to generate (but is only slightly noticable).
Hope you can manage to get this sorted, as its very annoying indeed :(
You should run:
composer dump-autoload
and if does not work you should re-install composer
Short answer: classmaps are static while PSR autoloading is dynamic.
If you don't want to use classmaps, use PSR autoloading instead.
My error was placing a function inside config/fortify.php, in my case it was an anonymous function that gave the error.
The definitive solution for this is to see what files I normally modify in the config/ folder.
In many places they say delete the files from bootstrap/cache/* but it didn't work in my case, and it didn't really make sense. In any case I leave you the commands:
php artisan clear-compiled
composer dump-autoload
php artisan optimize
But I really recommend that you go through the base laravel config files that you have configured. here you will find the error.
I'm currently writing an install script for our platform, and it needs to be able to create a composer.json file, and then run Composer. I've done that and it works fine, for the most part. The issue I'm having is that one of our dependencies runs a task upon installation of every subsequent package (for copying over config yaml files to the main project's directory), using Composer's script option. So for instance, in the generated Composer.json file is a bit that looks like this:
"scripts": {
"post-package-install": [
"Super\\Cool\\Task::postInstall"
],
"pre-package-update": [
"Super\\Cool\\Task::preUpdate"
],
"post-package-update": [
"Super\\Cool\\Task::postUpdate"
]
},
If I delete the vendor folder and then run Composer manually within the directory, the events work fine, but running it from my install script leaves me with an error message of
Class Super\Cool\Task is not autoloadable, can not call post-package-install script.
My only feeling is that perhaps Composer is trying to run its autoloader from the location of within my script, rather than the location of the composer.json file, but that's just a hunch
Does anyone know a way around this? Or is this a bug within Composer?
Just an update, it turns out this was an issue that has already been fixed. Running composer self-update fixed it
This is my composer.json file:
"require": {
"php": ">=5.4",
"zendframework/zendframework": "2.*",
"doctrine/doctrine-module": "dev-master",
"doctrine/doctrine-orm-module": "0.*",
"gedmo/doctrine-extensions": "dev-master"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"scripts": {
"post-update-cmd": [
"rm -rf vendor/Behat",
"git clone git://github.com/Behat/Behat.git",
"cp composer.phar Behat/composer.phar",
"cd Behat && git submodule update --init",
"cd Behat && php composer.phar install",
"cd Behat && php composer.phar require guzzle/guzzle:3.0.*",
"mv Behat vendor/Behat",
"ln -sf ../Behat/bin/behat vendor/bin/"
]
}
How can I make it so the scripts are only run in the dev environment?
Basically I want the scripts to run only when I call:
php composer.phar update --dev
To do the non-development environment update without triggering any scripts, use the --no-scripts command line switch for the update command:
php composer.phar update --no-scripts
^^^^^^^^^^^^
By default, Composer scripts are only executed1 in the base package2. So you could have one package for development and in the live environment make it a dependency of the live system.
Apart from that, I do not see any way to differentiate scripts automatically.
This answer is back from 2012, the additional options in order of appearance can now safely be listed. As the list is composer-only and the original question smells to fall for x/y, the general answer is to use a build manager.
But turns out this could be done already at the day of asking, as in this composer-json example:
{
"scripts": {
"post-update-cmd": "composer::dev-post-update-cmd",
"dev-post-update-cmd": [
"rm -rf vendor/Behat",
": ... ",
"ln -sf ../Behat/bin/behat vendor/bin/"
]
}
}
1.0.0-alpha6 (2012-10-23): dispatch dev-only scripts with PHP script class and __callStatic, e.g. composer::dev-post-update-cmd. if in_array('--dev', $_SERVER['argv']) then $eventDispatcher->dispatchCommandEvent($name).
1.0.0-alpha7 (2013-05-04): --dev is now default and henceforth optional, --no-dev required for not --dev script dispatching. this effectively changes the command-line in question from: composer update --dev running only to: not running on composer update --no-dev. $event->isDevMode() now available, also required for new second parameter on dispatching the script on the event dispatcher. Compare with answer by Christian Koch.
1.0.0-alpha9 (2014-12-07): autoload-dev now allows to not have the script class in --no-dev automatically by removing it from autoload. this works b/c non-existing classes fall-through w/o error.
1.3.0-RC (2016-12-11): --dev is deprecated. COMPOSER_DEV_MODE environment parameter now available in update/install/dumpautoload scripts. no inherit need any longer for the PHP script class, unless enviroment parameters do not work in your setup, then use a PHP class script for a workaround. Compare with answer by Veda.
3 (future): --dev will needlessly make composer fatal, at least this is announced. this closes the circle to pre-1.0.0-alpha7 which also failed on the opposite, --no-dev. the command-line library in use then and yet in the future is not able to cope with -[-not]-args symmetrically, and if the pair is divided and one must go, then it can only throw.
References
See "Note:" in What is a script? - Scripts - Composer Docs
Base package is commonly referred to as root package in the Composer documentation.
Introduction
Some of the answers are a bit brief and don't go into detail about the context in which this is done. I'd like to share some knowledge with whoever is still puzzled after reading the previous answers.
Determine the right option for you
First, take a moment to realise that you're effectively creating a different flow, specific for a certain environment (i.e. your development server/container). This is against any best practices, as it is generally prone to errors. Having said that, you can achieve what you want in several ways;
Not triggering any scripts (docs)
If on some environment you do not want to trigger any scripts, you can prevent this using the --no-scripts flag.
Documentation reads: --no-scripts: Skips execution of scripts defined in composer.json.
composer upgrade --no-scripts
This is especially useful when upgrading packages while your code is currently not working. It would also work if your only scripts are development and test-related.
Running one script separately (docs)
Simply run the specific command as needed:
composer run-script [--dev] [--no-dev] script
This is useful when you want to run a script only on specific occasions.
For example, on build systems that have to perform a certain script before running any tests; build systems offer configuration options to call custom scripts like the above.
Defining a condition in the command (docs)
Documentation reads: During a composer install or update process, a variable named COMPOSER_DEV_MODE will be added to the environment. If the command was run with the --no-dev flag, this variable will be set to 0, otherwise it will be set to 1.
An example could look like
"scripts": {
"post-install-cmd": [
"[ $COMPOSER_DEV_MODE -eq 0 ] || <your command>"
]
}
Personally i would say this is the recommended way if you are using containers.
Note: this does not work on windows, since it would need %COMPOSER_DEV_MODE%.
There are also packages (like scriptsdev by neronmoon) that help you achieve the same goal without having to type the above in all commands, using a dev-scripts section in the extra section in composer.json
Defining a condition in your PHP script (docs)
Call a PHP method, that checks your environment based on how your application already does this. You can even reuse this condition by combining it with the method above; "Defining a condition in the command".
"scripts": {
"post-update-cmd": [
"AppNameSpaceName\\YourClassName::methodName"
]
}
You can then go ahead and create the class, like so:
<?php
namespace AppNameSpaceName;
class YourClassName
{
methodName() {
// do stuff
}
}
In many modern frameworks there is already a mechanism present to determine the runtime environment of the application (Symfony way, Laravel way).
Yarn run (docs)
Since most PHP applications nowadays also transpile their javascript files, either NPM or Yarn would be installed. You can use the scripts section to run this part only on development machines/containers. For example:
yarn run dev-only-script
having a section in package.json
"scripts": {
"dev-only-script": "rm some/folder && ln -s path/to/your/folder some/"
}
The point of this is would be to your composer.json clean. In yarn you could have scripts for dev-server, test and build.
It's not possible to choose different script for default install and the --dev option but you can use the method isDevMode() in Composer\Script\Event to run command only in a development enviroment. http://getcomposer.org/apidoc/master/Composer/Script/Event.html
You can use the COMPOSER_DEV_MODE environment variable (new in version 1.3.0-RC - 2016-12-11):
"scripts": {
"post-install-cmd": [
"[ $COMPOSER_DEV_MODE -eq 0 ] || echo devmode only"
]
},
You can achieve the same effect by setting up a custom script for the dev pathway, instead of using the post-update-cmd hook.
"scripts": {
"update-behat": [
"rm -rf vendor/Behat",
"git clone git://github.com/Behat/Behat.git",
"cp composer.phar Behat/composer.phar",
"cd Behat && git submodule update --init",
"cd Behat && php composer.phar install",
"cd Behat && php composer.phar require guzzle/guzzle:3.0.*",
"mv Behat vendor/Behat",
"ln -sf ../Behat/bin/behat vendor/bin/"
],
"dev-update": [
"#composer update --dev",
"#update-behat"
]
}
Then simply run php composer.phar dev-update
Run the following command.
composer update --no-scripts
Here is the small package, that you may use to do that
https://github.com/neronmoon/scriptsdev
It adds ability to define only-dev scripts.
usage
...
"extra": {
"scripts-dev": {
"post-install-cmd": [
"npm install --dev"
],
"post-update-cmd": "php ./someCoolCommand.php"
},
}
...
You can run either one and check,
composer update --no-scripts
or
composer dump-autoload