Мне нужно создать некоторый контент JSON в контроллере, и мне нужно получить полный URL-адрес загруженного изображения, расположенного здесь: /web/uploads/myimage.jpg
.
Как я могу получить полный URL-адрес?
http://www.mywebsite.com/uploads/myimage.jpg
Вы можете сгенерировать URL-адрес из объекта запроса:
$baseurl = $request->getScheme() . '://' . $request->getHttpHost() . $request->getBasePath();
Вы можете сделать расширение ветки, которое сокращает часть /web
вашего пути и использует запрос для генерации базового url.
см. Symfony\Component\Routing\Generator\UrlGenerator::doGenerate
для более надежной реализации.
Кроме того, Twig имеет доступ к запросу от app.request
.
Вы можете использовать это в контроллере:
$this->getRequest()->getUriForPath('/uploads/myimage.jpg');
EDIT: Этот метод также включает в себя app.php
и app_dev.php
к URL-адресу. Значение будет работать только в том случае, если включена функция перезаписи URL!
Вы можете использовать службу templating.helper.assets
.
Сначала определите свой базовый URL-адрес активов:
# app/config/config.yml
framework:
templating:
assets_base_url: "http://www.mywebsite.com/"
Затем просто вызовите службу из своего контроллера, команды или где бы вы ни были:
<?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();
}
}
templating.helper.assets
доступен только при включенном шаблонизаторе php
.
Если вы хотите получить этот URL-адрес из шаблона ветки, используйте:
{{ app.request.uriForPath('/uploads/myimage.jpg') }}
asset
дает мне полный путь, но не URI (не абсолютное)
С Symfony 2.1 вы можете использовать:
$request->getSchemeAndHttpHost(). '/uploads/myimage.jpg';
Примечание. Это решение имеет преимущество для работы в и средах DEV и PROD.
Лучшим решением было бы ИМХО посмотреть Twig
реализацию asset
, которую вы можете найти в:
\Symfony\Bundle\TwigBundle\Extension\AssetsExtension
в методе:
public function getAssetUrl($path, $packageName = null, $absolute = false, $version = null)
который в основном использует службу templating.helper.assets
, похожую на @iamdto:
$url = $this->container->get('templating.helper.assets')->getUrl($path, $packageName, $version);
Или непосредственно используйте службу или класс AssetsExtension
соответственно.
app.request.uriForPath('/uploads/myimage.jpg') | replace({'/app_dev.php': ''})
это позволяет избежать проблемы с app_dev.php
Это решение не требует добавления какой-либо переменной или параметра в конфигурацию и является той же функцией, которая используется Twig для {{ absolute_url() }}
public function yourAction(AssetsHelper $assetsHelper, HttpFoundationExtension $httpExtension)
{
$assetsPath = $assetsHelper->getUrl('/img/test.jpg');
$assetFullUrl = $httpExtension->generateAbsoluteUrl($assetPath);
}
Полный URL вашего актива будет на $assetFullUrl
Метод app.request.uriForPath()
дает абсолютный URL-адрес из пути. Помощник asset()
дает путь к активу.
{{ app.request.uriForPath(asset('bundles/mybundle/images/name.png')) }}
Важно иметь как для случая, когда приложение не находится в корне домена, например:
http://mydomain.com/myapp/app.php
Это работает для меня
$baseurl = $this->getRequest()->getScheme() . '://' . $this->getRequest()->getHttpHost() . $this->getRequest()->getBasePath();
Решение @Al Jey отлично работает с Assetic (проверено на Symfony 2.6)
{% image '@AcmeBundle/Resources/public/images/myimage.jpg' %}
<img src="{{ app.request.uriForPath(asset_url) }}">
{% endimage %}
Вы также можете внедрить Packages
непосредственно в ваш сервис.
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);
}
}
Если у вас включена автопроводка, вам не нужно ничего настраивать в вашем services.yml
, иначе что-то вроде:
services:
App\Service\SomeClass:
class: App\Service\SomeClass
arguments: ['@assets.packages']
В моем случае рабочим решением для получения абсолютного URL было:
$request->getUri('/web/uploads/myimage.jpg.');
В Symfony 4 и, возможно, до этого, в действиях контроллера вы можете просто использовать generateUrl()
с флагом ABSOLUTE_URL
следующим образом:
$this->generateUrl(
'my_route', [], UrlGeneratorInterface::ABSOLUTE_URL
);
Для Twig это тоже должно работать (проще):
{{ url(asset('...')) }}
Вы можете получить URL-адрес сайта, чтобы указать веб-папку, используя следующий код
$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;
Рабочее решение Symfony 3.3 +
# app/config/config.yml
parameters:
...
base_url: 'http://mywebsite.com'
Чтобы получить его в действии вашего контроллера:
$baseUrl = $this->getParameter('base_url');
Теперь вы можете добавить свое изображение к нему e-g: $baseUrl . '/uploads/' . $image
или, если хотите, вы можете определить URL базы данных загруженных ресурсов в config.yml и получить доступ к ней в действии контроллера.
Самое лучшее в этом решении - это возможность предварительно определить его для разных сред, например: в config.yml
, config_dev.yml
и config_test.yml
, поэтому, когда вы перемещаете проект между разными средами, вам не нужно измените его, как он уже там.
Ура!
$request = $this->getRequest();
getRequest()
устарела в пользу внедрения объектаRequest