frontendkiller
frontendkiller

Reputation: 125

Slim 3 controller not connecting to db container

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

Answers (2)

Ali Kaviani
Ali Kaviani

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

srk
srk

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

Related Questions