Problem with PSR-4 Autoloader using composer - php

I have this directories structure:
src
- PrintXMLInfo.php
- PrintListInfo.php
- PrintInformation.php
vendor
main.php
composer.json
Now in composer.json I declared this psr-4 autoload:
"autoload": {
"psr-4": {
"TemplateMethod\\": "src/"
}
}
And in the abstract class PrintInformation I put:
namespace TemplateMethod;
abstract class PrintInformation
And Extended it in PrintXMLInfo and PrintListInfo
namespace TemplateMethod;
use TemplateMethod\PrintInformation;
class PrintXMLInfo extends PrintInformation
The same in PrintListInfo.
The problem is "use TemplateMethod\PrintInformation";
I'm in the same namespace of PrintInformation, but if I write:
use PrintInformation;
i get an error of class not found:
PHP Fatal error: Class 'PrintInformation' not found in /home/vagrant/shared/template_method/src/PrintXMLInfo.php on line 6
I can't get where I'm wrong, if parent and child class are in the same namespace shouldn't I be able to call them without namespace prefix in use, right?

Related

Class Not Found in PHP Laravel 6.x when another class extends

I always get the class not found exception in php laravel 6 when i create a class and extend a parent class named A which is located in the same directory.
However, another child class that is located in same directory could extend class A successfully.
In addition, i couldn't also instantiate the class A due to class not found exception in another .php file.
Please help me on this.
Thanks in an advance.
Parent class: myContext
<?php
namespace config\models;
class myContext {
public static $conn;
...
}
Class myUser: extension is fine.
<?php
namespace config\models;
class myUser extends myContext {
private $name;
...
}
Class oauth: extension returns myContext class not found.
<?php
namespace config\models;
class oauth extends myContext {
private $user;
}
Instantiate the class - returns class not found.
<?php
use config\models\myContext as context;
$cont = new context();
Check whether the namespace is added correctly when the parent class is imported.
Refer
https://www.quora.com/What-is-namespaces-and-use-in-Laravel
external classes and PHP files in Laravel - Class not found
Laravel - Model Class not found
Laravel 6: Class 'Form' not found
To get the provided example codes to work you need to use require_once
<?php
require_once('models/myContext.php');
use app\config\models\myContext as context;
$test = new context();
A search on SO brought me to this source
You try to add this line of code in the composer.json file, then execute the composer dumpautoload command on the command line
In composer.json file,
"autoload": {
"psr-4": {
"App\\": "app/",
"config\\models\\": "config/models"
},
"classmap": [
"database/seeds",
"database/factories"
]
},
After that composer dump-autoload.
have you add autoload for config/ folder in composer.json. Laravel only default autoload for app/

What is autoload in composer.json and how can we use this in laravel?

I am just start working with Laravel, want to create a custom class and want to call this class in every controller. For this, I create a Customer class in app/Library/ folder.
When I tried to autoload this library via composer, json it's giving an error:
Could not scan for classes inside "App/Library/Customer" which does not appear to be a file nor a folder.
How can we use autoload class in controllers?
Customer.php
<?php
namespace App\Library;
use App\Model\User;
class Customer
{
public function login($user_name,$password){
$data = User::where('email', $user_name)
->where('password', $password)
->first();
return $data->id';
}
}
Autoload section of Composer.json
{
"autoload": {
"classmap": [
"database",
"app/Library/Customer"
],
"psr-4": {
"App\\": "app/"
},
"files" : [
"app/Helper/helper.php"
]
}
}
I think you're not understanding what the composer autoload is there for. You use this to include libraries and their dependencies, not really for classes you've created in your app.
What you're better off doing is when you create the controller add in the class you want to use eg:
<?php
use App\Library\Customer;
You will need to put this in every controller.
You should remove it from the classmap group and just add the proper namespace and class. You can see all the psr-4 standards here: http://www.php-fig.org/psr/psr-4/
Lets say you have a folder structure like this:
app
-> Library
-> Customer.php // namespace App\Library; class Customer{}
-> Model
-> User.php // namespace App\Model; class User{}
And all the files should autoload as long as you use the proper namespace and class names.
By the way you should use the Auth facade instead: https://laravel.com/docs/5.4/authentication
There is no need to classmap as already psr-4 autoloading is in place. You've to understand how it works. then you can simply import your classes using use keyword, like this
<?php
use App\Library\Customer;
For more information read PSR-4: Autoloader and take this Tutorial

Class not found, composer and Zend Framework 1 autoloader issue

I have the following class autoload definition in a [root]/composer.json file:
{
...
"autoload": {
"psr-0": {
"": [
"application/models",
"application/controllers",
"application/forms",
"library/"
]
},
"psr-4": {
"": ["src/"]
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
...
}
When I call the [root]/public_html/index.php page I got the following error:
PHP Fatal error: Uncaught Error: Class 'classes\DependencyInjection' not found in /var/www/html/application/bootstrap.php:29
What's in [root]/public_html/index.php is the following code:
$bootstrap = true;
require_once '../application/bootstrap.php';
And what's in [root]/application/bootstrap.php file is:
// turn on autoloading for classes
// composer autoloader
include(MMIPATH.'/vendor/autoload.php');
// zend autoload
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
$diContainer = new classes\DependencyInjection(services.yaml');
$proxy = $diContainer->get('containerProxy');
This is the definition of [root]/library/classes/DependencyInjection.php:
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
USE Symfony\Component\DependencyInjection\Container;
class DependencyInjection extends ContainerBuilder
{
....
}
What's wrong here? Why autoloader can't find that class?
You're attempting to load a "classes" namespace, however your class is not defined as being in the "classes" namespace.
new classes\DependencyInjection(...) in PSR-0 loads {paths}\classes\DependencyInjection.php and attempts to instantiate the class DependencyInjection from the namespace classes, but DependencyInjection is not in the classes namespace. The file will load but the class does not exist.
You could add namespace classes; to each of these classes, but that's not exactly a good solution. Better solution is to use proper namespacing or change your PSR-0 list to include library/classes and use new DependencyInjection(...). (My vote is for the first one -- use proper namespaces.)
As requested. example:
File Location
{app}\library\UsefullNamespace\DependencyInjection.php
Call it using
new UsefullNamespace\DependencyInjection.php
DependencyInjection.php:
namespace UsefullNamespace;
use [...];
class DependencyInjection extends ContainerBuilder
{

Codeception/AspectMock Parent class not found by locator

I have a problem with Codeception/AspectMock.
When using custom autoloader and try to create an instance of a class which has parent form the same custom namespace I have this error:
PHP Fatal error: Uncaught InvalidArgumentException: Class [parent
class name] was not found by locator in
vendor/goaop/parser-reflection/src/ReflectionEngine.php:112
I have very simple setup:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$kernel = AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'includePaths' => [__DIR__. '/lib'],
]);
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
$b = new \lib\B();
Class \lib\B:
namespace lib;
class B extends A {}
Class \lib\A:
namespace lib;
class A
{
public function getName()
{
return static::class;
}
}
Class B is loaded via my custom autoloader, but then the locator tries to load parent class A via composer autoloader and returns this error. Is this a bug, or I'm doing something wrong?
The topic starter has already got an answer on GitHub.
In order to use custom autoloader you should re-init ReflectionEngine with composite class locator that will be able to locate your classes or you can use CallableLocator with closure for resolving paths.
Or, even better you could switch your code base to the PSR0/PSR-4
For example:
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
\Go\ParserReflection\ReflectionEngine::init(
new class implements \Go\ParserReflection\LocatorInterface {
public function locateClass($className) {
return (new ReflectionClass($className))->getFileName();
}
}
);
$b = new \lib\B(); // here you go
If you can easily do a find and replace on your codebase, maybe you could refactor your code to PSR-4 autoloading standards and do away with the need for a custom autoloader altogether.
This is the spec https://www.php-fig.org/psr/psr-4/. I'll try and explain it as simply as possible.
Imagine changing your lowercase namespace lib to Lib, and setting that namespace to the src/ directory in your composer.json:
"autoload": {
"psr-4": {
"Lib\\": "src/"
}
}
After setting that, run composer dumpautoload. Then all you need to do is search and replace namespace lib;, replacing with namespace Lib;.
An example class located in src/Form.php would have namespace Lib; at the top, followed by class Form.
<?php
namepace Lib;
class Form
{
// code
}
Namespaces use the folder naming convention. All classes directly in src/ have namespace Lib;. If there are subdirectories, the directory name becomes part of the namespace. For example a file in src/Form/Field/Text.php would have namespace Lib\Form\Field; class Text {}.
<?php
namepace Lib\Form\Field;
class Text
{
// code
}
You can see the full convention in the link above, but the general rule is make any folders begin with a capital letter, as with your classname, and the autoloader should be able to find all of your classes.
This is probably the best practice solution for you, and again as I said, only requires a little bit of file renaming and namespace tweaking. Good luck!

Class not found issue (Composer, PHPUnit)

Getting the following error form PHPUnit:
Fatal error: Class 'FoobarTest\Money\Money'
not found in /www/foobar/tests/FoobarTest/Money/MoneyTest.php on line 11
My structure is like:
/src/Foobar/Money/Money.php (class Money, namespace Foobar\Money)
/tests/FoobarTest/Money/Money.php (class Money, namespace FoobarTest\Money)
Autoloading done through composer:
"autoload": {
"psr-4": {
"Foobar\\": "src/"
},
"psr-0": {
"FoobarTest\\": "tests/"
}
},
Tried with PSR0, PSR2, PSR4, ...
MoneyTest class:
<?php
namespace FoobarTest\Money;
class MoneyTest extends \PHPUnit_Framework_TestCase
{
// ...
Money class:
<?php
namespace Foobar\Money;
class Money
{
// ...
Why is it trying to load FoobarTest\Money\Money instead of Foobar\Money\Money ?
To help php autoloader (and composer) you must import the target class using
use Foobar\Money\Money;
in your test file.
Also you probably want to give your test file a MoneyTest.php name to match the corresponding class name.

Categories