Your thoughts on auto-include my models/controller to DI container?


#1

I’m trying to find a good way to auto-include my modes/controller so i don’t need to repeat my self over and over to include them in the DI container. But is it safe, what do you recommend ?

example (when repeat my self)

//  Model
$container['user'] = function ($container) {
    return new \App\Models\User($container);
};


$container['products'] = function ($container) {
    return new \App\Models\Product($container);
};

// controllers
$container['HomeController'] = function ($container) {
    return new \App\Controllers\HomeController($container);
};

$container['AuthController'] = function ($container) {
    return new \App\Controllers\AuthController($container);
};

and so on (doing this process by hand takes time and repeat)....

Is Slim-Bridge the way to go ?


#2

Personally i do not use container for models.
And why do you inject the container into the Model?

imho the only thing should a model use in the constructor is the properties that are required for the object to be instantiated.

$user = new User(‘John’, ‘Robber’)

For the controller i recommend you to use the invocable magic method and put them into the container as the doc suggest: https://www.slimframework.com/docs/objects/router.html#container-resolution

It’s a very valid way of thinking “use cases > controller”


#3

How iam i suppose to call the models from the controllers ? example ? I’m using autoload psr-4 if you need to know :slight_smile:

Example of routes

$this->post('/createorder', 'OrdersController:postOrders')
->setName('order')
->setArgument('nav.public', 'hidden')
->setArgument('access', 2); // Who can access

#4

You can create your Model using the “new” keyword.
Try to keep it simple for the moment, then you can use some design patterns and make it more testable.

You can try to see this for a basic example:


#6

This is what i have now.

Post Controller

namespace App\Controllers;
use Slim\Views\Twig as View;
use \App\Models\Post as Post;

class PostController extends Controller{

    public function index($request, $response){


   
		Post::index();

        return $this->view->render($response, 'posts.twig');
   
    }
}

Post Model

namespace App\Models;
use Slim\Views\Twig as View;

class Post extends Model{

	public static function index(){ // __invoke(){

		echo 'asdasd';
       
        
	}


}

#7

Hi,
you could have a base controller and inject the dependencies you always (request, response, …) use in its constructor

For injecting models or other objects in the controller withoud having to type all that code in the routes I think the best solution is having some kind of automatic resolution like Laravel does.

Take a look at the link bellow. I have implemented a route resolver method that resolves and injects into the controller uri arguments, container dependencies or tries to automatically resolve and inject a object using reflection if the first two fail.


#8

i have a tiny problem with my code now, i cant use $this->container bcs the Model.php is not getting called anywhere with the container in it, any ideas how to do it without injecting it to the container ?

Model.php

namespace App\Models;
use \Slim\PDO\Database as pdo;
class Model{
    private $container;
    public function __construct($container){
        $this->container = $container;

    }
    public function __get($property){
        if ($this->container->{$property}) {
            return $this->container->{$property};
        }
    }
}

User.php

    namespace App\Models;
    use Slim\Views\Twig as View;

    class User extends Model{

    	public function attempt($username, $password){

    		$stmt  = $this->container->pdo->select()->from('account')->where('accountid', '=', $username);
    		$stmt  = $stmt->execute();
    		$data  = $stmt->fetch();
            	if ($data) {
                            // call pw fucntion for pw match
                    	// ŕeturn $data;
                    }else{
                    	return false;
                    }
    	}

    }

#9

since the magic method __get exists in your model i think you can change the line bellow

$stmt  = $this->container->pdo->select()->from('account')->where('accountid', '=', $username);

$stmt  = $this->pdo->select()->from('account')->where('accountid', '=', $username);

in my opinion Model constructor should only receive \Slim\PDO\Database and not thw whole container.


#10

cant call it from the user model

$stmt  = $pdo->select()->from('account')->where('accountid', '=', $username);

Type: Error
Message: Call to a member function select() on null
File: /var/www/hpseed.dev/app/Models/User.php
Line: 16