Symfony2 : get current directory error - php

When I try to get the current directory with :
$this->container->getParameter('kernel.root_dir').'/../web/
I've got this error : Fatal error: Using $this when not in object context in C:\XXX on line 124
Code :
class AdminController {
/**
* Add event controller.
*
* #param Request $request Incoming request
* #param Application $app Silex application
*/
public function addEventAction(Request $request, Application $app) {
$event = new Event();
$types= $app['dao.type']->findAllSelectList();
$eventForm = $app['form.factory']->create(new EventType($types), $event);
$eventForm->handleRequest($request);
if ($eventForm->isSubmitted() && $eventForm->isValid()) {
var_dump($event->getCoverImageLink());
$file = $event->getCoverImageLink();
$fileName = md5(uniqid()).'.'.$file->guessExtension();
var_dump($fileName);
//$path = $this->container->getParameter('kernel.root_dir').'/../web';//$this->get('kernel')->getRootDir() . '/../web';
var_dump($this);
$app['dao.event']->save($event);
$app['session']->getFlashBag()->add('success', 'The event was successfully created.');
}
return $app['twig']->render('event_form.html.twig', array(
'title' => 'New event',
'eventForm' => $eventForm->createView()));
}
How to fix this error please? What is the correct function to use?

It appears that you are using Silex, not Symfony 2. Being a very minimalistic framework, silex doesn't give you all the configuration and dependency injection goodies that Symfony does.
The easiest approach to be able to retrieve the application root, would be to define it yourself in bootstrap.php. Simply add something like this at the top:
define('APP_ROOT', __DIR__ . '/../');
Now you can just use the constant in your controller:
public function addEventAction(Request $request, Application $app) {
...
$path = APP_ROOT . '/../web';
...
}

Related

Sharing the same instance of an object: auryn vs. PHP-DI

I am trying to build my first no-framework PHP application and I am following this tutorial.
I am relatively new to some concepts described in the tutorial. Despite this, I decided to use, as Dependency Injector, PHP-DI instead of the suggested one (rdlowrey/auryn).
I have created everything according to the tutorial except for the file Bootstrap.php (and the file Dependencies.php:
<?php declare(strict_types = 1);
require(__DIR__ . '/../vendor/autoload.php');
...
$container = include('Dependencies.php');
$request = $container->make('Http\HttpRequest');
$response = $container->make('Http\HttpResponse');
...
switch ($routeInfo[0]) {
...
case \FastRoute\Dispatcher::FOUND:
$className = $routeInfo[1][0];
$method = $routeInfo[1][1];
$vars = $routeInfo[2];
$class = $container->make($className);
$class->$method($vars); // (**)
break;
}
echo $response->getContent(); // (*)
$class can be only an instance of a Homepage class which has only one method (show()), called in (**):
class Homepage
{
private $request;
private $response;
private $renderer;
public function __construct(
Request $request,
Response $response,
Renderer $renderer
) {
$this->request = $request;
$this->response = $response;
$this->renderer = $renderer;
}
public function show() {
$data = [
'name' => $this->request->getParameter('name', 'stranger'),
];
$html = $this->renderer->render('Homepage', $data);
$this->response->setContent($html); // (***)
}
}
With all that said, the application returns a 200 HTTP response with an empty body [here (*)]
but if I try to print the content of the HTTP response after (***) I get the correct response.
This could mean that there are two different instances of an HttpResponse class. (Is that right?)
By using rdlowrey/auryn, the author of the tutorial, used the method share() to share the same HttpReponse instance among classes, as shown in the "original" Dependencies.php file:
<?php declare(strict_types = 1);
use \Auryn\Injector;
...
$injector = new Injector;
$injector->alias('Http\Response', 'Http\HttpResponse');
$injector->share('Http\HttpResponse');
...
return $injector;
Is there a way to get the same behavior using PHP-DI (with PHP definitions)?
Here's my version of Dependencies.php:
<?php declare(strict_types = 1);
$definitions = [
'Http\Request' => DI\create('Http\HttpRequest')->constructor(
$_GET, $_POST, $_COOKIE, $_FILES, $_SERVER),
'Http\HttpRequest' => function () {
$r = new Http\HttpRequest($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
return $r;
},
'Http\Response' => DI\create('Http\HttpResponse'),
'Twig\Environment' => function () {
$loader = new Twig\Loader\FilesystemLoader(
dirname(__DIR__) . '/templates');
$twig = new Twig\Environment($loader);
return $twig;
},
'Example\Template\TwigRenderer' => function (Twig\Environment $renderer) {
return new Example\Template\TwigRenderer($renderer);
},
'Example\Template\Renderer' => DI\create(
'Example\Template\TwigRenderer')->constructor(
DI\get('Twig\Environment')),
];
$containerBuilder = new DI\ContainerBuilder;
$containerBuilder->addDefinitions($definitions);
$container = $containerBuilder->build();
return $container;
In Bootstrap.php, getting (get()) HttpRequest/HttpResponse instances, instead of making (make()) them, solved the problem.
...
$container = include('Dependencies.php');
$request = $container->get('Http\HttpRequest');
$response = $container->get('Http\HttpResponse');
...
As clearly stated in the documentation:
The make() method works like get() except it will resolve the entry
every time it is called. [..] if the entry is an object, an new instance will be created every time [..]

ZF2 Unit test of login in wierd code

I am new to ZF2 and I want to test the login method in a legacy application. Or introduce Unit tests in old code :).
The code that I have is not done according to the manual; it seems super strange if I compare it to the manual examples or even best practices.
I the login method like this:
http://pastebin.com/ZzvuBcGe
in this case the legacy is that Helper, Carts, Users, Userslogs and Usertests are models .... all of them extend DB.
In the module.config.php I have this code:
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
'AuthService' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$dbTableAuthAdapter = new DbTableAuthAdapter(
$dbAdapter,
'tbl_user',
'USER_LOGIN',
'USER_PASSWORD',
'MD5(?)'
);
$authService = new AuthenticationService();
$authService->setAdapter($dbTableAuthAdapter);
$authService->setStorage(new StorageSession('session'));
return $authService;
},
'Helper' => function ($sm) {
return new Helper($sm);
},
'Users' => function ($sm) {
return new Users($sm);
},
'Carts' => function ($sm) {
return new Carts($sm);
}
...
I know that the DbTableAuthAdapter is deprecated but I have to understand how to modify this in order to change it in the best way possible. I have the feeling if I change this all the User, Carts etc models will crash.
My Unit test is like this for the moment:
<?php namespace ApplicationTest\Controller;
use Application\Controller\LoginController;
use Zend\Stdlib\ArrayUtils;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class LoginControllerTest extends AbstractHttpControllerTestCase
{
protected $traceError = true;
public function setUp()
{
parent::setUp();
// The module configuration should still be applicable for tests.
// You can override configuration here with test case specific values,
// such as sample view templates, path stacks, module_listener_options,
// etc.
$configOverrides = [];
$this->setApplicationConfig(ArrayUtils::merge(
// Grabbing the full application configuration:
include __DIR__ . '/../../../../../config/application.config.php',
$configOverrides
));
}
public function loginCredentialsProvider()
{
return [
['userDev', '12345'],
];
}
/**
* #covers LoginController::loginAction()
* #dataProvider loginCredentialsProvider
* #param $username
* #param $password
*/
public function testLogin($username, $password)
{
// prepare request
//$this->getRequest()
//->setMethod('POST')
//->setPost(new Parameters(array(
//'user_login' => $username,
//'user_password' => $password
//)));
$helperMock = $this->getMockBuilder('Application\Model\Helper')
->disableOriginalConstructor()
->getMock();
$serviceManager = $this->getApplicationServiceLocator();
$serviceManager->setAllowOverride(true);
$serviceManager->setService('Application\Model\Helper', $helperMock);
// send request
$this->dispatch('/login', 'POST', $this->loginCredentialsProvider());
$this->assertEquals('userDev12345', $username . $password);
// $this->markTestIncomplete('login incomplete');
}
/**
* #depends testLogin
*/
public function testLogout()
{
$this->markTestIncomplete('logout incomplete');
}
}
I tried different ways to test but no succes and of course that I get errors:
Zend\ServiceManager\Exception\ServiceNotCreatedException: An exception was raised while creating "Helper"; no instance returned
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:930
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:1057
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:633
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:593
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:525
/project/module/Application/src/Application/Controller/LoginController.php:38
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php:83
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:207
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:116
/project/vendor/zendframework/zendframework/library/Zend/Mvc/DispatchListener.php:113
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:207
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php:313
/project/vendor/zendframework/zendframework/library/Zend/Test/PHPUnit/Controller/AbstractControllerTestCase.php:282
/project/module/Application/test/ApplicationTest/Controller/LoginControllerTest.php:69
/project/vendor/phpunit/phpunit/phpunit:47
Caused by
Zend\ServiceManager\Exception\ServiceNotCreatedException: An exception was raised while creating "Zend\Db\Adapter\Adapter"; no instance returned
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:930
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:1055
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:633
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:593
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:525
/project/module/Application/src/Application/Model/DB.php:17
/project/module/Application/config/module.config.php:1324
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:923
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:1057
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:633
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:593
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:525
/project/module/Application/src/Application/Controller/LoginController.php:38
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php:83
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:207
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:116
/project/vendor/zendframework/zendframework/library/Zend/Mvc/DispatchListener.php:113
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:207
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php:313
/project/vendor/zendframework/zendframework/library/Zend/Test/PHPUnit/Controller/AbstractControllerTestCase.php:282
/project/module/Application/test/ApplicationTest/Controller/LoginControllerTest.php:69
/project/vendor/phpunit/phpunit/phpunit:47
Caused by
PHPUnit_Framework_Error_Notice: Undefined index: db
/project/vendor/zendframework/zendframework/library/Zend/Db/Adapter/AdapterServiceFactory.php:26
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:923
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:1055
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:633
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:593
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:525
/project/module/Application/src/Application/Model/DB.php:17
/project/module/Application/config/module.config.php:1324
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:923
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:1057
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:633
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:593
/project/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:525
/project/module/Application/src/Application/Controller/LoginController.php:38
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php:83
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:207
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:116
/project/vendor/zendframework/zendframework/library/Zend/Mvc/DispatchListener.php:113
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/project/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:207
/project/vendor/zendframework/zendframework/library/Zend/Mvc/Application.php:313
/project/vendor/zendframework/zendframework/library/Zend/Test/PHPUnit/Controller/AbstractControllerTestCase.php:282
/project/module/Application/test/ApplicationTest/Controller/LoginControllerTest.php:69
/project/vendor/phpunit/phpunit/phpunit:47
The issues that I have are first how to get the test to pass with this code? I know that normally you do the test and after that the code but I need a starting point to understand the mess that I have in the application. Second, what is the easy or the best way to modify the "models" to not be a dependency for each method and then pass the test? How to modify the deprecated DbTableAuthAdapter in order not to brake all things?
Like i said I am new to ZF2 and Phpunit and I am stuck over this messy code and I have the best practices in my mind but I don't know how to put them in action in this code. Thank you for all the info that I will receive for this.
LATER EDIT
the solution is to add this line in the test, foreach model:
// access via application object..
$bla = $this->getApplication()->getServiceManager()->get('Tests');
the solution is to add this line in the test, foreach model:
$bla = $this->getApplication()->getServiceManager()->get('Tests');
Thank you i336_ :)

Yii2 testing environment guidelines for extension development [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am developing an Yii 2 public (MIT) extension to change some of the yii\web\View behaviours (minify, combine and many other optimizations).
I can do it easily. But I really want to write as many tests (codeception) as possible for it. This is where I am very confused.
I already have some unit tests (for example: testing a specific minifing, or returning combined minified result). But I would like to test the entire result and the final integration between my extension and the Yii2 web application using it.
I just would like some guidelines for this process:
Should I have a real (complete) app inside my extension for testing purposes? If so, should it be 'installed' inside tests dir?
Would you use functional testing ? (I think so because the View will find files in AssetBundles, combine and minify them, publish the result as a single file and replace the assets' urls by new url (i.e., the optimized asset url) inside the view;
Could you provide some very basic examples/guidelines?
I just would like to highlight that I dont intend you do my testing job, I really want to learn how to do it. This is why I really would be very grateful for any tips.
Thank you so much.
My Own Guidelines
Ok, I've found my way based on tests inside yii2-smarty.
So, these are the guidelines for testing your own Yii2 extension development using phpunit:
1) The tests/bootstrap.php:
// ensure we get report on all possible php errors
error_reporting(-1);
define('YII_ENABLE_ERROR_HANDLER', false);
define('YII_DEBUG', true);
$_SERVER['SCRIPT_NAME'] = '/' . __DIR__;
$_SERVER['SCRIPT_FILENAME'] = __FILE__;
require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
//optionals
Yii::setAlias('#testsBasePathOrWhateverYouWant', __DIR__);
Yii::setAlias('#slinstj/MyExtensionAlias', dirname(__DIR__));
2) Create a tests/TestCase base class extending \PHPUnit_Framework_TestCase:
namespace slinstj\MyExtension\tests;
use yii\di\Container;
/**
* This is the base class for all yii framework unit tests.
*/
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
/**
* Clean up after test.
* By default the application created with [[mockApplication]] will be destroyed.
*/
protected function tearDown()
{
parent::tearDown();
$this->destroyApplication();
}
/**
* Populates Yii::$app with a new application
* The application will be destroyed on tearDown() automatically.
* #param array $config The application configuration, if needed
* #param string $appClass name of the application class to create
*/
protected function mockApplication($config = [], $appClass = '\yii\console\Application')
{
new $appClass(ArrayHelper::merge([
'id' => 'testapp',
'basePath' => __DIR__,
'vendorPath' => dirname(__DIR__) . '/vendor',
], $config));
}
protected function mockWebApplication($config = [], $appClass = '\yii\web\Application')
{
new $appClass(ArrayHelper::merge([
'id' => 'testapp',
'basePath' => __DIR__,
'vendorPath' => dirname(__DIR__) . '/vendor',
'components' => [
'request' => [
'cookieValidationKey' => 'wefJDF8sfdsfSDefwqdxj9oq',
'scriptFile' => __DIR__ .'/index.php',
'scriptUrl' => '/index.php',
],
]
], $config));
}
/**
* Destroys application in Yii::$app by setting it to null.
*/
protected function destroyApplication()
{
Yii::$app = null;
Yii::$container = new Container();
}
protected function debug($data)
{
return fwrite(STDERR, print_r($data, TRUE));
}
}
3) Create your testSomething classes extending TestCase:
namespace slinstj\MyExtension\tests;
use yii\web\AssetManager;
use slinstj\MyExtension\View;
use Yii;
/**
* Generated by PHPUnit_SkeletonGenerator on 2015-10-30 at 17:45:03.
*/
class ViewTest extends TestCase
{
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp()
{
parent::setUp();
$this->mockWebApplication();
}
public function testSomething()
{
$view = $this->mockView();
$content = $view->renderFile('#someAlias/views/index.php', ['data' => 'Hello World!']);
$this->assertEquals(1, preg_match('#something#', $content), 'Html view does not contain "something": ' . $content);
}
//other tests...
/**
* #return View
*/
protected function mockView()
{
return new View([
'someConfig' => 'someValue',
'assetManager' => $this->mockAssetManager(),
]);
}
protected function mockAssetManager()
{
$assetDir = Yii::getAlias('#the/path/to/assets');
if (!is_dir($assetDir)) {
mkdir($assetDir, 0777, true);
}
return new AssetManager([
'basePath' => $assetDir,
'baseUrl' => '/assets',
]);
}
protected function findByRegex($regex, $content, $match = 1)
{
$matches = [];
preg_match($regex, $content, $matches);
return $matches[$match];
}
}
That is all! This code skeleton is highly based in the yii2-smaty/tests code. Hope to help you (and me in further needs).
this approach works, but i had to make some small adjustments:
if you are developing an extension (in /vendor/you/extension directory) and the bootstrap.php file is inside a test-directory, the paths for autoloader and yii base class are most likely wrong. Better is:
require_once(__DIR__ . '/../../../autoload.php');
require_once(__DIR__ . '/../../../yiisoft/yii2/Yii.php');
i have tested an validator class which needed an application object. i have simply created an console application inside the bootstrap file (append to end of file):
$config = require(__DIR__ . '/../../../../config/console.php');
$application = new yii\console\Application($config);

Laravel league/flysystem getting file URL with AWS S3

I am trying to build a file management system in Laravel based on league/flysystem: https://github.com/thephpleague/flysystem
I am using the S3 adapter and I have it working to save the uploaded files using:
$filesystem->write('filename.txt', 'contents');
Now I am stuck on generating the download file URL when using the S3 adapter.
The files are saved correctly in the S3 bucket, I have permissions to access them, I just don't know how to get to the S3 getObjectUrl method through the league/flysystem package.
I have tried:
$contents = $filesystem->read('filename.txt');
but that returns the content of the file.
$contents = $filemanager->listContents();
or
$paths = $filemanager->listPaths();
but they give me the relative paths to my files.
What I need is something like "ht...//[s3-region].amazonaws.com/[bucket]/[dir]/[file]..."
I am using Laravel 5.2 and the code below seemed to work fine.
Storage::cloud()->url('filename');
I'm not sure what the correct way of doing this is with Flysystem, but the underlying S3Client object has a method for doing that. You could do $filesystem->getAdapter()->getClient()->getObjectUrl($bucket, $key);. Of course, building the URL is as trivial as you described, so you don't really need a special method to do it.
When updating to Laravel 5.1 this method no longer supported by the adapter. No in your config you must have the S3_REGION set or you will get a invalid hostname error and secondly I had to use the command as input to create the presignedRequest.
public function getFilePathAttribute($value)
{
$disk = Storage::disk('s3');
if ($disk->exists($value)) {
$command = $disk->getDriver()->getAdapter()->getClient()->getCommand('GetObject', [
'Bucket' => Config::get('filesystems.disks.s3.bucket'),
'Key' => $value,
'ResponseContentDisposition' => 'attachment;'
]);
$request = $disk->getDriver()->getAdapter()->getClient()->createPresignedRequest($command, '+5 minutes');
return (string) $request->getUri();
}
return $value;
}
Maybe I'm a little late to this question, but here's a way to use Laravel 5's built-in Filesystem.
I created a Manager class that extends Laravel's FilesystemManager to handle the public url retrieval:
class FilesystemPublicUrlManager extends FilesystemManager
{
public function publicUrl($name = null, $object_path = '')
{
$name = $name ?: $this->getDefaultDriver();
$config = $this->getConfig($name);
return $this->{'get' . ucfirst($config['driver']) . 'PublicUrl'}($config, $object_path);
}
public function getLocalPublicUrl($config, $object_path = '')
{
return URL::to('/public') . $object_path;
}
public function getS3PublicUrl($config, $object_path = '')
{
$config += ['version' => 'latest'];
if ($config['key'] && $config['secret']) {
$config['credentials'] = Arr::only($config, ['key', 'secret']);
}
return (new S3Client($config))->getObjectUrl($config['bucket'], $object_path);
}
}
Then, I added this class to the AppServiceProvider under the register method so it has access to the current app instance:
$this->app->singleton('filesystemPublicUrl', function () {
return new FilesystemPublicUrlManager($this->app);
});
Finally, for easy static access, I created a Facade class:
use Illuminate\Support\Facades\Facade;
class StorageUrl extends Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor()
{
return 'filesystemPublicUrl';
}
}
Now, I can easily get the public url for my public objects on my local and s3 filesystems (note that I didn't add anything for ftp or rackspace in the FilesystemPublicUrlManager):
$s3Url = StorageUrl::publicUrl('s3') //using the s3 driver
$localUrl = StorageUrl::publicUrl('local') //using the local driver
$defaultUrl = StorageUrl::publicUrl() //default driver
$objectUrl = StorageUrl::publicUrl('s3', '/path/to/object');
Another form of Storage::cloud():
/** #var FilesystemAdapter $disk */
$s3 = Storage::disk('s3');
return $s3->url($path);
Using presigned request S3:
public function getFileUrl($key) {
$s3 = Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$bucket = env('AWS_BUCKET');
$command = $client->getCommand('GetObject', [
'Bucket' => $bucket,
'Key' => $key
]);
$request = $client->createPresignedRequest($command, '+20 minutes');
return (string) $request->getUri();
}
For private cloud use this
Storage::disk('s3')->temporaryUrl($path);

Dynamic route prefix in Symfony2

I am creating a SaaS with symfony2 providing private websites.
What I am trying to do is to let people access the website this way :
http://www.mydomain.com/w/{website_name}
Here is the routing configuration i am using :
websites:
resource: "#MyBundle/Resources/config/routing.yml"
prefix: /w/{website_name}
The problem is that when I try to access, for exemple, http://www.mydomain.com/w/chucknorris I am getting the error :
An exception has been thrown during the rendering of a template ("Some
mandatory parameters are missing ("website_name") to generate a URL
for route "websites_homepage".") in
"MyBundle:Publication:publicationsList.html.twig".
What I understood is that my route configuration is working well but when I am calling the router to generates url in the website it isn't aware of the "context" {website_name} url parameter.
One solution I've imagined is to find a way to automatically and seemlessly inject this parameter when it's set in the context.
Until now all I've been able to do is to create a service to get this parameter this way :
public function __construct(Registry $doctrine, ContainerInterface $container) {
$website_name = $container->get('request')->get("website_name");
if (!empty($website_name)) {
$repository = $doctrine->getManager()->getRepository('MyBundle:website');
$website = $repository->findOneByDomain($website_name);
if ($website) {
$this->website = $website;
} else {
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException();
}
} else {
$this->isPortal = true;
}
}
My question is : How do I inject that argument to all url generated to avoid getting the error of parameter missing and without having to specify it manualy everytime I call the router in controllers or twig ? (I guess it's something about request event but i have no clue on how to do it and especialy how to do it according to symfony2 good usages)
UPDATE
Here is the listener i created base on locallistener provided by symfony:
<?php
class WebsiteNameRouteEventListener implements EventSubscriberInterface {
private $router;
public function __construct(RequestContextAwareInterface $router = null) {
$this->router = $router;
}
public function onKernelResponse(FilterResponseEvent $event) {
$request = $event->getRequest();
$this->setWebsiteName($request);
}
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
$this->setWebsiteName($request);
}
public static function getSubscribedEvents() {
return array(
// must be registered after the Router to have access to the _locale
KernelEvents::REQUEST => array(array('onKernelRequest', 16)),
KernelEvents::RESPONSE => 'onKernelResponse',
);
}
private function setWebsiteName(Request $request) {
if (null !== $this->router) {
echo "NEW CODE IN ACTION";die();
$this->router->getContext()->setParameter('website_name', $request->attributes->get("website_name"));
}
}
}
But i am still getting this error :
An exception has been thrown during the rendering of a template ("Some
mandatory parameters are missing ("website_name") to generate a URL
for route "homepage".") in
"MyBundle:Publication:publicationsList.html.twig". 500 Internal
Server Error - Twig_Error_Runtime 1 linked Exception:
MissingMandatoryParametersException ยป
Without my echo "...."; die() being executed so i guess twig is not firing the event i am listening on when it execute the path(routename) code.
Any idea ?
You could use the router context.
$this->router->getContext()->setParameter('website_name', $website_name);
See this file: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php

Categories