53

I need to generate some JSON content in controller and I need to get the full URL to an uploaded image situated here : /web/uploads/myimage.jpg.

How can I get the full url of it?

http://www.mywebsite.com/uploads/myimage.jpg

i.am.michiel
  • 10,281
  • 7
  • 50
  • 86

16 Answers16

59

You can generate the url from the request object:

$baseurl = $request->getScheme() . '://' . $request->getHttpHost() . $request->getBasePath();

You could make a twig extension that cuts the /web part of your path and uses the request to generate the base url.

see Symfony\Component\Routing\Generator\UrlGenerator::doGenerate for a more solid implementation.

Also, Twig has access to the request from app.request.

solarc
  • 5,638
  • 2
  • 40
  • 51
47

You can use this in Controller:

$this->getRequest()->getUriForPath('/uploads/myimage.jpg');

EDIT : This method also includes the app.php and app_dev.php to the url. Meaning this will only work in production when url-rewriting is enabled!

i.am.michiel
  • 10,281
  • 7
  • 50
  • 86
smatyas
  • 745
  • 6
  • 18
  • 2
    To me, this solution worked in the development environment as well. – RayOnAir Feb 06 '13 at 14:59
  • 3
    @RayOnAir, the problem is that if you're using the `app_dev.php` url, an asset will be appended to this url, e.g. `http://bla.com/app_dev.php/uploads/test.png` - which doesn't exist. – Prisoner Nov 14 '13 at 14:15
  • 2
    Not working in Symfony 2.5. This code returns URL with the app.php or app_dev.php included in the path. By the way it can be used, but you got to use str_replace() to produce legal URL. – Todor Todorov Jul 14 '14 at 07:23
  • THX. Working fine in Symfony 3.4.13 . $request->getUriForPath('/uploads/myimage.jpg'); – medskill Jan 20 '19 at 23:20
  • Works in Symfony 5.2 as well. – Boolean_Type Mar 03 '23 at 16:40
29

You can use the templating.helper.assets service.

First define your assets base URL :

# app/config/config.yml
framework:
    templating:
        assets_base_url: "http://www.mywebsite.com/"

Then just call the service from within your controller, command or wherever you are :

<?php

// src/Acme/Bundle/DemoBundle/Controller/DemoController.php

namespace Acme\Bundle\DemoBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DemoController extends Controller
{
    public function indexAction()
    {
        $myAssetUrl = $this
            ->get('templating.helper.assets')
            ->getUrl('bundles/acmedemo/js/main.js', $packageName = null)
        ;

        // $myAssetUrl is "http://www.mywebsite.com/bundles/acmedemo/js/main.js"

        return array();
    }
}
iamdto
  • 1,372
  • 11
  • 23
  • This is a great solution, as it is the most flexible one! You can put your assets anywhere you want (i.e. a CDN) in the future and only change the assets_base_url value in your config file. – RayOnAir Mar 07 '14 at 15:06
  • Keep in mind that `templating.helper.assets` is only available when `php` templating engine is enabled. – Mantas Apr 04 '16 at 12:59
  • with Symfony 3.0+, the equivalent service to fetch asset information within PHP is `assets.packages`. – Alister Bulman Mar 05 '18 at 21:44
14

If you want to get this url from within a twig template use:

{{ app.request.uriForPath('/uploads/myimage.jpg') }}
Eugene Kuzmenko
  • 947
  • 9
  • 11
12

As of Symfony 2.1 you can use:

$request->getSchemeAndHttpHost().'/uploads/myimage.jpg';

Note: This solution has the advantage to work in both DEV and PROD environments.

COil
  • 7,201
  • 2
  • 50
  • 98
10

The best solution would be IMHO to look at Twig's implementation of asset, which you can find in:

\Symfony\Bundle\TwigBundle\Extension\AssetsExtension

in the method:

public function getAssetUrl($path, $packageName = null, $absolute = false, $version = null)

which basically uses the templating.helper.assets service similar to @iamdto's answer:

$url = $this->container->get('templating.helper.assets')->getUrl($path, $packageName, $version);

Or directly use the AssetsExtension service or class respectively.

stryba
  • 1,979
  • 13
  • 19
  • 1
    Yep, using the extension helper of the "asset" twig function is the most secure way. Thanks !! – Chicna Oct 29 '14 at 10:08
4
app.request.uriForPath('/uploads/myimage.jpg') | replace({'/app_dev.php': ''})

this avoid the problem of app_dev.php

Giuseppe Garassino
  • 2,272
  • 1
  • 27
  • 47
Ignacio
  • 331
  • 6
  • 15
  • The questioner asked for controller code, this is twig. If you don't want app_dev.php added to your URLs you should simply use the prod controller (app.php or simply "/" if it's configured right). – flu Oct 18 '13 at 09:38
  • thanks Nacho, very useful as quick and dirty test ;) – nicolallias Apr 20 '16 at 15:35
3

This solution doesn't require adding any variable or parameter on config and is the same function that is used by Twig for {{ absolute_url() }}

public function yourAction(AssetsHelper $assetsHelper, HttpFoundationExtension $httpExtension)
{
    $assetsPath = $assetsHelper->getUrl('/img/test.jpg');
    $assetFullUrl = $httpExtension->generateAbsoluteUrl($assetPath);
}

The complete url of your asset will be on $assetFullUrl

Rui Cardoso
  • 739
  • 6
  • 18
2

This one works for me

$baseurl = $this->getRequest()->getScheme() . '://' . $this->getRequest()->getHttpHost() . $this->getRequest()->getBasePath();
debianek
  • 589
  • 1
  • 9
  • 30
2

Method app.request.uriForPath() gives an absolute URL from a path. Helper asset() gives the path of an asset.

{{ app.request.uriForPath(asset('bundles/mybundle/images/name.png')) }}

It's important to have both for the case where the application is not at the root of the domain, for eg:

http://mydomain.com/myapp/app.php
Quentin
  • 2,529
  • 2
  • 26
  • 32
2

For CDNs, you can also inject the Packages directly into your service.

First the asset base url in config.yml:

framework:
    assets:
        base_url:
            - 'http://cdn.mysite.com'

Then the fun part:

namespace App\Service;

use Symfony\Component\Asset\Packages;

class SomeClass
{
    private $packages;

    public function __construct(Packages $packages)
    {
        $this->packages = $packages;
    }

    public function proxyToAssetUrl(string $path): string
    {
        return $this->packages->getUrl($path);
    }
}

If you have autowiring enabled then you won't need to configure anything in your services.yml, otherwise something like:

services:
    App\Service\SomeClass:
        class: App\Service\SomeClass
        arguments: ['@assets.packages']
Yes Barry
  • 9,514
  • 5
  • 50
  • 69
1

The @Al Jey solution works fine with Assetic (tested on Symfony 2.6)

{% image '@AcmeBundle/Resources/public/images/myimage.jpg' %} 
    <img src="{{ app.request.uriForPath(asset_url) }}"> 
{% endimage %}
ke20
  • 665
  • 4
  • 19
0

Working solution in Symfony 3.3+

# app/config/config.yml
parameters:
    ...
    base_url: 'http://mywebsite.com'

To get it in your controller action:

$baseUrl = $this->getParameter('base_url');

You can now append your image to it e-g: $baseUrl . '/uploads/' . $image or if you like you can define uploaded assets base url in config.yml and access it in controller action.

Best thing about this solution would be the ability to pre-define it for different environments e-g: in config.yml, config_dev.yml and config_test.yml so when you move your project between different environments, you don't have to change it as it's already there..

Cheers!

Muzafar Ali
  • 1,362
  • 1
  • 12
  • 18
0

You can use the function getSchemeAndHttpHost() for Gets the scheme and HTTP host and use the function getBasePath() to get the root path from which this request is executed

$request->getSchemeAndHttpHost().$request->getBasePath()."/uploads/myimage.jpg"

This method works fine for the app.php and app_dev.php.

pedram shabani
  • 1,654
  • 2
  • 20
  • 30
0

You can use \Symfony\Bridge\Twig\Extension\HttpFoundationExtension $httpFoundationExtension->generateAbsoluteUrl('url');

Service ID is twig.extension.httpfoundation if you need it.

Erik
  • 303
  • 1
  • 3
  • 12
-1

You can get site url i.e point to web folder by using the following code

$protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';

    $hostName = $request->server->get('HTTP_HOST');

    $baseDirectory = "";

    if(!empty($this->container->get('router')->getContext()->getBaseUrl())){

        $baseDirectory = str_replace('app_dev.php', '', $this->container->get('router')->getContext()->getBaseUrl());
    }

    $rootUrl = $protocol.$hostName.$baseDirectory;
Ashok
  • 1
  • 2