Reputation: 125
i am a new in slim framework and am using anonymous functions of routes to access database data with a given route and its working but if i try to pass them in a controller am getting the error bellow
Slim Application Error The application could not run because of the following error:
Details
Type: Error Message: Call to undefined method Slim\Container::prepare() File: C:\xampp\htdocs\drivingapp\app\src\Controllers\apiController.php Line: 22 Trace
#0 [internal function]: App\Controllers\apiController->igice(Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#1 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\Handlers\Strategies\RequestResponse.php(41): call_user_func(Array, Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#2 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\Route.php(344): Slim\Handlers\Strategies\RequestResponse->__invoke(Array, Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#3 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\MiddlewareAwareTrait.php(116): Slim\Route->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#4 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\Route.php(316): Slim\Route->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#5 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\App.php(438): Slim\Route->run(Object(Slim\Http\Request), Object(Slim\Http\Response))
#6 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\MiddlewareAwareTrait.php(116): Slim\App->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#7 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\App.php(332): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#8 C:\xampp\htdocs\drivingapp\vendor\slim\slim\Slim\App.php(293): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response))
#9 C:\xampp\htdocs\drivingapp\public\index.php(30): Slim\App->run()
#10 {main}
Below is my apiController.php:
<?php
namespace App\Controllers;
use Slim\Views\Twig;
use Psr\Log\LoggerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
class apiController{
private $db;
public function __construct($db){
$this->db = $db;
}
public function igice($request, $response){
$stmt = $this->db->prepare("SELECT * FROM igice ORDER BY igiceid");
$stmt->execute();
$dowork = $stmt->fetchAll();
return $this->response->withJson($dowork);
}
}
bellow it is my my dependencie.php
$container['db'] = function ($c) {
$settings = $c->get('settings')['db'];
$pdo = new PDO("mysql:host=" . $settings['host'] . ";dbname=" . $settings['dbname'],
$settings['user'], $settings['pass']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
};
// -----------------------------------------------------------------------------
// Registering Controllers
// -----------------------------------------------------------------------------
$container[App\Action\HomeAction::class] = function ($c) {
return new App\Action\HomeAction($c->get('view'), $c->get('logger'));
};
$container['apiController']=function($c){
return new App\Controllers\apiController($c->get('db'));
};
Below its my routes.php:
$app->get('/ibice','App\Controllers\apiController:igice');
Upvotes: 1
Views: 3415
Reputation: 321
Its better to add container to your apiController constructor to easily access all container objects including db so you can easily change your code like this sample :
by just adding __get magic method to your controller and you can easily access all container objects in your controller just using $this->dependency name ;)
<?php
namespace App\Controllers;
use Slim\Views\Twig;
use Psr\Log\LoggerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
class apiController{
protected $container;
public function __construct($container){
$this->container = $container;
}
public function __get($property)
{
if ($this->container->{$property}) {
return $this->container->{$property};
}
}
public function igice($request, $response){
$stmt = $this->db->prepare("SELECT * FROM igice ORDER BY igiceid");
$stmt->execute();
$dowork = $stmt->fetchAll();
return $this->response->withJson($dowork);
}
}
in your dependencies :
$container['apiController']=function($c){
return new App\Controllers\apiController($c);
};
and for the routes :
$app->get('/ibice','App\Controllers\apiController:igice');
like yours before
Upvotes: 1
Reputation: 190
Modify apiController.php
<?php
namespace App\apiController;
use Slim\Views\Twig;
use Psr\Log\LoggerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
use PDO;
final class apiController{
private $db;
public function __construct($host, $dbname, $user, $password){
try {
$this->db = new PDO("mysql:host=" . $host . ";dbname=" . $dbname, $user, $password);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function getDb() {
if ($this->db instanceof PDO) {
return $this->db;
}
}
}
Then you should write functions for each route and i am giving you an example
<?php
namespace App\apiController;
use Slim\Views\Twig;
use Psr\Log\LoggerInterface;
use Slim\Http\Request;
use Slim\Http\Response;
final class Hello
{
private $view;
private $conn;
public function __construct(Twig $view, $db)
{
$this->view = $view;
$this->conn = $db->getDb();
}
public function __invoke(Request $request, Response $response, $args)
{
$this->logger->info("action dispatched");
$stmt = $this->conn->prepare("SELECT * FROM igice ORDER BY igiceid");
$stmt->execute();
$dowork = $stmt->fetchAll();
return $response->withJson($dowork,201);
}
}
modify dependencies.php
$container['apiController']=function($c){
return new App\Controllers\apiController::class($c->get('db'));
};
Upvotes: 1