I just started using Slim Framework to create my rest API. Everything works well until I try to route HTTP request to a static class method (I used the anonymous function before). Below is my new route code on index.php:
include "vendor/autoload.php";
$config = ['settings' => [
'addContentLengthHeader' => false,
'displayErrorDetails' => true,
'determineRouteBeforeAppMiddleware' => true
]
];
$app = new \Slim\App($config);
$app->get('/user/test', '\App\Controllers\UserController:test');
$app->run();
And below is my UserController class on UserController.php
class UserController{
public function test($request, $response, $args){
$array = ['message'=>'your route works well'];
return $response->withStatus(STAT_SUCCESS)
->withJson($array);
}
}
Error details:
Type : RuntimeException
Message: Callable \Controllers\UserController does not exist
File : /var/www/html/project_api/vendor/slim/slim/Slim/CallableResolver.php
Below is my project folder tree
project_api/
index.php
vendor/
slim/slim/Slim/CallableResolver.php
Controllers/
UserController.php
my composer.json
{
"require": {
"slim/slim": "^3.8",
"sergeytsalkov/meekrodb": "*",
"slim/http-cache": "^0.3.0"
}
},
"autoload": {
"psr-4": {
"Controllers\\": "Controllers/"
}
}
It seems that your namespace is define improperly. In your composer.json, class UserController under the namespace Controllers.
you should define a namespace at the top of your UserController.php:
namespace Controllers;
and change $app->get() in your index.php to:
$app->get('/user/test', 'Controllers\UserController:test');
Related
I am trying to get my slim application to work, but I get this error:
( ! ) Fatal error: Uncaught RuntimeException: Callable Quiz\Controller\QuizController::index() does not exist in /var/www/html/vendor/slim/slim/Slim/CallableResolver.php on line 138
( ! ) RuntimeException: Callable Quiz\Controller\QuizController::index() does not exist in /var/www/html/vendor/slim/slim/Slim/CallableResolver.php on line 138
I'm using PHP 8.1 and Slim 4.11
Project structure:
My autoload config:
"autoload": {
"psr-4": {"Quiz\\": "source/"}
}
Method which should be called:
<?php
declare(strict_types=1);
namespace Quiz\Trivia\Controller;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Http\Response;
final class QuizController
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function index(ServerRequestInterface $request, Response $response, array $args): ResponseInterface
{
return $this->container->get('views')->render(
$response,
'index.twig'
);
}
}
I define the route in routes.php as follows:
<?php
declare(strict_types=1);
use Quiz\Trivia\Controller\QuizController;
return [
'index' => [
'type' => 'get',
'path' => '/',
'class' => QuizController::class . ':index'
]
];
Later, I add the route in index.php with $app->map(...) to the slim app.
I already tried some solutions from older posts, but nothing worked so far. So I think I'm missing something crucial.
Thanks in Advance!
This is because your autoload config is set to "Quiz\": "source/ so it expects to find all classes belonging to the Quiz namespace in that folder, when in fact the controller you're trying to use is not located there.
You should move the trivia folder inside your source directory (with a capital T to respect conventions) or update the map to include the trivia namespacing and it's directory.
"Quiz\": "source/
"Quiz\\Trivia\": "trivia/"
(the double-backslash \\ is intentional.)
I'm trying to switch from the pimple container that comes bundled with Slim, to PHP-DI and I'm having an issue with getting the autowiring to work. As I'm restricted to using PHP 5.6, I'm using Slim 3.9.0 and PHP-DI 5.2.0 along with php-di/slim-bridge 1.1.
My project structure follows along the lines of:
api
- src
| - Controller
| | - TestController.php
| - Service
| - Model
| - ...
- vendor
- composer.json
In api/composer.json I have the following, and ran composer dumpautoload:
{
"require": {
"slim/slim": "3.*",
"php-di/slim-bridge": "^1.1"
},
"autoload": {
"psr-4": {
"MyAPI\\": "src/"
}
}
}
My api/src/Controller/TestController.php file contains a single class:
<?php
namespace MyAPI\Controller;
class TestController
{
public function __construct()
{
}
public function test($request,$response)
{
return $response->write("Controller is working");
}
}
I initially tried to use a minimal setup to get the autowiring working, just using the default configuration. index.php
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '/../../api/vendor/autoload.php';
$app = new \DI\Bridge\Slim\App;
$app->get('/', TestController::class, ':test');
$app->run();
However, this returned the error:
Type: Invoker\Exception\NotCallableException
Message: 'TestController'is neither a callable nor a valid container entry
The only two ways I could get it to work, is to place the TestController class in index.php directly (which makes me think PHP-DI isn't playing well with the autoloader) or to use the following extension of \DI\Bridge\Slim\App. However, as I need to explicitly register the controller class, this kinda defeats the point of using autowiring (unless I'm missing the point):
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use function DI\factory;
class MyApp extends \DI\Bridge\Slim\App
{
public function __construct() {
$containerBuilder = new ContainerBuilder;
$this->configureContainer($containerBuilder);
$container = $containerBuilder->build();
parent::__construct($container);
}
protected function configureContainer(ContainerBuilder $builder)
{
$definitions = [
'TestController' => DI\factory(function (ContainerInterface $c) {
return new MyAPI\Controller\TestController();
})
];
$builder->addDefinitions($definitions);
}
}
$app = new MyApp();
$app->get('/', ['TestController', 'test']);
$app->run();
If you want to call the test method the syntax is :
$app->get('/', TestController::class .':test');
// or
$app->get('/', 'TestController:test');
rather than
$app->get('/', TestController::class ,':test');
cf https://www.slimframework.com/docs/v3/objects/router.html#container-resolution
I registering a controller with the container, but it seems not working because it doesn't match to the correct location.
\slim\src\routes.php
<?php
// Routes
$app->get('/dd', 'App\controllers\HomeController:home');
\slim\App\controllers\HomeController.php
<?php
class HomeController
{
protected $container;
// constructor receives container instance
public function __construct(ContainerInterface $container) {
$this->container = $container;
}
public function home($request, $response, $args) {
// your code
// to access items in the container... $this->container->get('');
return $response;
}
public function contact($request, $response, $args) {
// your code
// to access items in the container... $this->container->get('');
return $response;
}
}
My project folder structure:
\slim
\public
index.php
.htaccess
\App
\controllers
HomeController.php
\src
dependencies.php
middleware.php
routes.php
settings.php
\templates
index.phtml
\vendor
\slim
Maybe I should to setting \slim\src\settings.php?
Because it show Slim Application Error:
Type: RuntimeException Message: Callable
App\controllers\HomeController does not exist File:
D:\htdocs\slim\vendor\slim\slim\Slim\CallableResolver.php Line: 90
Last, I also refer to these articles:
https://www.slimframework.com/docs/objects/router.html#container-resolution
PHP Slim Framework Create Controller
PHP Slim Framework Create Controller
How can i create middleware on Slim Framework 3?
How can i create middleware on Slim Framework 3?
Add psr-4 to your composer file so that you're able to call your namespaces.
{
"require": {
"slim/slim": "^3.12
},
"autoload": {
"psr-4": {
"App\\": "app"
}
}
}
This PSR describes a specification for autoloading classes from file paths. Then in your routes.php file add this at the top :
<?php
use app\controllers\HomeController;
// Routes
$app->get('/dd', 'App\controllers\HomeController:home');
and finally in your HomeController.php file add :
<?php
namespace app\controllers;
class HomeController
{
//.. your code
}
hope this helps...:)
I am trying to just check out the symfony event dispatcher class and i have been following this online tutorial , so i have the following in my index.php file:
<?php
require('vendor/autoload.php');
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
$dispatcher = new EventDispatcher;
$dispatcher->addListener('UserSignedUp' , function(Event $event){
// die('Handling It !!');
var_dump($event);
});
$event = new App\Events\UserSignedUp( (object) [ 'name' => 'gautam' , 'email' => 'gautamz07#yahoo.com' ] );
$dispatcher->dispatch('UserSignedUp' , $event);
and i have the following directory structure:
event_dis
- app
- events
- UserSignUp.php
- vendor
- index.php
- composer.json
I have the following in my composer.json file:
{
"require": {
"symfony/event-dispatcher": "^3.2"
},
"autoload" : {
"psr-4" : {
"App\\" : "app/"
}
}
}
The UserSignedUp.php class looks like the following :
<?php
namespace App\Events;
class UserSignedUp extends Event {
public $user;
public function __construct($user) {
$this->user = $user;
}
}
Now since i have the following line in my index.php file:
$event = new App\Events\UserSignedUp( (object) [ 'name' => 'gautam' , 'email' => 'gautamz07#yahoo.com' ] );
The UserSignedUp class gets called and i get the following error in my browser:
Class 'App\Events\Event' not found in C:\xampp\htdocs\symfony_compo\event_dis\app\Events\UserSignedUp.php on line 6
Now why am i getting this error , in the tutorial this same example works perfectly, but on my local machine this does't , can somebody tell me what am i doing wrong here ??
Event class does not exists in App\Events namespace. You should edit UserSignedUp.php and add use Symfony\Component\EventDispatcher\Event;:
<?php
namespace App\Events;
use Symfony\Component\EventDispatcher\Event;
class UserSignedUp extends Event {
public $user;
public function __construct($user) {
$this->user = $user;
}
}
I am trying to include a third party library into my Symfony 2 project as explained here. However, I keep getting the error message Fatal error: Class 'Sprain_Images' not found in /src/MyProject/MyBundle/Controller/BackendController.php on line 267.
Here is what I did:
I put a third party class into the src folder (not directly in vendors because this class is not available to be loaded by deps).
#Directory structure
-src
-MyProject
-vendor
-sprain
-lib
-Images
-src
Images.php
Then I created the class to be used:
# /src/vendor/sprain/lib/Images/Images.php
require_once __DIR__.'/src/class.Images.php';
class Sprain_Images extends Images {
}
I also registered the prefix in autoload.php:
# /app/autoload.php
$loader->registerPrefixes(array(
'Twig_Extensions_' => __DIR__.'/../vendor/twig-extensions/lib',
'Twig_' => __DIR__.'/../vendor/twig/lib',
'Sprain_' => __DIR__.'/../src/vendor/sprain/lib',
));
And eventually I called the class in my controller:
# /src/MyProject/MyBundle/Controller/BackendController.php
$image = new \Sprain_Images();
However the class is not being found. Where did I make the mistake?
The class Sprain_Images should be in src/vendor/sprain/lib/Sprain/Images.php.
You can read more about the PSR-0 standard : https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md#underscores-in-namespaces-and-class-names
You just need to modify your composer.json file for the autoload value:
http://getcomposer.org/doc/04-schema.md#autoload
//composer.json in your symfony 2.1 project
"autoload": {
"psr-0": {
"": "src/",
"YourLibrary": "src/location/of/lib"
}
},
And then in your controller for example:
namespace Acme\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use YourLibrary\FolderName\ClassName.php;
class DefaultController extends Controller {
/**
* #Route("/")
* #Template()
*/
public function indexAction()
{
$lib = new ClassName();
$lib->getName();
return array('name' => $name);
}
}