Composer autoloader seems to be not included correctly - php

I'm trying to implement simple library without web server. That means I actually don't have any entry point where I can include autoload.php.
I trying to add bunch of classes, but PhpStorm cannot recognise namespacing and and my classes cannot being auto-imported.
E.g.
I'm trying to import file App/Engines/Contracts/BaseEngine.php which is placed in src/Engines/Contracts/BaseEngine.php via
use App\Engines\Contracts\BaseEngine;
The PhpStorm says Undefined Class
All PhpStorm configuration seems to be correct: I've specified composer.json and checked auto-import in namespace scope.
So, basically the question is: How to deal with composer autoloader in such a library?
Attaching my composer.json code.
{
"name": "mom/task",
"description": "Todo",
"authors": [
{
"name": "Foo Bar",
"email": "foo.mail.com"
}
],
"require": {
"php": "^7.4"
},
"require-dev": {
"phpunit/phpunit": "^8",
"squizlabs/php_codesniffer": "3.*"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}
UPD: attaching BaseEngine code.
<?php
namespace App\Engines\Contracts;
interface BaseEngine
{
/**
* #param int $variable
* #param int $multiplier
* #return mixed
*/
public function compute(int $variable, int $multiplier): int;
}

Related

Laravel 8 package development - Route Target class does not exist

I know the title topic sounds similar to other questions, but I've searched many topics on stackoverflow and none resolve my issue.
I am currently developing a package under Laravel ^8.12, below the content of the function that register my routes:
protected function registerRoutes(): void
{
Route::prefix('workflowmakr')
->namespace('AlvariumDigital\WorkflowMakr\Http\Controllers')
->as('workflowmakr.')
->middleware(config('workflowmakr.routes_middleware'))
->group(__DIR__ . '/../routes/api.php');
}
And below is the content of the routes/api.php file:
<?php
use Illuminate\Support\Facades\Route;
Route::resource('actions', 'ActionController')->except(['created', 'edit']);
Route::resource('scenarios', 'ScenarioController')->except(['created', 'edit']);
Route::resource('statuses', 'StatusController')->except(['created', 'edit']);
Route::resource('transitions', 'TransitionController')->except(['created', 'edit']);
For a better view of the project architecture, below is a screenshot of the packages folder containing the package under development:
And finally, below is the composer.json declaring my package:
...
"extra": {
"laravel": {
"providers": [
"AlvariumDigital\\WorkflowMakr\\WorkflowMakrServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"AlvariumDigital\\WorkflowMakr\\": "packages/AlvariumDigital/WorkflowMakr/src/"
}
},
...
When I execute the command php artisan route:list to view all my routes I got this error :
$> php artisan route:list
Illuminate\Contracts\Container\BindingResolutionException
Target class [AlvariumDigital\WorkflowMakr\Http\Controllers\ActionController] does not exist.
at D:\Films\R_D\Laravel packages\workflow-makr\vendor\laravel\framework\src\Illuminate\Container\Container.php:832
828▕
829▕ try {
830▕ $reflector = new ReflectionClass($concrete);
831▕ } catch (ReflectionException $e) {
➜ 832▕ throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e);
833▕ }
834▕
835▕ // If the type is not instantiable, the developer is attempting to resolve
836▕ // an abstract type such as an Interface or Abstract Class and there is
1 [internal]:0
Illuminate\Foundation\Console\RouteListCommand::Illuminate\Foundation\Console\{closure}(Object(Illuminate\Routing\Route))
2 D:\Films\R_D\Laravel packages\workflow-makr\vendor\laravel\framework\src\Illuminate\Container\Container.php:830
ReflectionException::("Class AlvariumDigital\WorkflowMakr\Http\Controllers\ActionController does not exist")
EDIT
Below is the content of the ActionController file:
<?php
namespace AlvariumDigital\WorkflowMakr\Http\Controllers;
use AlvariumDigital\Models\Action;
use AlvariumDigital\WorkflowMakr\Helpers\Constants;
use Illuminate\Routing\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class ActionController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\JsonResponse
*/
public function index()
{
$query = Action::query();
if (config('workflowmakr.pagination_size') == -1) {
return response()->json($query->get(), 200);
}
return response()->json($query->paginate(config('workflowmakr.pagination_size')), 200);
}
// ...
}
EDIT 2
The content of the package composer.json file:
{
"name": "AlvariumDigital/WorkflowMakr",
"description": "Generalize the management of your workflows",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Alvarium Digital",
"email": "contact#alvariumdigital.com",
"homepage": "http://www.alvariumdigital.com",
"role": "Corporate"
},
{
"name": "EL OUFIR Hatim",
"email": "heloufir#alvariumdigital.com",
"homepage": "https://www.linkedin.com/in/eloufirhatim/",
"role": "Developer"
}
],
"support": {
"email": "heloufir#alvariumdigital.com"
},
"minimum-stability": "dev",
"require": {}
}
Did I do something wrong or incomplete?
You can ask for more details if needed.
Thanks
You have structured this directory incorrectly. You have the PSR4 autoloading loading the src directory as the namespace. Your controllers are not in the src folder, only the Service Provider is in there. So to composer there are no files for it to find and autoload based on your PSR4 autoloading.

package:discovery does not find my ServiceProvider

I have created a custom Laravel package. Its hosted on a private repository.
When I try to install the package in a Laravel application like this:
composer require memberportal/congress-models
I get this error:
In ProviderRepository.php line 208:
Class 'Memberportal\CongressesModels\CMServiceProvider' not found
Script #php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 1
Installation failed, reverting ./composer.json to its original content.
I have double checked everything a hundred times, but I am clueless why he doesn't find the class CMServiceProvider.php.
Do I need to specify the provider anywhere else then in the composer.json?
This is the content of composer.json from my package:
{
"name": "memberportal/congress-models",
"description": "Takes care of the models between API and client",
"type": "metapackage",
"authors": [
{
"name": "My name",
"email": "my#email.com"
}
],
"version" : "1.0",
"minimum-stability": "stable",
"require": {
"laracasts/presenter": "^0.2.2"
},
"require-dev": {
"orchestra/testbench": "^4.0"
},
"autoload": {
"psr-4": {
"Memberportal\\CongressesModels\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Memberportal\\CongressesModels\\Tests\\": "tests"
}
},
"extra": {
"laravel": {
"providers": [
"Memberportal\\CongressesModels\\CMServiceProvider"
]
}
}
}
This is the folder structure:
This is the content of CMServiceProvider.php:
<?php
namespace Memberportal\CongressesModels;
use Illuminate\Support\ServiceProvider;
class CMServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
}
}
Since you want to install a Laravel package your package type should be package. A metapackage is a package that does not contain actual software, it simply depends on other packages to be installed.
In short, change
"type": "metapackage",
to
"type": "package",
and Laravel will find the service provider with auto-discovery when the package is required by composer.

PSR4 not working

I have setup a folder structure like this for a package of legacy classes
vendorname/legacy/src/ClassA.php
namespace Vendorname\Legacy;
class ClassA{}
vendorname/legacy/src/Folder/Class2.php
namespace Vendorname\Legacy\Folder;
class FolderClass2{}
With composer I'm loading this from a github repo like this:
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:username/vendorname-legacy-classes.git"
}
],
"require": {
"vendorname/legacy": "master#dev"
}
When I load ClassA like this it works:
use Vendorname\Legacy\ClassA;
$a = new ClassA();
However none of my subfolder'd classes work:
use Vendorname\Legacy\Folder\FolderClassB;
$b = new FolderClassB();
Class 'Vendorname\\Legacy\\Folder\\FolderClassB' not found
I have already defined the source folder with a file vendor\vendorname\composer.json
{
"name": "vendorname/legacy",
"description": "Vendorname Legacy classes",
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-4": {
"Vendorname\\Legacy\\": "src"
}
},
"extra": {
"branch-alias": {
"master": "master"
}
}
}
you need to define one thing more to your composer.json
{
"autoload": {
"psr-4": {"Vendorname\\Legacy\\": "vendorname/legacy/src/"}
}
}

Composer autoloading with PSR4

Probably something trivial but I have a problem with basic autoloading. I wanna create sandbox project just for testing new solutions so I've created following structure:
Sandbox
|- index.php
|- composer.json
|- vendor
| |- {autogenerated content}
|- src
|- Working.php
File composer.json looks like this:
{
"name": "vendor/sandbox",
"authors": [
{
"name": "foo",
"email": "bar#example.com"
}
],
"require": {
"phpunit/phpunit": "dev-master",
"phpunit/phpunit-mock-objects": "dev-master"
},
"psr-4": {
"Sandbox\\": "src/"
}
}
Of course I've run composer.update after changes. Then I wrote a trivial body of Working.php:
<?php
namespace Sandbox;
class Working
{
public function __construct() {
echo "Hello World";
}
}
And of course index.php as well:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Sandbox\Working;
new Working();
?>
I checked permissions to those files just to be sure but when I try to run I get
PHP Fatal error: Class 'Sandbox\Working' not found in /var/www/Sandbox/index.php on line 6
I realize it's probably something trivial but what can be wrong here?
At your composer.json you are missing autoload key.
It should be like
"autoload": {
"psr-4": {
"Sandbox\\": "src/"
}
}
I believe
"psr-4": {
"Sandbox\\": "src/"
}
Should be:
"autoload": {
"psr-4": {
"Sandbox\\": "src/"
}
So your file would be:
{
"name": "vendor/sandbox",
"authors": [
{
"name": "foo",
"email": "bar#example.com"
}
],
"require": {
"phpunit/phpunit": "dev-master",
"phpunit/phpunit-mock-objects": "dev-master"
},
"autoload": {
"psr-4": {
"Sandbox\\": "src/"
}
}

How to use my Package in Laravel5

I have a question related to Package for Laravel 5. I am creating one package and tried to use that. package successfully created and using composer i can also get that in New Laravel setup , issue is that when i tried to use that it's says class not found. Here's my composer.json and Steps that i followed:
for e.g. my username = git_test and packagename = mypackage
My Package Structure :
**git_test > mypackage > src
My composer.json file
{
"name": "git_test/mypackage",
"description": "XXXXXXXXXX",
"keywords": ["laravel"],
"license": "MIT",
"authors": [
{
"name": "XXXXXXX",
"email": "XXXXXX#gmail.com"
}
],
"require": {
"php": ">=5.4.0",
"illuminate/support": "5.0.*"
},
"autoload": {
"psr-4": {
"git_test\\mypackage\\": "src/"
}
},
"minimum-stability": "dev"
}
Here's my src/myclass.php
namespace git_test\mypackage;
class myclass {
function test(){ echo "This is Test"; }
}
Now i am going to use this in my new laravel project so i add package in my directory composer and try to use the myclass in my HomeController
HomeController Code
use git_test\mypackage\myclass as TaskClass;
class HomeController extends Controller {
public function index()
{
$atTaskObj = new TaskClass('');
}
I got the error like "git_test\mypackage\myclass" Not Found. where i am doing wrong? any suggestion please.
Thanks in Advance!!!
PSR-4 paths have to end with \\:
"autoload": {
"psr-4": {
"git_test\\mypackage\\": "src/"
}
},

Categories