web-dev-qa-db-ja.com

Slim Framework 3のクラスのアプリにアクセスする

ルートがindex.phpとは別のクラスにある場合、Slimのインスタンスにアクセスする方法を理解できません

Slim Framework 2を使用するとき、私は常に以下を使用しましたが、Slim 3では機能しません。

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

コンテナでセットアップしたデータベース接続にアクセスしようとしていますが、別のクラスからです。これは、スリムアプリを開始するために現在index.phpで取得しているものです。

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

そして、これが私のルートです:

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

そして、これは私のルートが指すmycontroller.phpクラスで取得したものです。$ this-> appが存在しないため、明らかに機能していません。

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

GetinstanceがSlim 2と比較してSlim 3の一部ではないため、エラーメッセージは次のとおりです。

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

どんな助けにも感謝します、

よろしく

11
user3507740

Rob Allenが作成した Slim 3 Skeleton をご覧ください。

Slim 3は依存性注入を頻繁に使用するため、使用することもできます。

dependencies.phpに次のようなものを追加します。

$container = $app->getContainer();

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

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

そしてあなたのYour\Custom\Class.php

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

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

他にご不明な点がございましたら、お気軽にお問い合わせください。

更新:

このようにルートを定義すると

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

Slimがコンテナで\mycontroller:testを検索します。

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

そのため、ブラウザでwww.example.com/testを開くと、Slimは自動的に\mycontrollerの新しいインスタンスを作成し、引数$request$responseを使用してメソッドtestを実行します。 $args。また、データベース接続をmycontrollerクラスのコンストラクターの引数として受け入れるため、メソッドでも使用できます:)

13
Martin

Slim 3 RC2以降では、以下のルートが与えられます:

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

CallableResolverは、DICで'MyController'というキーを検索し、それがコントローラーを返すことを期待するため、次のようにDICに登録できます。

// 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
    }
}

または、DICに登録しない場合、CallableResolverはコンテナーをコンストラクターに渡すため、次のようなコントローラーを作成できます。

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

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

以下のベースコントローラーを作成して拡張しました。 Slimを使い始めたばかりですが、コントローラーでDIにアクセスする必要がある場合に機能します。

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);
        }
    }
}

次に、他のコントローラーでこのように使用できます。

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

重要

私は@mganslerに賛成票を投じました。スリム3を扱う場合は最初に読んでください。スリム2との違いに興味がある場合にのみ読んでください。


更新

だから、それらの使用法は誰も掃除していない古いコードだったようです。

ただし、Slim 2(sli​​m 3はまだ非常にベータ版であるため)を使用しているすべてのユーザーに役立つはずであり、違いを確認するための参照ポイントとしてこの投稿をここに残します。


古い更新(上記を参照)

OPの更新後、GitHubのソースコードを調べたところ、getInstanceはまだ非常に多くありますが、わずかな違いがあるかもしれません...

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

テストファイル(古くなっている可能性がありますが、ほとんどありません)は次のように表示されます。

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

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

しかし、同時にいくつかのファイルでこのような呼び出しが見られます。これらのファイルは明らかにコンテキストに依存しており、diffオブジェクト($ env)を返すか、同じ静的ファイル(Slim.php)にあります

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

static::getInstance();

しかし、これは静的関数がまだ存在していることを示しているので、以下の私の例を使用して、現在の形式で機能しない理由を理解してみてください。

また、slim3の使用例として明らかな例としてのみ、この「たぶん」が興味深いかもしれません: https://github.com/akrabat/slim3-skeleton

他のプロジェクトが存在する可能性がありますが、問題が解決しない場合はgithubフィルターで検索してください。



元の回答内容

ルートと他のクラスの詳細を含めてください。ここでは3つの方法を示します。実行例の詳細は下にあります。

この情報はSlim 3ベータではなくSlim Framework 2に関連していますが、slim 3ベータは同様のコード例を示し、変更のオーバーホールについて言及しておらず、実際にはSlim 2のドキュメントへのリンク: 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には、次のようなコード例が1つだけあります。

$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()

明らかにこれはindex.phpの外には適合しませんが、GetInstanceの動作を示すSlim2 docoと一致しています。


どちらがあなたに合いますか?

私はこれらの異なるアプローチを使用する複数のファイルを持っていますが、この外部クラスがどのように適合し、その構成が何であるかについてのコンテキストが少なすぎるため、何が最も適合するのかは言えません。


たとえば、my controllers(ほとんどの私のルートのエンドポイントです)は、基本クラスまたは直接の方法で同じアプローチを使用します。

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();
    }


    //...
}


私のヘルパーファイルは次のようなコードを表示します:

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


ミドルウェア:

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;
}


さまざまなファイルでのアクセス方法の例ですが、共有したコードはすでに推奨されたアプローチをすでに使用していることを示しています

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

繰り返しますが、外部ファイルがどのように適合するかを確認するために、より多くの情報が必要ですが、それがルートの最後または「include()」にある場合は、機能するはずです。

古いアプローチは機能しなかったと言いましたが、実際の結果と期待される結果が何であるかについての情報はありませんでした(エラーメッセージなど)。これが機能しない場合は、OPを更新してください。

1
Daniel Brose

これは大変でした。 @mganslerの回答は本当に役に立ちましたが、彼の回答ではデータベース接続を通過しましたが、コントローラー内の$ appではありませんでした

同じアイデアに従って、$ appを送信することもできます。

まず、dependencies.php内で、$ appを取得し、それをコンテナーにスローして、後でコントローラーに注入する必要があります。

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

次に、それを注入する必要があります:

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

今あなたの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;
    }

これで、次のように呼び出すことができます。

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