php 在 Slim Framework 3 中访问类中的应用程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32365258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Access app in class in Slim Framework 3
提问by user3507740
Im having trouble understanding how to access the instance of Slim when a route is in a seperate class than index.php
当路由位于与 index.php 不同的类中时,我无法理解如何访问 Slim 的实例
When using Slim Framework 2 I always used the following, but its not working in Slim 3:
使用 Slim Framework 2 时,我总是使用以下内容,但在 Slim 3 中不起作用:
$this->app = \Slim\Slim::getInstance();
Im trying to access a database connection I have setup in the container, but from a separate class. This is what I currently got in my index.php to initiate a Slim app:
我试图访问我在容器中设置的数据库连接,但来自一个单独的类。这是我目前在 index.php 中获得的用于启动 Slim 应用程序的内容:
require_once("rdb/rdb.php");
$conn = r\connect('localhost');
$container = new \Slim\Container;
$container['rdb'] = function ($c){return $conn;}
$app = new \Slim\App($container);
And here is my route:
这是我的路线:
$app->get('/test','\mycontroller:test');
And this is what I got in my mycontroller.php class which my route points to, which obviously is not working as $this->app doesn't exist:
这就是我在我的路由指向的 mycontroller.php 类中得到的,这显然不起作用,因为 $this->app 不存在:
class mycontroller{
public function test($request,$response){
$this->app->getContainer()->get('rdb');
}
The error message is the following, due to getinstance not being part of Slim 3 compared to Slim 2:
错误消息如下,因为与 Slim 2 相比,getinstance 不是 Slim 3 的一部分:
Call to undefined method Slim\App::getInstance()
Grateful for any help,
感谢任何帮助,
Regards Dan
问候丹
回答by Martin
Have a look at the Slim 3 Skeletoncreated by Rob Allen.
看看由 Rob Allen 创建的Slim 3 Skeleton。
Slim 3 heavily uses dependency injection, so you might want to use it too.
Slim 3 大量使用依赖注入,因此您可能也想使用它。
In your dependencies.php
add something like:
在您dependencies.php
添加类似:
$container = $app->getContainer();
$container['rdb'] = function ($c) {
return $conn;
};
$container['Your\Custom\Class'] = function ($c) {
return new \Your\Custom\Class($c['rdb']);
};
And in your Your\Custom\Class.php
:
而在你的Your\Custom\Class.php
:
class Class {
private $rdb;
function __construct($rdb) {
$this->rdb = $rdb;
}
public function test($request, $response, $args) {
$this->rdb->doSomething();
}
}
I hope this helps, if you have any more questions feel free to ask.
我希望这会有所帮助,如果您有更多问题,请随时提出。
Update:
更新:
When you define your route like this
当你像这样定义你的路线时
$app->get('/test', '\mycontroller:test');
Slim looks up \mycontroller:test
in your container:
Slim\mycontroller:test
在您的容器中查找:
$container['\mycontroller'] = function($c) {
return new \mycontroller($c['rdb']);
}
So when you open www.example.com/test
in your browser, Slim automatically creates a new instance of \mycontroller
and executes the method test
with the arguments $request
, $response
and $args
.
And because you accept the database connection as an argument for the constructor of your mycontroller
class, you can use it in the method as well :)
因此,当您www.example.com/test
在浏览器中打开时,Slim 会自动创建一个 的新实例\mycontroller
并test
使用参数$request
、$response
和执行该方法$args
。并且因为您接受数据库连接作为mycontroller
类构造函数的参数,所以您也可以在方法中使用它:)
回答by Rob Allen
With Slim 3 RC2 and onwards given a route of:
使用 Slim 3 RC2 及以后给出的路线:
$app->get('/test','MyController:test');
The CallableResolver
will look for a key in the DIC called 'MyController'
and expect that to return the controller, so you can register with the DIC like this:
该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
}
}
Alternatively, if you don't register with the DIC, then the CallableResolver
will pass the container to your constructor, so you can just create a controller like this:
或者,如果您不向 DIC 注册,则将CallableResolver
容器传递给您的构造函数,因此您可以像这样创建一个控制器:
class MyController
{
public function __construct($container) {
$this->rdb = $container->get('rdb');
}
public function test($request,$response){
// do something with $this->rdb
}
}
回答by Lee
I created the following base controller and extended from that. Only just started playing with Slim but it works if you need access to to the DI in your controllers.
我创建了以下基本控制器并从中扩展。刚刚开始玩 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);
}
}
}
Then in your other controllers you can use it like this.
然后在您的其他控制器中,您可以像这样使用它。
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');
}
}
回答by Leo Leao
This was a tough one. @mgansler answer was really helpful, but in his answer he passed a database connection, and not exactly $app inside the controller
这是一场艰难的比赛。@mgansler 的回答真的很有帮助,但在他的回答中,他传递了一个数据库连接,而不是控制器内部的 $app
Following the same idea it is possible to send $app though.
按照同样的想法,虽然可以发送 $app。
First inside your dependencies.php you need to grab the $app and throw it in a container to inject it to the Controller later.
首先在您的 dependencies.php 中,您需要获取 $app 并将其放入容器中,以便稍后将其注入控制器。
$container['slim'] = function ($c) {
global $app;
return $app;
};
Then you got to inject it:
然后你必须注入它:
// Generic Controller
$container['App\Controllers\_Controller'] = function ($c) {
return new _Controller($c->get('slim'));
};
Now on your controller.php:
现在在你的 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;
}
Now you just got call it like this:
现在你可以这样称呼它:
$this->slim->doSomething();
回答by Daniel Brose
Important
重要的
I upvoted @mgansler and you should read that first if dealing with slim 3, and read this only if interested in differences to slim 2.
我对@mgansler 投了赞成票,如果处理的是 slim 3,你应该先阅读它,并且只有在对与 slim 2 的差异感兴趣时才阅读这篇文章。
Update
更新
So it seems those usages were just old code no one cleaned.
因此,这些用法似乎只是没有人清理过的旧代码。
However im leaving this post here as it should be helpful to anyone using Slim 2 (as slim 3 is very much still beta) and as a referance point to help see differences.
然而,我把这篇文章留在这里,因为它应该对任何使用 Slim 2 的人有所帮助(因为 slim 3 仍然是测试版),并作为帮助查看差异的参考点。
Old Update (see above)
旧更新(见上文)
Following update of OP, i looked at github source code and found that getInstance is still very much there, but with some slight differences perhaps...
在 OP 更新之后,我查看了 github 源代码,发现 getInstance 仍然非常多,但可能有一些细微的差异......
https://github.com/slimphp/Slim/search?utf8=%E2%9C%93&q=getInstance
https://github.com/slimphp/Slim/search?utf8=%E2%9C%93&q=getInstance
Test files (which maybe outdated, but unlikely) show something like this:
测试文件(可能已经过时,但不太可能)显示如下内容:
public function testGetCallableAsStaticMethod()
{
$route = new \Slim\Route('/bar', '\Slim\Slim::getInstance');
$callable = $route->getCallable();
$this->assertEquals('\Slim\Slim::getInstance', $callable);
}
But at the same time we see calls like this in some files, which are obviously contextual and either return diff object ($env) or are in same static file (Slim.php)
但同时我们在一些文件中看到这样的调用,这些调用显然是上下文的,要么返回差异对象($env),要么在同一个静态文件(Slim.php)中
$env = \Slim\Environment::getInstance(true);
static::getInstance();
But this does show the static function still exists, so use my examples below and try to figure out why not working for you in current form.
但这确实表明静态函数仍然存在,因此请使用我下面的示例并尝试找出为什么不以当前形式为您工作。
Also, this 'maybe' of interest, as only obvious example of slim3 in usage: https://github.com/akrabat/slim3-skeleton
此外,这个“可能”很有趣,作为使用 slim3 的唯一明显示例:https: //github.com/akrabat/slim3-skeleton
Though other projects prob exist, search with github filters if still having issues.
尽管存在其他项目 prob,但如果仍有问题,请使用 github 过滤器进行搜索。
Original Answer content
原答案内容
Please include more detail on the route and the other class, but here are 3 ways, with execution examples detailed further down.
请包括有关路线和其他课程的更多详细信息,但这里有 3 种方法,并在后面详细说明了执行示例。
This info does relate to Slim Framework 2, not the Slim 3 beta, but slim 3 beta shows similar example code and makes no mention of overhauling changes, and in fact links to the Slim 2 documentation: http://docs.slimframework.com/configuration/names-and-scopes/
此信息确实与 Slim Framework 2 相关,而不是 Slim 3 beta,但 slim 3 beta 显示了类似的示例代码并且没有提及大修更改,实际上链接到 Slim 2 文档:http: //docs.slimframework.com /配置/名称和范围/
$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 has only one code example, which looks like this:
Slim3 Beta 只有一个代码示例,如下所示:
$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()
Though obviously this doesnt fit outside of index.php, but is consistent with Slim2 doco showing GetInstance works.
虽然显然这不适合 index.php 之外,但与显示 GetInstance 工作的 Slim2 doco 一致。
Which one fits you?
哪一款适合你?
I have multiple files that use these different approaches, though i cant say what fits best as too little context on how this external class fits in and what its composition is.
我有多个使用这些不同方法的文件,但我无法说出什么最适合,因为关于这个外部类如何适合以及它的组成是什么的上下文太少。
For example, my controllers(which are endpoints of most my routes) use the same approach, through a base class or just direct:
例如,我的控制器(大多数路由的端点)使用相同的方法,通过基类或直接:
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();
}
//...
}
My helper filesshow code like this:
我的帮助文件显示如下代码:
function get_permissions_options_list($context = null)
{
if(empty($context)) $context = 'user';
return App::config('permissions')[$context];
}
My 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;
}
Thats example of how i access in the various files, though the code you shared already shows that you have used the recommended approach already
这是我如何访问各种文件的示例,尽管您共享的代码已经表明您已经使用了推荐的方法
$app = \Slim\Slim::getInstance();
Though again, need more info to say for sure how your external file fits in, but if its at the end of a route or in an 'include()', then it should work.
虽然再次需要更多信息来确定您的外部文件如何适应,但如果它位于路由的末尾或在“include()”中,那么它应该可以工作。
You said your old approach didnt work though, but gave no info on what the actual result vs expected result was (error msg, ect), so if this doesnt work please update the OP.
你说你的旧方法虽然不起作用,但没有提供实际结果与预期结果的信息(错误消息等),所以如果这不起作用,请更新 OP。