Symfony switch from 2.8-3.3 ClassNotFoundException use statement missing namespace? - php

Just recently we decided to upgrade from symfony 2.8 too 3.3 with this being noted I felt it was best to start a fresh symfony project and just pull over some parts of the project and change the key needed items that changed over this major version upgrade. I have worked out most of the issues however currently I get this meaning that I may have more issues that I suspect. here is the current one:
C:\xampp\htdocs\Fresh_Api>php bin/console server:run PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to lo ad class "CommandListener" from namespace "Directive\MultiTenant\MasterBundle\EventListener". Did you forget a "use" statement for another namespace? in C:\xampp\htdocs\Fresh_Api\var\cache\dev\a ppDevDebugProjectContainer.php:580 Stack trace:
#0 C:\xampp\htdocs\Fresh_Api\vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Contai ner.php(331): appDevDebugProjectContainer->getAppBundle_CommandListenerService()
#1 C:\xampp\htdocs\Fresh_Api\var\cache\dev\appDevDebugProjectContainer.php(965): Symfony\Component\D ependencyInjection\Container->get('app_bundle.comm...')
#2 C:\xampp\htdocs\Fresh_Api\vendor\symfony\symfony\src\Symfony\Component\EventDispatcher\EventDispatcher.php(229): appDevDebugProjectContainer->{closure}()
#3 C:\xampp\htdocs\Fresh_Api\vendor\symfony\symfony\src\Symfony\Component\EventDispatcher\EventDispatcher.php(61):Symfony\Component\EventDispatcher\EventDispatcher->sortListeners('console.command')
#4 C:\x in C:\xampp\htdocs\Fresh_Api\var\cache\dev\appDevDebugProjectContainer.php on line 580
This is of course after I try running php bin/console server:run
I have tried deleting my cache, deleting my autoload file, deleting my vendor file and reinstalling composer. I have tried to look to see if there are any dependencies that are missing. (I could have missed something here)
The file it's talking about is a generated file so something about it is not properly noticing that that class exists.
Here is the CommandListener
namespace Directive\MultiTenant\MasterBundle\EventListener;
use Directive\MultiTenant\MasterBundle\Connection\ConnectionWrapper;
use Directive\MultiTenant\MasterBundle\Entity\Tenant;
use Directive\MultiTenant\MasterBundle\Repository\TenantRepository;
use AppBundle\TenantProviderInterface;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Exception;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Input\InputOption;
The appDevDebugProjectContainer is a little large so I'll wait to see if there are any response to see if it's even needed as I'm sure it's something else that is causing it not to generate the proper information needed.
thanks for any input you have.
EDIT: This is a link here noting it's the same issue however this exact issue there is already resolved before all this. Here is my code for that section.
"autoload" : {
"psr-4": {
"AppBundle\\": "src/AppBundle"
},
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
},
This was already fixed already. here is another link I used to try to solve my issue that of course had no help.
php bin/console symfony commands give a fatal error
and another
Symfony 3.3 Getting ClassNotFoundException

All Credit goes to Cerad the answer is sadly duplicated however I did not notice something that was needed. the autoloader needs to know where it is pulling classes from and has to be setup with the new way the symfony does it now. Here is my example with my additional code to make it work.
"autoload" : {
"psr-4": {
"AppBundle\\": "src/AppBundle",
"BundleName\\": "src/BundleName"
},
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
},

Related

Symfony Cron library failed on Doctrine DBAL error

I am using this cron library within my Symfony project. It was working today and after recreating everything from the start (docker, database, vendor folder) and running it again, it crashes.
As it says in documentation I was able to make specific commands and they are persisted in the database.
However when running bin/console cron:start --blocking it throws:
In Manager.php line 60:
Attempted to call an undefined method named "ping" of class
"Doctrine\DBAL\Connection".
And in my log file:
console.ERROR: Error thrown while running command "cron:start --blocking". Message: "Call to undefined method Doctrine\DBAL\Connection::ping()" {"exception":"[object] (Error(code: 0): Call to undefined method Doctrine\\DBAL\\Connection::ping() at /app/vendor/cron/cron-bundle/Cron/Manager.php:60)","command":"cron:start --blocking","message":"Call to undefined method Doctrine\\DBAL\\Connection::ping()"} []
The package you are using is not compatible with doctrine/dbal >= 3.
You can this to your composer.json and reinstall, so that your project uses DBAL 2:
"conflict": {
"doctrine/dbal": "^3.0"
},
Of course, this would depend on you not needing DBAL 3 for anything else.
Although, frankly, I would stop using the Cron/Symfony-Bundle. Seems completely unnecessary. Just add your cronjob tasks directly to your crontab. It's not like the bundle frees you from editing crontab, so you might as well put your tasks there.

Composer autoload doesn't work regardless of whatever I do

I have a project, and I need some packages, so I reorganized the project to use PSR-4.
Here's my composer.json:
{
"name": "me/production",
"type": "project",
"authors": [
{
"name": "Me",
"email": "me#me.com"
}
],
"config": {
"platform": {
"php": "5.6.1"
}
},
"autoload": {
"psr-4": {
"API\\": "api/"
}
},
"require": {
"nesbot/carbon": "^2.25"
},
}
it doesn't work in my scripts. But, here's the real kicker: I do require_once __DIR__ . '/vendor/autoload.php'; in my php console, and it doesn't work either. I have triple and quadruple checked the path, the autoload is there.
What do I mean by "doesn't work"? the autoload requires successfully. It allows me to use libraries. BUT actual instantiations result in a
Class not found error.
Not only for my classes in the API namespace, which are namespaced in the top of the file and are exactly in the folder they're suppose to be, but I also CANNOT instantiate Carbon. I can use Carbon\Carbon but any attempt to instantiate will fail.
Interestingly, instantiation of \Carbon\Carbon directly does not fail.
What's going on? This is weird.
Thank you in advance.
EDIT: I tried redumping the autoloader, I also tried removing the vendor folder and reinstalling. All to no avail.
EDIT: May be worth mentioning I downgraded carbon to ^1.21 because carbon 2 doesnt support php 5.6. But it still doesn't work.
EDIT: It happens with my API namespace as well, here's an example using my implementation of the Instagram API:
use \API\Insta;
php > var_dump(new Insta);
PHP Fatal error: Class 'Insta' not found in php shell code on line 1
php > var_dump(new \API\Insta);
object(API\Insta)#3 (1) {
["ig_token"]=>
string(51) "A_VALID_TOKEN"
}
php >
EDIT: The problem solved itself, it has now mutated into one I care very little about: I can use everything but not in the php console. I am not sure what fixed it.
As you found out, nesbot/carbon, version 2.25 requires at least PHP v7.1.8.
Just having a use statement doesn't check anything, instead it creates a local alias that can be used. If you try to use something that does not exist, only then would it fail.
Please clarify that you have the following directory structure:
./composer.json
./composer.lock
./Api/Insta.php
and in the file Api/Insta.php:
namespace API; // this is your top namespace name
use Carbon/Carbon; // etc
class Insta { ... }
Having the namespace different to the directory name can lead to confusion.
There will also be the index.php/front-controller that pulls in the vendor/autoload.php file and presumably runs the framework.

Composer library can't find dependency

I made my first php library available through packagist. I'm still figuring out how it works, but I keep getting this exception:
Fatal error: Uncaught Error: Class 'Waspeer\NextAction\FabianBeiner\Todoist\TodoistClient' not found in /home/deb58323n2/domains/wannessalome.nl/public_html/assets/todoist/vendor/waspeer/todoist-next-action/src/NextAction.php:120
I listed FabianBeiner\Todoist as a dependency in my composer.json:
"require": {
"php": ">=7.1.0",
"fabian-beiner/todoist-php-api-library": "^0.7.2"
},
"autoload": {
"psr-4": {
"Waspeer\\NextAction\\": "src/"
}
}
And this is in my library file:
namespace Waspeer\NextAction;
use FabianBeiner\Todoist\TodoistClient;
It seems like it's trying to find the dependency in the folder of my library, but I don't know why and how to solve this. Any ideas?
Solved it! When I changed new FabianBein\Todoist\TodoistClient later in the code to just new TodoistClient it worked. Guess I don't really get yet how this use statement/autoloading works..

Laravel 4.1, changing auth.model works, but L4 502s if you remove the models/User.php file

The default Authentication model is app/models/User.php, set by the config item auth.model
That worked fine. So of course I decided to follow a nice guide a make my own namespaced directory to keep all of my models, repos, etc.
I added the line to composer.json to autoload, changed the auth.model setting to the path (model namespace is Models\User), but upon removing the models/user.php file, L4 kicks out a 502 with the (very brief) log entry of
...FatalErrorException' with message 'Class 'User' not found'
in .../Illuminate/Database/Eloquent/Model.php:711
If I add back the models/User.php file, everything works, except it uses the wrong model to log in, so I have to keep a copy in each place.
Am I missing something, some other setting? I can't imagine the path to the User model is hard-coded, but it's sure acting that way.
This is with a fairly fresh Homestead install with Vagrant.
Update #1
Relevant lines from composer.json
"autoload": {
"classmap": [
"app/EC"
Snippet of User class. They're the standard boilerplate User models, except I extend Eloquent with my ECBaseModel class, so the one in app/models extends \Models\ECBaseModel instead
<?php namespace Models;
use \Illuminate\Auth\UserInterface;
use \Illuminate\Auth\Reminders\RemindableInterface;
class User extends ECBaseModel implements UserInterface, RemindableInterface
{
getAuthIdentifier, getAuthPassword, getReminderEmail, getRememberTokens
}
Updated #2
[2014-07-01 20:04:09] homestead.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Class 'User' not found' in /home/vagrant/Code/ec_api/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:711
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleShutdown()
#1 {main} [] []
Some people have suggested dump-autoload but that cannot be the case. PHP knows that it wants to talk to the User class and is failing to find it, but as it does not exist then running dump-autoload is not going to help. It would help only if PHP knew it wanted to talk to Models\User but could not find it, as the autoload lookup was old.
Paste in the entire backtrace. The error will be in there. It will tell us what code is actually calling this old reference. When you see what is trying to call it, you can kill it.
Update: PSR-4 is a little better at handling autoloading when it comes to namespaces.
"autoload": {
"psr-4": {
"App\\": "app/src/"
}
},
Then have app/src/Model/User.php and put it in the App\Model namespace, calling it User.

Using a non-laravel package on Laravel 4

Is it possible to include a package that was not specifically designed for L4 in the framework?
If so, how is it done? I know I need to add the package to my composer.json which adds it to the vendor folder, but can I register it somehow in the providers array? are there any other steps necessary?
I would like to use the Google checkout package originally designed for Yii
Using third party composer packages with Laravel 4
When developers create composer packages, they should map the auto-loading using PSR-0 or PSR-4 standards. If this is not the case there can be issues loading the package in your Laravel application. The PSR-0 standard is:
{
"autoload": {
"psr-0": { "Acme": "src/" }
}
}
And the PSR-4 standard:
{
"autoload": {
"psr-4": { "Acme\\": "src/" }
}
}
Basically the above is a standard for telling composer where to look for name-spaced files. If you are not using your own namespaces you dont have to configure anything else.
SCENARIO 1
PSR-0 standard following packages (with autoload classmap) in Laravel
This is a simple one, and for example i will use the facebook php sdk, that can be found:
https://packagist.org/packages/facebook/php-sdk
Step 1:
Include the package in your composer.json file.
"require": {
"laravel/framework": "4.0.*",
"facebook/php-sdk": "dev-master"
}
Step 2:
run: composer update
Step 3:
Because the facebook package uses a class map its working out of the box, you can start using the package instantly. (The code example below comes straight from a normal view. Please keep your logic out from views in your production app.)
$facebook = new Facebook(array(
'appId' => 'secret',
'secret' => 'secret'
));
var_dump($facebook); // It works!
SCENARIO 2
For this example i will use a wrapper from the instagram php api. Here there need to be made some tweaks to get the package loaded. Lets give it a try!
The package can be found here:
https://packagist.org/packages/fishmarket/instaphp
Step 1:
Add to composer .json
"require": {
"laravel/framework": "4.0.*",
"fishmarket/instaphp": "dev-master"
}
Then you can update normally (composer update)
Next try to use the package like you did with the facebook package. Again, this is just code in a view.
$instagramconfig = array(
'client_id' => 'secret',
'client_secret'=> 'secret',
'access_token' => 'secret'
);
$api = Instaphp::Instance(null, $instagramconfig);
var_dump($api); // Epic fail!
If you try the above example you will get this error:
FatalErrorException: Error: Class 'Instaphp' not found in ...
So we need to fix this issue. To do this we can examine the instagram composer.json, that has its autoload diffrent than the facebook php sdk had.
"autoload": {
"psr-0": { "Instaphp": "." }
}
Compared to the facebook composer.json:
"autoload": {
"classmap": ["src"]
}
(Composer handles different kinds of autoloading, from files and class-maps to PSR. Take a look at your vendor/composer/ folder to see how its done.)
Now we will have to load the class, manually. Its easy, just add this (top of your controller, model or view):
use Instaphp\Instaphp;
composer dump-autoload, and it works!
step2 (optional)
Another method is (if you dont want to use the "use" statement, you can simply tell composer to look for the files straight from your code. Just change the Instance like so:
// reference the name-spaced class straight in the code
$api = Instaphp\Instaphp::Instance(null, $instagramconfig);
var_dump($api); // It works
However I suggest using the usestatement to make it clear to other developers (and your future self) what (external) classes/packages are used in the program.
SCENARIO 3
Here we use the Laravels built in IOC container to register service providers. Please note that some packages might not be suitable for this method. I will use the same Instagram package as in scenario 2.
Quick and dirty
If you don't care about design patterns and service providers you can bind a class like this:
App::bind('Instaphp', function($app)
{
return new Instaphp\Instaphp;
});
And you resolve it like this.
App::make('Instaphp');
Quick and dirty end
If you're working on a bigger project, and you make use of interfaces you should probably abstract the bindings further.
Step 1:
Create a folder inside your app folder, for example a 'providers' folder.
app/providers
Make sure Laravel auto-loads that folder, you can pass in some additional info to composer.json, like this:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php",
"app/providers" // this was added
]
},
Now create a File inside the new folder called Instagram.php and place this inside:
<?php
use Illuminate\Support\ServiceProvider;
class InstagramServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('Instaphp', function()
{
return new Instaphp\Instaphp;
});
}
}
Now run composer dump-autoload again, and you can use the package. Note that the instagram package has a final private function __construct(), this means you cannot use that package outside the original class without changing the construct method to public. I'm not saying this is a good practice, and i suggest to use the scenario 2, in the case of the instagram package.
Anyway, after this you can use the package like this:
$instagramInstance = App::make('Instaphp');
$instagramconfig = array(
'client_id' => 'secret',
'client_secret'=> 'secret',
'access_token' => 'secret'
);
$instagram = new $instagramInstance();
$userfeed = $instagram->Users->feed($instagramconfig);
var_dump($userfeed); // It works!
Add "tvr/googlecheckout": "dev-master" this to your composer.json.
Run composer install, then you can use the IoC container. Some code examples can be found in the official docs for Laravel 4: http://four.laravel.com/docs/ioc#basic-usage

Categories