Autoloading with PSR4 naming in php - php

I have following library structure
C:\WWW\WEBS
| users.php
|
\---lib
| Api.php
| Server.php
| TimeSync.php
|
\---TimeSync
Ntp.php
Protocol.php
Sntp.php
In server.php I have
<?php
namespace lib;
class Server extends Api
{
}
?>
In users.php I am using it as
<?php
use lib\Server;
$objServer = new Server();
?>
I also tried it using like use lib\Server;
But in both cases it is saying
Fatal error: Class 'lib\Server' not found in
C:\www\Experimentation\webserviceserver\users.php on line 7
Where I am going wrong .Should I user a autoloader?

You will need to use an autoloader.
You can use the one delivered in Composer.
Once you've installed it (at the root of your project), you put a composer.json file, and inside you copy the following code :
{
"autoload":{
"psr-4":{
"Lib\\" : "lib/"
}
}
}
Then you use the command composer dumpautoload. That will copy the autoloading files in a folder named "vendor" at the root of your project.
Then in users.php you require the autoloader :
require_once "vendor/autoload.php"
And you use the namespacing :
use Lib;
$objServer = new Lib\Server();
It might work.

Related

How to deal with Class not found with composer

I installed composer and laravel and installed some packages
all work fine, but now I created my own class under the folder services
I gave it name space of Services like that:
namespace Services;
And the class name is UploadToImgurService
I run the composer command:
composer dump-autoload
And in my controller I wrote:
use Services\UploadToImgurService;
But I get this error:
Class 'Services\UploadToImgurService' not found
What did I did wrong?
Is there anything else that I should do with composer for autoloading the service class?
EDIT
I found a solution
I edited y composer.json file and added to psr-4 the line
"Services\\" : "app/services"
But why It didn't workt before? The line :
"App\\": "app/",
was there, maybe it loaded the class but under the app namespace?
If you are using a case sensitive file system, you will need to have the Services folder with upper case S.
Your idea is right, but let me try to explain how the psr-4 autoloading works.
You can define root namespaces in your composer.json file and map it to any project directory. Inside the defined directories, your classes should get the root namespace. The namespace segments after the root are build by your sub directory structure and the class name is equal to the file name (PSR-4 Autoloading).
E.g
"MyNamespace\\WithSubNamespace\\": "cool/project"
cool/project/MyClass.php -> MyNamespace\WithSubNamespace\MyClass
cool/project/SubDirectory/AnotherClass.php -> MyNamespace\WithSubNamespace\SubDirectory\AnotherClass
In Laravel, the app directory is mapped to the App namespace as default. Optionally, you can change the root namespace with the command php artisan app:name [NewRootNamespaceName], but the autoloader only finds classes inside the app directory.
If you create a new directory outside of "app", you have to add the directory to your psr-4 namespace mapping in the composer.json file.
In your example, you define a new root namespace in the existing app directory, so your issue was that the root namespace was unknown and you solved it by adding the line in your composer.json.
This is possible, because psr-4 provides a huge flexibility. But personally, i would not recommend to use different root namespaces in the same project.
I hope i could help and maybe this is also interesting for you: composer.json PSR-4.
maybe you forgot to add this line of code
require_once('vendor/autoload.php');
Once I was getting the error:
Fatal error: Uncaught Error: Class "..." not found
in /var/www/html/... on line ...
I was requiring autoload file this way:
require 'vendor/autoload.php';
After I changed the line to:
require __DIR__.'/vendor/autoload.php';
it started working...
Weird, since the the vendor folder was in the same directory as the file which was calling it.
BTW, I was using Composer 2 and PHP 8.1.

Autoloader unable to load the dependency

I see that my dependency use
"autoload": {
"psr-4": {"Ion\\": "src/"}
}
And at the src/container folder
<?php
namespace Ion;
class Container
And, I try to load it using the autoloader (of course I've composer require that library)
<?php
require 'vendor/autoload.php';
use Ion\Container;
$ion = new Container();
But, it turns out to be a fatal error
Fatal error: Uncaught Error: Class 'Ion\Container' not found in C:\UniServerZ\www\projects\playground\ion\test.php on line 6
What's wrong with this? Anyway to fix it?
Please help
This is the package (which I code) : https://packagist.org/packages/terrydjony/ion
I have downloaded your package and troubleshoot the issue. Actually, you need to place your file in a folder called Ion. It should be src/Ion/Container.php instead of ion/src/Container.php.
+-- src
| +-- Ion
| +-- Container.php
+-- vendor
+-- composer.json
Another small mistake you made, your class filename is in lowercase container.php but you defined it in uppercase.
class Container
{
}

phpspec creates files in wrong folders per psr-4 namespace specification

I scrapped the earlier form of my question because it was too convoluted. Here's the new version.
I want to use phpspec with my psr-4 formatted projects.
Here's the way I tried to set up a test project:
Created a new folder for the project:
cd ~/Desktop/
mkdir TestPhpSpec
cd TestPhpSpec
create a new composer.json file and require phpspec:
composer require phpspec/phpspec
Which creates my composer.json file:
{
"require": {
"phpspec/phpspec": "^2.3"
}
}
I add my psr-4 namespace to the autoload property of my composer.json file:
{
"require": {
"phpspec/phpspec": "^2.3"
},
"autoload": {
"psr-4": {
"Acme\\": "src/Acme"
}
}
}
Then I dump my autoload to make sure my namespace is loaded: composer dumpautoload
After that, I create my phpspec.yml to describe the namespace to phpspec:
suites:
acme_suite:
namespace: Acme
psr4_prefix: Acme
Then I describe the class I want to start building:
phpspec describe Acme/Markdown
This is where I run into the first problem. Even though I specify the Acme namespace in my describe command, the spec does not get placed in a folder matching the namespace:
Though the class it creates is namespaced correctly:
<?php
namespace spec\Acme; // correct namespace
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class MarkdownSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Acme\Markdown');
}
}
Then if I try to run the test to start TDD-ing.
phpspec run
It offers to create the class for me and I let it. From there I get the second problem; I get the error message:
[PhpSpec\Process\Prerequisites\PrerequisiteFailedException]
The type Acme\Markdown was generated but could not be loaded. Do you need to configure an autoloader?
And the class it creates is not in it's namespaced folder:
The class it creates is also namespaced correctly:
<?php
namespace Acme; // correct namespace
class Markdown
{
}
I've looked over the docs and can't figure out what I'm doing wrong. Any suggestions?
Try with
suites:
acme_suite:
src_path: Acme/src
spec_path: Acme/spec

Composer autoload won't work after deployment

I am relatively new to using composer and autoload to organize my code. I have a git repository and on my local machine, I set up composer in the root dir of my project. I specified everything in a composer.json needed to get running. Using "composer install", all libraries are automatically installed.
{
"name": "my/repo",
"description": "bla",
"version": "1.2.3",
"require":
{
"php": "5.6.*",
"geraintluff/jsv4": "1.*",
"lcobucci/jwt": "^3.0"
},
"autoload":
{
"psr-4":
{
"MyNamespace\\": "src/"
}
}
}
So - once I ran "composer install" on my local machine, everything was autoloaded in my code. Fine.
But now I need to deploy the whole thing on another linux system. So i pull from the git and run composer install. All the libraries are fetched and the autoload file shows up in vendor/
Yet, I cannot use autoload (yes, I did require_once(__DIR__ . '/../vendor/autoload.php');). Everytime I try to instantiaze a class, i get a
PHP Fatal error: Class 'X' not found in /var/www/bla/x.class.php on line 123
Using use X; does not solve the problem, nor does trying to instantiate the class with its full Namespace name (e.g. $x = new \A\B\X();)
Here is the folder structure (if this matters):
+ src/
| + X.class.php // namespace here is "MyNamespace"
| + Y.class.php // same namespace
+ test/
+ run.php // namespace is "Test"
Here is a snippet of this code (run.php):
<?php namespace Test; // different namespace than the rest of the code
// making the namespace also "\MyNamespace" wouldnt work either
require_once(__DIR__ . '/../vendor/autoload.php');
use \MyNamespace\Y; // whether this line is here or not does not change the error
session_start();
// same error as with "just" implements Y {}
class SomeClass implements \MyNamespace\Y {
// ...
}
?>
So here, the Fatal error is thrown for the line where Y is extended. No matter if I use the full namespace or not. Only thing that will help is a require_once()...
So, this forces me to go back to the cumbersome way of doing all the require/includes myself!? Is there any way to solve this?
PS: composer dumpautoload wont help
PPS: composer validate shows no errors
For PSR-4 compliance, your file structure should be:
+ src/
| + X.php
| + Y.php
Note the removal of the .class.php suffix. http://www.php-fig.org/psr/psr-4/

Composer and PSR-0 class autoloading with namespaces

Hello guys i have problem with autoloading my class with composer. On Linux all work perfect, but now my boss change env and set Windows. All this work on linux but windows show newbie fatal error:
Fatal error: Class 'AbstractController' not found in
D:\xampp\htdocs\ikacFw\frontController.php on line 7
Common to see my composer.json and stucture for better picture on problem.
Stucture is :
frontController.php
-- vendor
----- Doctrine
----- Ikac
--------- Components
---------- Mvc
------------- Controller
Am trying to load all data from vendor directory.
Composer.json
{
"autoload": {
"psr-0": {
"vendor": ""
}
}
}
Also new component i add manual. Like this :
$loader = require_once 'vendor/autoload.php';
$loader->add('vendor', "Ikac");
Okay next when i try to call :
<?php
require_once 'vendor/autoload.php';
use Ikac\Mvc\Controller;
$a = new AbstractController();
I get error "not found".
My class AbstractController contain defined namespace but dont work again. Like test i do this:
<?php
//vendor/Ikac/Mvc/Controller/AbstractController.php
namespace Ikac\Mvc\Controller;
class AbstractController {
function __construct() {
echo __CLASS__;
}
}
?>
I do from cmd composer dump-autoload, install, but dont work. All this perfect work on linux but here wont. Any idea how to fix this or where i do mistake.
Thanks guys!
SLOVED:
{
"autoload": {
"psr-0": {
"": "vendor/"
}
}
}
Well you should do
<?php
require_once 'vendor/autoload.php';
use Ikac\Mvc\Controller\AbstractController;
$a = new AbstractController();
Your autoloading declaration is wrong.
You will NEVER ever need to include the vendor folder in any autoloading. The vendor folder will contain the autoloading for both all dependencies, and - if configured - for your own classes as well.
You can use Composer to create autoloading for your own classes. Just include the correct info. But from your current info I cannot deduct what would be correct.

Categories