Since Symfony-2.7 the asset's method 3rd argument (a boolean that indicates whether to generate an absolute url) was deprecated.
From sources:
#trigger_error('Generating absolute URLs with the Twig asset() function was deprecated in 2.7 and will be removed in 3.0. Please use absolute_url() instead.', E_USER_DEPRECATED);
So the official way to generate it in a Symfony-3.0 compatible way became:
{{ absolute_url(asset('some/asset.css')) }}
The problem though is that the HttpFoundationExtension that provides the absolute_url relies on the "request stack" which is empty in case of non-http request.
So it returns the original path without any transformations:
if (!$request = $this->requestStack->getMasterRequest()) {
return $path;
}
https://github.com/symfony/symfony/blob/2.7/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php#L59
So the question is - how to generate a full url in a CLI-based application?
An important note: http://symfony.com/doc/current/cookbook/console/sending_emails.html this advice is not actual when you use absolute_url helper.
Try pushing dummy request object to request_stack service, also configure request context in parameters.yml as said in sending_emails.html
$request = new Request();
// if you use locales
$request->setLocale("en");
// to be able to render twig asset absolute paths we have to inject dummy request
$container->enterScope('request');
$container->set('request', $request, 'request');
$container->get('request_stack')->push($request);
Related
I have a controller has an action that looks something like this:
/**
* #Route("/my_route_path", name="my_route_name")
*/
public function doSomethingAction(Request $request)
{
$myPath = $request->getScheme().'://'.$request->getHttpHost().''.$request->getBasePath();
$data = file_get_contents($myPath. '/data_folder/data.json');
return $this->render('#Entry/my_template.html.twig', array(
'data' => json_decode($data, true)
));
}
And I create a functional test for this controller like this:
/** #test */
public function doSomething_should_success()
{
$client = static::createClient();
$crawler = $client->request('GET', '/my_route_path');
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
But I can't run the functional test I still get : Failed asserting that 500 is identical to 200
So, after I checked the test.log file I find this error : file_get_contents(http://localhost/data_folder/data.json) : failed to open stream
As now the problem is comming from $request->getBasePath() because always contain empty string but the expected behaviour is return PATH_TO_MY_PROJECT_FOLDER\web in my case must return projects\web_apps\MY_PROJECT_FOLDER_NAME\web
So, the simplified question: why the request object always contain an empty basePath string in the unit test but it works very well on the browser.
The Request object helps you handle the request of a client, that is something like GET /my_route_path plus lots of headers and a server that is directed at.
The web server passes those information on to php and symfony, and symfony will turn this into a Request object. Symfony has usually one entry point, which is public/index.php (symfony 4) or web/app.php (symfony 3) which is assumed to be / or possibly /basePath/ (the basepath will be communicated by the web server and handled by Symfony).
Symfony will generate a Request object, where the basepath is essentially abstracted away, and whenever you generate a url (via Controller::generateUrl) the base path is taken into account. that's why the basepath is important for Requests.
This is actually described pretty well in the comments of the Request's functions:
getBasePath vs getPathInfo.
However, this only concerns the public facing URLs and doesn't have anything to do with how you structure your project and where that project is located, because that's completely irrelevant to the Request (separation of concerns and stuff).
So I guess, you are actually looking for the root directory of your project.
To find the location of your project dir, there is the very base version, where you directly use the PHP magic var __DIR__ which contains the directory the current script file is in, and you can navigate from there. since controllers are usually located such that their path is projectdir/src/Controller/TheController.php a __DIR__.'/../.. would give you the projectdir. However, that's not really clean. The better version:
Depending on the symfony version you're using, you should retrieve the project dir via the ParameterBagInterface (symfony 4)
function doSomethingAction(ParameterBagInterface $params) {
$projectDir = $params->get('kernel.project_dir');
}
or via the container (symfony 3) see also: new in symfony 3.3: A simpler way to get the project root directory
function doSomethingAction() {
$projectDir = $this->getParameter('kernel.project_dir');
}
In my case I had to inyect RequestStack $stackand access the main request, after that my "BasePath" has value. This is because I where in a subrequest and I had to access to the top level of the request.
This post helped me to understood: Symfony2 - get main request's current route in twig partial/subrequest
/**
* #Route("/myroute", name="myroute")
*/
public function myroute(RequestStack $stack)
{
$request = $stack->getMainRequest();
$route = $request->getPathInfo();
}
I don't understand the semantics of the Symfony Routing Component's API.
From the first code example on the Routing Component documentation page:
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match('/foo');
Why is the hostname and HTTP method passed in via $context and the path via a parameter to match()? Or is it? There is also a path parameter in the RequestContext constructor.
One gets the impression match() is supposed to be called multiple times with different paths within one request, which I can't imagine would ever happen.
After integrating the Routing Component into my application, I now have a hunch why
it was done like that.
Most of the properties of the RequestContext - method, request body, get parameters - can be used without modification, but depending on the desired path structure and server configuration (rewrite rules, etc.) there are multiple ways in which the path needs to be preprocessed.
This doesn't explain why the path is passed to the match() function and the request object is passed to the constructor, but it does explain why they are passed in separately.
I want to upgrade from ZF2 to ZF3 right now and has the following problem with using URL parameter in my PhpRenderer.
In ZF2 I use the HelperPluginManager to get Application, then the MvcEvent and finally the routeMatch:
$routeMatch = $this
->getHelperPluginManager()
->getServiceLocator()
->get('Application')
->getMvcEvent()
->getRouteMatch();
$parameterAction = $routeMatch->getParam('action');
In ZF3 there is a deprecation warning with using the getServiceLocator() (which makes sense, because it only returns the creationContext from the ServiceManager). I want to find a way not trigger the warning.
Configure the Application as a factory-using class (using \Zend\Mvc\Service\ApplicationFactory::class) also not works, because:
Zend\View\HelperPluginManager can only create instances of Zend\View\Helper\HelperInterface and/or callables.
Is there any way to get the Application context in my template (or better even the parameters of the URL)?
Your question title is "ZF3: Read out url parameter in PhpRenderer" while inside your question you asked another one.
You can get this in any controller (get URL parameters in ZF3):
$URLparam = (string)$this->params()->fromQuery('parameter', '');
For routeMatch, if you have a MvcEvent just use;
$event->getRouteMatch()
If you have container;
$container->getApplication()->getMvcEvent()->getRouteMatch();
If you want to access routeMatch in view there's no way except view helper like tasmaniski/zend-current-route
I'm trying to delete a resource using ZF1 rest client
$this->restClient = new Zend_Rest_Client('https://myurl.com');
$response = $this->restClient->delete('/service/'.$this->uuid.'.json?api_key='.$this->apikey);
but I get an error:
Path "/service/v-2149d050-c64b-0131-33b0-1231390c0c78.json?api_key=a-9a136a00-b340-0131-2662-1231390c0c78" is not a valid HTTP path
the web service documentation simply says to use
DELETE https://myurl.com/service/YOUR_UUID.json?api_key=YOUR_API_KEY
any idea on how to use this class?
thanks
DELETE https://myurl.com/service/YOUR_UUID.json?api_key=YOUR_API_KEY
That is not the path only, but a full URI. It breaks down to:
Path: service/YOUR_UUID.json
Query-Info: api_key=YOUR_API_KEY
For Zend rest client, you need to call one function per each parameter, and a parameter can not be named as a standard HTTP verb:
$client = new Zend_Rest_Client('https://exeample.com');
$client->api_key(YOUR_API_KEY);
$response = $client->restClient->delete('/service/'.$this->uuid.'.json);
For more information please see the Request Arguments section in the vendor documentation on how to pass arguments with your request.
I am very new to silex, but have experience with Java based MVC frameworks.
The problem I have seems to be how to accept certain special characters in URL arguments.
I have a controller defined as such:
$app->get('/editPage/{fileName}', function ($fileName) use ($app,$action) {
return $app['twig']->render('edit.twig.html',$action->editPage($fileName));
});
and this works great for urls like:
/myapp/editPage/file.html
/myapp/editPage/file-2.html
but if I pass an encodes "/" or %2F, the route is not picked up, and I get a 404.
1. /myapp/editPage/folder%2Ffile.html
The mod_rewrites rules should route any non-existent file paths to the index.php where silex is defined, so I am not sure what is happening.
I just need a way to capture values with "/" for this particular page. There are no conflicting childpages, so if there is a way to wildcard the path "/editPage/{.*|filename}/" or something obvious I am missing.
You can use assert to change the regex that is used to match the variable. If you want it to match anything, pass a very lenient regex.
eg.
$app = new \Silex\Application();
$app->get('/file/{filename}', function ($filename) {
die(var_dump($filename));
})->assert('filename', '.*');
$app->run();
These requests
GET /file/a%2fb%2fc.txt
GET /file/a/b/c.txt
both yield
string 'a/b/c.txt' (length=9)
It's not an issue with Silex but with Apache.
Apache rejects by design encoded slashes as part of the URI for security purposes. See this answer: https://stackoverflow.com/a/12993237/358813
As a workaround passing the value inside a query string is completely fine:
http://example.com/?file=%2Fpath%2Fto%2Ffile will work, provided you configure Silex accordingly.
In addition to #tacone answer's, here's how I configured Silex to make it work.
I guess it's not the prettiest solution however...
The URL called should be /get/?url=<url encoded>
$siController->get('/get/', function(Application $app, $url){
/** #var SocialIdentifier $si */
$si = $app['social_identifier.social_identifier'];
$result = $si->get($url);
return $app->json($result, 200);
})
->value('url', $_GET['url']);