wake-up-neo.net

Greifen Sie in Slim Framework 3 auf die App zu

Ich habe Probleme, zu verstehen, wie auf die Instanz von Slim zugegriffen werden kann, wenn sich eine Route in einer separaten Klasse als index.php befindet

Bei der Verwendung von Slim Framework 2 habe ich immer Folgendes verwendet, aber es funktioniert nicht in Slim 3:

$this->app = \Slim\Slim::getInstance();

Ich versuche, auf eine Datenbankverbindung zuzugreifen, die ich im Container eingerichtet habe, aber von einer separaten Klasse. Dies ist, was ich derzeit in meiner index.php habe, um eine Slim-App zu initiieren:

require_once("rdb/rdb.php");
$conn = r\connect('localhost');
$container = new \Slim\Container;
$container['rdb'] = function ($c){return $conn;}
$app = new \Slim\App($container);

Und hier ist meine Route:

$app->get('/test','\mycontroller:test');

Und das ist, was ich in meiner mycontroller.php-Klasse bekommen habe, auf die meine Route verweist, was offensichtlich nicht funktioniert, da diese App nicht existiert: 

class mycontroller{
public function test($request,$response){
$this->app->getContainer()->get('rdb');
}

Die Fehlermeldung ist folgende, da Getinstance nicht Teil von Slim 3 im Vergleich zu Slim 2 ist:

Call to undefined method Slim\App::getInstance() 

Für jede Hilfe dankbar,

Grüße Dan

11
user3507740

Werfen Sie einen Blick auf das Slim 3 Skeleton von Rob Allen.

Slim 3 verwendet stark Abhängigkeitsinjektionen, so dass Sie diese möglicherweise auch verwenden möchten.

Fügen Sie in Ihrem dependencies.php etwas hinzu:

$container = $app->getContainer();

$container['rdb'] = function ($c) {
    return $conn;
};

$container['Your\Custom\Class'] = function ($c) {
    return new \Your\Custom\Class($c['rdb']);
};

Und in deinem Your\Custom\Class.php:

class Class {
    private $rdb;
    function __construct($rdb) {
        $this->rdb = $rdb;
    }

    public function test($request, $response, $args) {
        $this->rdb->doSomething();
    }
}

Ich hoffe das hilft, wenn Sie weitere Fragen haben, zögern Sie nicht zu fragen.

Update:

Wenn Sie Ihre Route so definieren

$app->get('/test', '\mycontroller:test');

Slim sucht in Ihrem Container nach \mycontroller:test:

$container['\mycontroller'] = function($c) {
    return new \mycontroller($c['rdb']);
}

Wenn Sie also www.example.com/test in Ihrem Browser öffnen, erstellt Slim automatisch eine neue Instanz von \mycontroller und führt die Methode test mit den Argumenten $request, $response und $args____ aus. Außerdem akzeptieren Sie die Datenbankverbindung als Argument für den Konstruktor Ihrer mycontroller. Klasse, du kannst es auch in der Methode verwenden :)

13
Martin

Ab Slim 3 RC2 eine Route von:

$app->get('/test','MyController:test');

Die Variable CallableResolver sucht im DIC nach einem Schlüssel namens 'MyController' und erwartet, dass der Controller zurückgegeben wird. Sie können sich also beim DIC wie folgt registrieren:

// Register controller with DIC
$container = $app->getContainer();
$container['MyController'] = function ($c) {
    return new MyController($c->get('rdb'));   
}

// Define controller as:
class MyController
{
    public function __construct($rdb) {
        $this->rdb = $rdb;
    }

    public function test($request,$response){
        // do something with $this->rdb
    }
}

Wenn Sie sich nicht bei der DIC registrieren, wird die Containervariable CallableResolver an Ihren Konstruktor übergeben. Sie können also einfach einen Controller wie folgt erstellen:

class MyController
{
    public function __construct($container) {
        $this->rdb = $container->get('rdb');
    }

    public function test($request,$response){
        // do something with $this->rdb
    }
}
6
Rob Allen

Ich habe den folgenden Basiscontroller erstellt und daraus erweitert. Ich habe gerade erst angefangen, mit Slim zu spielen, aber es funktioniert, wenn Sie Zugriff auf das DI in Ihren Controllern haben.

namespace App\Controllers;

use Interop\Container\ContainerInterface;

abstract class Controller
{
    protected $ci;

    /**
     * Controller constructor.
     *
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface  $container)
    {
        $this->ci = $container;
    }

    /**
     * @param $name
     * @return mixed
     */
    public function __get($name)
    {
        if ($this->ci->has($name)) {
            return $this->ci->get($name);
        }
    }
}

Dann können Sie es in Ihren anderen Controllern so verwenden.

namespace App\Controllers;

 /**
 * Class HomeController
 *
 * @package App\Controllers
 */
class HomeController extends Controller
{

    /**
     * @param $request
     * @param $response
     * @param $args
     * @return \Slim\Views\Twig
     */
    public function index($request, $response, $args)
    {
        // Render index view
        return $this->view->render($response, 'index.twig');
    }

}
2
Lee

Wichtig

Ich habe @mgansler upvoted und Sie sollten dies zuerst lesen, wenn Sie sich mit Slim 3 beschäftigen, und dies nur dann, wenn Sie an Unterschieden zu Slim 2 interessiert sind.


Update

Es scheint also, dass diese Verwendungen nur alter Code waren, den niemand gesäubert hat.

Allerdings lasse ich diesen Beitrag hier, da er für jeden hilfreich sein sollte, der Slim 2 verwendet (Slim 3 ist noch sehr viel Beta) und als Referenzpunkt dient, um Unterschiede zu erkennen.


Altes Update (siehe oben)

Nach dem Update des OP habe ich mir den Quellcode von github angesehen und festgestellt, dass getInstance immer noch sehr viel vorhanden ist, aber mit ein paar kleinen Unterschieden ...

https://github.com/slimphp/Slim/search?utf8=%E2%9C%93&q=getInstance

Testdateien (die möglicherweise veraltet sind, aber unwahrscheinlich) zeigen Folgendes:

public function testGetCallableAsStaticMethod()
{
    $route = new \Slim\Route('/bar', '\Slim\Slim::getInstance');

    $callable = $route->getCallable();
    $this->assertEquals('\Slim\Slim::getInstance', $callable);
}

Gleichzeitig sehen wir jedoch in einigen Dateien Aufrufe wie diese, die offensichtlich kontextabhängig sind und entweder ein diff-Objekt ($ env) zurückgeben oder sich in derselben statischen Datei befinden (Slim.php).

$env = \Slim\Environment::getInstance(true);

static::getInstance();

Dies zeigt jedoch, dass die statische Funktion immer noch vorhanden ist. Verwenden Sie daher meine Beispiele und versuchen Sie herauszufinden, warum Sie nicht in der aktuellen Form für Sie arbeiten.

Auch dieses "vielleicht" von Interesse, als einziges offensichtliches Beispiel für slim3 im Gebrauch: https://github.com/akrabat/slim3-skeleton

Obwohl andere Projekte möglicherweise vorhanden sind, suchen Sie mit Github-Filtern, wenn noch Probleme auftreten.



Originaler Antwortinhalt

Bitte geben Sie mehr Details zu der Route und der anderen Klasse an, aber hier gibt es drei Möglichkeiten, Ausführungsbeispiele weiter unten.

Diese Informationen beziehen sich auf Slim Framework 2, nicht auf die Slim 3-Betaversion, aber die Slim 3-Betaversion zeigt einen ähnlichen Beispielcode und erwähnt keine Überholungsänderungen. Sie enthält auch Links zur Slim 2-Dokumentation: http: //docs.slimframework .com/configuration/names-and-scopes/

$this->app->getContainer()->get('rdb');

// Recommended approach, can be used in any file loaded via route() or include()
$app = \Slim\Slim::getInstance();

Slim::getInstance();

App::config('filename');

Slim3 Beta hat nur ein Codebeispiel, das wie folgt aussieht:

$app = new \Slim\App();

// which would by extension mean that this 'might' work too

$app = \Slim\App::getInstance();

// but be sure to try with slim2 naming just in case

$app = \Slim\Slim::getInstance()

Natürlich passt das nicht außerhalb von index.php, ist aber konsistent mit Slim2 Doco, das GetInstance-Werke zeigt.


Welches passt zu dir?

Ich habe mehrere Dateien, die diese unterschiedlichen Ansätze verwenden, obwohl ich nicht sagen kann, was am besten als zu wenig Kontext dazu passt, wie diese externe Klasse passt und wie ihre Zusammensetzung aussieht.


Zum Beispiel verwenden meine Controller (die Endpunkte der meisten Routen sind) denselben Ansatz, über eine Basisklasse oder einfach direkt:

class ApiBaseController /// extends \BaseController
{

    protected $app;
    protected $data;

    public function __construct()
    {

        $this->app = Slim\Slim::getInstance();
        $this->data = array();

    }

    //...

}


class VideoApiController extends \ApiBaseController
{

    // ... 


    public function embed($uid)
    {
        // trace($this->app->response->headers());
        $vid = \R::findOne('videos'," uid = ? ",array($uid));
        if(!empty($vid))
        {

            // embed logic

        }else{
            // see my baseclass
            $this->app->render('api/404.html', array(), 404);
        }
    }


    // ...




    // Returns the video file, keeping actual location obscured
    function video($uid)
    {
        require_once(APP_PATH.'helpers/player_helper.php');

        $data = \R::findOne('videos'," uid = ? ",array($uid));

        /// trace($_SERVER); die();

        if($data)
        {
            stream_file($data['filename']);
        }else{
            $app = \Slim\Slim::getInstance();
            $app->render('404.html');
        }

        /// NOTE - only same domain for direct /v/:uid call
        header('Access-Control-Allow-Origin : '.$_SERVER['HTTP_Host']);
        // header('X-Frame-Options: SAMEORIGIN');

        // Exit to be certain nothing else returned
        exit();
    }


    //...
}


Meine Hilfedateien zeigen Code wie folgt:

function get_permissions_options_list($context = null)
{
    if(empty($context)) $context = 'user';
    return App::config('permissions')[$context];
}


Meine Middleware:

function checkAdminRoutePermissions($route)
{
    $passed = runAdminRoutePermissionsCheck($route);

    if($passed)
        return true;

    // App::notFound();
    // App::halt(403, $route->getPattern());

    if(!Sentry::check())
        App::unauthorizedNoLogin();
    else
        App::unauthorized();
    return false;
}


Dies ist ein Beispiel für den Zugriff auf die verschiedenen Dateien, obwohl der von Ihnen freigegebene Code bereits zeigt, dass Sie die empfohlene Vorgehensweise bereits verwendet haben

$app = \Slim\Slim::getInstance();

Auch wenn Sie weitere Informationen benötigen, um sicher zu sagen, wie Ihre externe Datei passt, aber wenn sie sich am Ende einer Route oder in einem "include ()" befindet, sollte sie funktionieren.

Sie sagten, Ihr alter Ansatz funktionierte zwar nicht, gab jedoch keine Informationen darüber an, wie das tatsächliche Ergebnis im Vergleich zum erwarteten Ergebnis war (Fehler msg, ect). Wenn dies nicht funktioniert, aktualisieren Sie bitte das OP.

1
Daniel Brose

Dies war eine schwierige Frage. Die Antwort von @mgansler war wirklich hilfreich, aber in seiner Antwort übergab er eine Datenbankverbindung und nicht genau die $ app im Controller

Nach der gleichen Idee ist es möglich, $ app zu senden.

Zuerst müssen Sie in Ihrer dependencies.php die $ app packen und in einen Container werfen, um sie später in den Controller einzuspeisen.

$container['slim'] = function ($c) {
   global $app;
   return $app;
};

Dann musst du es spritzen:

// Generic Controller
$container['App\Controllers\_Controller'] = function ($c) {
    return new _Controller($c->get('slim'));
};

Nun auf deinem Controller.php:

private $slim;

/**
     * @param \Psr\Log\LoggerInterface       $logger
     * @param \App\DataAccess                $dataaccess
     * @param \App\$app                      $slim
     */
    public function __construct(LoggerInterface $logger, _DataAccess $dataaccess, $slim)
    {       
        $this->logger = $logger;
        $this->dataaccess = $dataaccess;
        $this->slim = $slim;
    }

Jetzt hast du es einfach so genannt:

$this->slim->doSomething();
1
Leo Leao