slimphp / Slim

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
http://slimframework.com
MIT License
11.98k stars 1.95k forks source link

Slim3 app magic __get passthrough #1660

Closed mbretter closed 8 years ago

mbretter commented 8 years ago

Hi,

during the migration from slim2 to 3, I've found that it would help a lot having

    public function __get($name)
    {
        return $this->container->get($name);
    }

within \Slim\App any chance getting this into Slim3?

thx,

silentworks commented 8 years ago

This is actually in the Container and since a closure is bound to the Container you can call services the same as you would in Slim 2.

https://github.com/slimphp/Slim/blob/3.x/Slim/Container.php#L287

$app->get('/foo/bar', function ($request, $response)
    $this->router->methodName();
});

You should also note there is a Strategy that allows you to map placeholders to args like in Slim 2, so you can do.

$app->get('/foo/bar/:name', function ($request, $response, $name)
    return $response->getBody()->write("Hello $name")
});

Will get something written up about migrating soon.

mbretter commented 8 years ago

I've used Slim2 as a container for a lot of stuff, like

$app->cache->get(...

with slim3 I have to rewrite tons of calls to

$app->getContainer()->cache->get(...

cache is in this case not a callable, so the __call() passthrough does nothing in this case

silentworks commented 8 years ago

Look at my example again, you can do the same, you just need to replace $app in the Closure to $this.

geggleto commented 8 years ago

As @silentworks mentioned

$app->cache->get(... becomes $this->cache in slim 3. The container has magic method support.

mbretter commented 8 years ago

most of my code is not directly in the route callback, it's inside classes somewhere else, where I'm getting the app using \Slim\Slim::getInstance(); (using a trait)

silentworks commented 8 years ago

Do note all classes that are instantiated by Slim itself using

$app->get('/', 'MyClass:hello');

The constructor is passed an instance of Container, so you can do


class MyClass
{
    private $container;
    public function __construct($container)
    {
        $this->container = $container;
    }

    public function hello()
    {
        $this->container->cache->get(...
    }
}

or you can create your own App class and extend Slim\App and add the magic getter to your version.

mbretter commented 8 years ago

My classes are Singletons, they are not directly instantiated by Slim, this would mean that I have to change the constructor/init of all of my classes and pass the container to all of them. Without accessing the global $app I have to make big changes to my source code.

One possibility would be exchanging the content from $app (currently instance of \Slim\App) with $app->getContainer().

It's not a big thing if you are starting from scratch with a new Slim application, but I'm migrating an existing application, I'm trying to keep the necessary code changes as small as possible. However I made a subclass of Slim and put the __get() in there.

geggleto commented 8 years ago

Glad you got it sorted.

If you could plz open an issue in the slim-website repo with what you did we can put it into the docs under a Strategy section!

feryardiant commented 8 years ago

I'm using __get() in my base controller so I can just use $this->view->.. form my main controller

mbretter commented 8 years ago

doc issue in website repo opened: https://github.com/slimphp/Slim-Website/issues/83