Slim3 PSR-4 autoloader - php

I am writing Slim3 API, for some reason slim is not loading namespace defined in composer.
Here is the project structure.
FolderStruc:
projectApi
- composer.json
- src
- public
- index.php
- ProjectName
- Api
- Controllers
- Entities
- Commands
My composer file packages and PSR-4 autoloader settings.
composer.json
{
"require": {
"slim/slim": "^3.0",
"symfony/yaml": "3.1",
"symfony/console": "3.1",
"symfony/process": "3.1",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"sabre/xml": "1.1.0",
"php-di/php-di": "#dev",
"php-amqplib/php-amqplib": "#dev",
"ramsey/uuid": "dev-master",
"monolog/monolog": "~1.15#dev",
"predis/predis": "~1.0.1",
"spipu/html2pdf": "^4.5",
"iio/libmergepdf": "~3.0"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"src\\ProjectName\\": "src/ProjectName/"
}
},
"autoload-dev": {
"psr-4": { "src\\ProjectName\\Tests\\": "tests" }
}
}
index.php
CategoryController
namespace ProjectName\Api\Controllers;
class CategoryController
{
/**
* #param \Slim\App $app
* #return array
*/
public function index(\Slim\App $app)
{
return ['Cats', 'Cats2', 'Cats3'];
}
}
** routes.php **
$app->get('/v1/category/list', function (Request $request, Response $response) {
$response = $response->withHeader('Content-type', 'application/json');
$categoryCtrl = new \ProjectName\Api\Controllers\CategoryController();
});
Slim fails to load namespace \ProjectName\Api\Controllers\CategoryController
any idea where and what is going wrong?
Best Regards
Danyal

You have incorrect autoloader definitions in your composer.json file.
The pattern is:
"psr-4": {
"Namespace\\Prefix\\": "/path/to/source/root"
}
So in your case it probably should be:
"autoload": {
"psr-4": {
"ProjectName\\": "src/ProjectName/"
}
},
"autoload-dev": {
"psr-4": { "ProjectName\\Tests\\": "tests/" }
}
autoload-dev definition is assuming there's a tests directory under project root path, which is not mentioned in your question.

Related

Symfony Unit testing Service with mocks doesn't find the class name

I try to test on a pure unit test my Symfony Service (located in src/AppBundle/Services/CapthaServiceAdapter):
namespace AppBundle\Services;
use AppBundle\Interfaces\CapthaBuilderInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Gregwar\Captcha\CaptchaBuilder;
/**
* The following class is an adapter for Gregwar Captcha Builder
* I do not set Gregwar's Captha Builder as a Service
* Because I want to stay hidden fromt he service container.
*/
class CapthaServiceAdapter implements CapthaBuilderInterface
{
const IMAGE_INLINE=0;
const IMAGE_NORMAL=1;
/**
* #var Session;
*/
private $session=null;
/**
* #var CaptchaBuilder
*/
private $capthaBuilder=null;
public function __construct(Session $sessionManager)
{
$this->session=$sessionManager;
$this->capthaBuilder=new CaptchaBuilder();
}
/**
* #inheritdoc
* #throws \InvalidArgumentException when type is not either self::IMAGE_INLINE or self::IMAGE_NORMAL
*/
public function build($identifier,$type)
{
if($type!==self::IMAGE_INLINE || $type!==IMAGE_NORMAL){
throw new \InvalidArgumentException("Type should be either CapthaService::IMAGE_INLINE or CapthaService::IMAGE_NORMAL you provided the value: ".$type);
}
$this->builder->build();
$this->session->set($sessionKey,$this->builder->getPhrase());
if($type==self::IMAGE_INLINE){
return $this->builder->inline();
}
return $this->builder->output();
}
/**
* #inheritdoc
*/
public function verify($identifier,$value)
{
$capthaSessionValue=$session->get($identifier);
return $capthaSessionValue && $value===$capthaSessionValue;
}
}
So I did the following Test case (located in tests/AppBundle/Services/CapthcaServiceTest.php):
namespace Tests\AppBundle\Services;
use PHPUnit\Framework\TestCase;
use AppBundle\Services\CapthaServiceAdapter;
use Symfony\Component\HttpFoundation\Session\Session;
class CapthcaServiceTest extends TestCase
{
private function getServiceForBuild()
{
$mock=$this->createMock(Session::class);
return new CapthaServiceAdapter($mock);
}
public function testBuildInline()
{
$service=$this->getServiceForBuild();
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
$this->assertRegExp('/^data:image\/jpeg;base64,(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)$/i',$element);
}
}
But when I try to run it I get the following error:
Error: Class 'AppBundle\Services\CapthaServiceAdapter' not found
So how I can make my test to look for my class?
Also my pgpunit.xml contains the following content:
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_CLASS" value="AppKernel" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
<exclude>./tests/Appbundle/Controller/DefaultControllerTest.php</exclude>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
Edit 1
By doing changes mentioned in the comments (updated the code above) I get the error:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
Do you know how I can fix that?
Edit 2:
I also have seen this answer so I post my composer.json as well:
{
"name": "pcmagas/ellakcy_member_app",
"license": "AGPL-v3",
"type": "project",
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
"require": {
"php": ">=5.5.9",
"captcha-com/symfony-captcha-bundle": "4.*",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/orm": "^2.5",
"dunglas/angular-csrf-bundle": "^1.1",
"gregwar/captcha": "^1.1",
"sensio/distribution-bundle": "^5.0.19",
"sensio/framework-extra-bundle": "^5.0.0",
"symfony/dom-crawler": "^4.1",
"symfony/monolog-bundle": "^3.1.0",
"symfony/polyfill-apcu": "^1.0",
"symfony/swiftmailer-bundle": "^2.6.4",
"symfony/symfony": "3.4.*",
"symfony/templating": "^3.4",
"symfony/twig-bundle": "^4.1",
"twig/twig": "^1.0||^2.0"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0",
"felixfbecker/language-server": "^5.4",
"jetbrains/phpstorm-stubs": "dev-master",
"phpunit/phpunit": "^6.5",
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "^4.1"
},
"scripts": {
"symfony-scripts": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
],
"post-install-cmd": [
"#symfony-scripts"
],
"post-update-cmd": [
"#symfony-scripts"
]
},
"config": {
"sort-packages": true
},
"extra": {
"symfony-app-dir": "app",
"symfony-bin-dir": "bin",
"symfony-var-dir": "var",
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"branch-alias": null
}
}
As you can see it has the autoloading class as well:
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
},
"files": [
"vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
]
},
Also By changing into this:
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle",
"AppBundle\\Services":"src/AppBundle/Services",
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
Results into this error:
Error: Class 'Tests\AppBundle\Services\CapthaService' not found
Hos I can make the phphunit to look into the appropriate namespace?
Over your code there is a line that mentions:
$capthaValue=$service->build('somevalue',CapthaService::IMAGE_INLINE);
The class CapthaService where is defined? Did you mean CapthaServiceAdapter (perhaps leftover from a refactor?)
Change into that and that should be fine.

Silex web test fails

I'm trying to write a simple web test to test my silex api using phpunit but
I keep getting this error when i try to run it..
1) App\Tests\BlogControllerTest::testInitialPage
TypeError: Argument 1 passed to Symfony\Component\HttpKernel\Client::__construct() must implement interface Symfony\Component\HttpKernel\HttpKernelInterface, null given, called in C:\vendor\silex\silex\src\Silex\WebTestCase.php on line 63
This is my web test
<?php
namespace App\Tests;
use Silex\WebTestCase;
class BlogControllerTest extends WebTestCase
{
public function createApplication()
{
require dirname(dirname(__DIR__)) . '/src/Application.php';
}
public function testInitialPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/Blog/1');
$this->assertTrue($client->getResponse()->isOk());
}
}
The content of my Composer file:
{
"require": {
"silex/silex": "~2.0",
"symfony/validator": "^4.0",
"crell/api-problem": "~1.7",
"tobiassjosten/responsible-service-provider": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "6",
"symfony/browser-kit": "^4.0",
"symfony/css-selector": "^4.0"
},
"autoload": {
"psr-4": {
"App\\": "src/",
"Tests\\": "tests/"
}
}
}
From documentation:
For your WebTestCase, you will have to implement a createApplication method, which returns your application instance:
public function createApplication()
{
// app.php must return an Application instance
return require __DIR__.'/path/to/app.php';
}
So here's what you need:
public function createApplication()
{
return new Application();
}
But in the most cases it would be better to return configured application, from your bootstrap (bootstrap example):
public function createApplication()
{
require __DIR__.'../web/index-test.php'; // path to your bootstrap file
return $app;
}

How to autoload from root namespace?

Trying the following config to load my models from root namespace failed. any alternative?
"autoload": {
"psr-4": {
"\\": "app/Models"
}
},
The following works but I have to run dumpautoload each time I create a new class.
"classmap": [
"app/Models"
],
Any suggestion?
Instead of "\\", you should map "" to "app/Models". Quoting from composer docs:
If you want to have a fallback directory where any namespace will be
looked for, you can use an empty prefix like:
{
"autoload": {
"psr-4": { "": "src/" }
}
}
So, in your case:
{
"autoload": {
"psr-4": {
"": "app/Models"
}
}
}

How to use DB of Laravel illuminate's Database in Slim Framework

I am using slim framework version 3. I have used Laravel's illuminate database. In my controller when I write below query it gives me error that "Class DB not Found" I have also specified use DB; in my controller inspite of that it does not allow me to write such mysql query.
$students = DB::table('students')->row();
This is my composer.json file content
"require": {
"slim/slim": "^3.0",
"slim/twig-view": "^1.0",
"vlucas/valitron": "^1.2",
"slim/csrf": "^0.3.3",
"slim/flash": "^0.1.0",
"illuminate/database": "5.2.*",
"illuminate/events": "5.2.*",
"illuminate/cache": "5.2.*",
"illuminate/filesystem": "5.2.*",
"luracast/config": "2.*",
"vlucas/phpdotenv": "~1.0",
"league/flysystem": "~1.0",
"illuminate/pagination": "5.2.*"
},
I have all necessary files in my vendor directory. But I want to use DB in my controller
Here is my controller code:-
<?php
namespace Controller;
use Slim\Views\Twig;
use Slim\Router;
use Slim\Flash\Messages as FlashMessages;
use Model\Student;
use DB;
final class StudentController
{
private $view;
private $router;
private $flash;
public function __construct(Twig $view, Router $router, FlashMessages $flash)
{
$this->view = $view;
$this->router = $router;
$this->flash = $flash;
}
public function listStudents($request, $response, $params)
{
$students = DB::table('students')->get();
return $this->view->render($response, 'students/list.twig', [
'students' => Student::all(),
]);
}
}
You have to correct used namespace:
use \DB;
or
use Illuminate\Support\Facades\DB;
instead of use DB
Also you might take a look at tutorial for using database illuminate without Laravel

Composer - unable to autoload files

I have a simple composer project on GitHub with the directory structure as:
/--
-composer.json
-lib/ComposerTest.php
with the ComposerTest.php file as:
namespace lib;
class ComposerTest{
public function doTest(){
return "This class was loaded from Composer\n";
}
}
and composer.json as:
{
"name":"sc/composerTest",
"autoload":{
"psr-0":{
"lib":"./"
}
}
}
Using the following composer.json file, I'm able to include the GitHub project into my vendor folder, but cannot get it to autoload.
{
"description" : "The CodeIgniter Application with Composer",
"require": {
"php": ">=5.3.2",
"codeigniter/framework": "3.1.*",
"kriswallsmith/buzz":"*",
"maltyxx/bower": "^1.0",
"sc/composerTest":"dev-master"
},
"require-dev": {
"mikey179/vfsStream": "1.1.*"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/sc/composerTest.git"
}
]
}
Can someone advise?
Edit: ComposerTest Controller
class ComposerTest extends CI_Controller
{
public function index()
{
$composerTest = new ComposerTest();
echo $composerTest->doTest();
}
}

Categories