【问题标题】:How to display the current picture above the upload field in SonataAdminBundle?如何在 SonataAdminBundle 的上传字段上方显示当前图片?
【发布时间】:2012-07-07 03:40:26
【问题描述】:

我正在使用 SonataAdminBundle(使用 Doctrine2 ORM)并且我已经成功地向我的图片模型添加了文件上传功能。

我想在 ShowEdit 页面上,在相关表单字段上方显示一个简单的 <img src="{{ picture.url }} alt="{{ picture.title }} /> 标签(前提是正在编辑的图片是当然不是新的),以便用户可以看到当前照片,并决定是否更改它。

经过数小时的研究,我一直无法弄清楚该怎么做。我想我需要覆盖一些模板,但我有点迷茫...... 有人可以给我一个提示吗?

谢谢!

这是我的 PictureAdmin 类的相关部分。

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->add('category', NULL, ['label' => 'Catégorie'])
        ->add('title', NULL, ['label' => 'Titre'])
        ->add('file', 'file', ['required' => false, 'label' => 'Fichier']) // Add picture near this field
        ->add('creation_date', NULL, ['label' => 'Date d\'ajout'])
        ->add('visible', NULL, ['required' => false, 'label' => 'Visible'])
        ->add('position', NULL, ['label' => 'Position']);
}

protected function configureShowFields(ShowMapper $showMapper)
{
    $showMapper
        ->add('id', NULL, ['label' => 'ID'])
        ->add('category', NULL, ['label' => 'Catégorie'])
        ->add('title', NULL, ['label' => 'Titre'])
        ->add('slug', NULL, ['label' => 'Titre (URL)'])
        ->add('creation_date', NULL, ['label' => 'Date d\'ajout'])
        ->add('visible', NULL, ['label' => 'Visible'])
        ->add('position', NULL, ['label' => 'Position']);
        // Add picture somewhere
}

【问题讨论】:

标签: php file-upload symfony symfony-sonata


【解决方案1】:

我已设法将图像放在编辑表单中的字段上方。但我的解决方案有点具体,因为我使用Vich Uploader Bundle 来处理上传,所以感谢捆绑助手,图片 url 的生成稍微容易了一些。

让我们看一下我的示例,电影实体中的电影海报字段。 这是我的管理课程的一部分:

//MyCompany/MyBundle/Admin/FilmAdmin.php

class FilmAdmin extends Admin {

protected function configureFormFields(FormMapper $formMapper)
{
 $formMapper
     ->add('title')
 ....
     ->add('poster', 'mybundle_admin_image', array(
                'required' => false,
                ))
}

mybundle_admin_image 由自定义字段类型处理,它只是文件类型的子类型,通过将其设置为 getParent 方法:(不要忘记将您的类型类注册为服务)

//MyCompany/MyBundle/Form/Type/MyBundleAdminImageType.php

public function getParent()
{
    return 'file';
}

然后我有一个扩展 Sonata 的默认样式的模板,我将它包含在管理类中:

//MyCompany/MyBundle/Admin/FilmAdmin.php

public function getFormTheme() {
    return array('MyCompanyMyBundle:Form:mycompany_admin_fields.html.twig');
}

最后我有一个扩展基本文件类型的自定义图像类型块:

//MyCompany/MyBundle/Resources/views/Form/mycompany_admin_fields.html.twig

{% block mybundle_admin_image_widget %}
{% spaceless %}
    {% set subject =  form.parent.vars.value %}
    {% if subject.id and attribute(subject, name) %}
        <a href="{{ asset(vich_uploader_asset(subject, name)) }}" target="_blank">
            <img src="{{ asset(vich_uploader_asset(subject, name)) }}" width="200" />
        </a><br/>
    {% endif %}
    {% set type = type|default('file') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock %}

这会导致上传字段上方显示 200 像素宽的图像预览(如果存在),链接到在新标签中打开的完整尺寸版本。您可以根据需要自定义它,例如添加灯箱插件。

【讨论】:

    【解决方案2】:

    您可以通过助手(FormMapper->setHelps)或通过 FormMapper 上的“帮助”选项在编辑页面上轻松完成此操作

    protected function configureFormFields(FormMapper $formMapper) {
        $options = array('required' => false);
        if (($subject = $this->getSubject()) && $subject->getPhoto()) {
            $path = $subject->getPhotoWebPath();
            $options['help'] = '<img src="' . $path . '" />';
        }
    
        $formMapper
            ->add('title')
            ->add('description')
            ->add('createdAt', null, array('data' => new \DateTime()))
            ->add('photoFile', 'file', $options)
        ;
    }
    

    【讨论】:

    • 这在使用 PictureAdmin 类时非常有用,但是当 PictureAdmin 嵌入到另一个管理类中时,任何想法如何使它工作,例如使用来自PageAdmin::configureFormFields()$formMapper-&gt;add('linkedPicture', 'sonata_type_admin')
    • @caponica 你知道怎么做...??我也陷入了同样的境地..
    • 是的,我搞定了。自从我查看代码以来已经有一段时间了,但是您基本上必须检测何时嵌入该字段,然后在 ImageAdmin 类中使用 pastebin.com/rvh65viG 之类的东西
    【解决方案3】:

    您可以在显示页面上轻松执行此操作 通过模板属性传递$showmapper

    ->add('picture', NULL, array(
        'template' => 'MyProjectBundle:Project:mytemplate.html.twig'
    );
    

    在您的模板中,您将获得当前对象,因此您可以调用 get 方法并拉取图像路径

    <th>{% block name %}{{ admin.trans(field_description.label) }}{% endblock %}</th>
    <td>
        <img src="{{ object.getFile }}" title="{{ object.getTitle }}" />
        </br>
        {% block field %}{{ value|nl2br }}{% endblock %}
    </td>
    

    要在编辑模式下显示图像,您必须覆盖 fileType 或者您必须在 fileType 之上创建自己的 customType

    还有一些具有这种功能的捆绑包 看看这个GenemuFormBundle

    【讨论】:

    • 这适用于显示页面,但有没有办法根据问题将图像放在字段上方?
    【解决方案4】:

    Symfony3 解决方案

    @kkochanski 的答案是迄今为止我发现的最干净的方法。这里是移植到 Symfony3 的版本。我还修复了一些错误。

    为您的新表单类型创建一个新模板image.html.twig(完整路径:src/AppBundle/Resources/views/Form/image.html.twig):

    {% block image_widget %}
        {% spaceless %}
            {% set type = type|default('file') %}
            <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
            {% if image_web_path is not empty %}
                <img src="{{ image_web_path }}" alt="image_photo"/>
            {% endif %}
        {% endspaceless %}
    {% endblock %}
    

    在您的config.yml 中注册新的表单类型模板:

    twig:
        form_themes:
            - AppBundle::Form/image.html.twig
    

    创建一个新的表单类型并将其保存为ImageType.php(完整路径:src/AppBundle/Form/Type/ImageType.php):

    <?php
    
    namespace AppBundle\Form\Type;
    
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormBuilderInterface;
    
    /**
     * Class ImageType
     *
     * @package AppBundle\Form\Type
    */
    class ImageType extends AbstractType
    {
        /**
         * @return string
         */
        public function getParent()
        {
            return 'file';
        }
    
        /**
         * @return string
         */
        public function getName()
        {
            return 'image';
        }
    
        /**
         * @param OptionsResolver $resolver
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'image_web_path' => ''
            ));
        }
    
        /**
         * @param FormView $view
         * @param FormInterface $form
         * @param array $options
         */
        public function buildView(FormView $view, FormInterface $form, array $options)
        {
            $view->vars['image_web_path'] = $options['image_web_path'];
        }
    
        /**
         * @param FormBuilderInterface $builder
         * @param array $options
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->setAttribute('image_web_path', $options['image_web_path'])
            ;
        }
    }
    

    如果你这样做了。您可以在实体管理类中导入新的ImageType

    use AppBundle\Form\Type\ImageType
    

    然后,最后在configureFormFields 中使用不带任何 inline-html 或样板代码的新表单类型:

    $formMapper
        ->add('imageFile', ImageType::class, ['image_web_path' => $image->getImagePath()])
    ;
    

    您必须调用自己的方法,而不是 $image-&gt;getImagePath(),该方法将 url 返回到您的图像。

    截图

    使用奏鸣曲管理创建一个新的图像实体:

    使用奏鸣曲管理员编辑图像实体:

    【讨论】:

    • 我有 Symfony 3.2 的问题:无法加载类型“文件”500 内部服务器错误 - InvalidArgumentException in vendor/symfony/symfony/src/Symfony/Component/Form/FormRegistry.php 在第 87 行 +在第 121 行的 vendor/symfony/symfony/src/Symfony/Component/Form/FormRegistry.php 中的 FormRegistry ->getType ('file')
    【解决方案5】:

    你可以通过这种方式简单地做到这一点

        $image = $this->getSubject();
        $imageSmall = '';
    
        if($image){
            $container = $this->getConfigurationPool()->getContainer();
            $media = $container->get('sonata.media.twig.extension');
            $format = 'small';
            if($webPath = $image->getImageSmall()){
                $imageSmall = '<img src="'.$media->path($image->getImageSmall(), $format).'" class="admin-preview" />';
            }
        }
    
       $formMapper->add('imageSmall', 'sonata_media_type', array(
          'provider' => 'sonata.media.provider.image',
          'context' => 'default',
          'help' => $imageSmall
       ));
    

    【讨论】:

    • 快,但脏。 :D
    【解决方案6】:

    Teo.sk 使用 VichUploader 编写了显示图像的方法。我找到了一个选项,允许您在没有此捆绑包的情况下显示图像。

    首先我们需要创建我们的form_type。有教程:symfony_tutorial

    在主管理类中:

    namespace Your\Bundle;
    
    //.....//
    
    class ApplicationsAdmin extends Admin {
    
    //...//
    
    public function getFormTheme() {
        return array_merge(
            parent::getFormTheme(),
            array('YourBundle:Form:image_type.html.twig') //your path to form_type template
        );
    
    protected function configureFormFields(FormMapper $formMapper)
    {
         $formMapper->add('file_photo', 'image', array(
                'data_class' => 'Symfony\Component\HttpFoundation\File\File',
                'label' => 'Photo',
                'image_web_path' => $this->getRequest()->getBasePath().'/'.$subject->getWebPathPhoto()// it's a my name of common getWebPath method
            ))
            //....//
            ;
    }
    
    }
    

    下一部分是 ImageType 类的代码。

    namespace Your\Bundle\Form\Type;
    
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
    use Symfony\Component\OptionsResolver\Options;
    use Symfony\Component\Form\FormView;
    use Symfony\Component\Form\FormInterface;
    use Symfony\Component\Form\FormBuilder;
    use Symfony\Component\Form\FormBuilderInterface;
    
    
    class ImageType extends AbstractType
    {
    
        public function getParent()
        {
            return 'file';
        }
    
        public function getName()
        {
            return 'image';
        } 
    
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'image_web_path'         => ''
            ));
        }
    
        public function buildView(FormView $view, FormInterface $form, array $options)
        {
            $view->vars['image_web_path'] = $options['image_web_path'];
        }
    
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                 ->setAttribute('image_web_path', $options['image_web_path'])
            ;
        }
    }
    

    以及 image_type 树枝模板的结束时间。

    {% block image_widget %}
    {% spaceless %}
        {% set type = type|default('file') %}
        <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
        <img src="{{ image_web_path }}" alt="image_photo"/>
    {% endspaceless %}
    {% endblock %}
    

    对我来说它正在工作!我也在使用 avalanche bundle 来调整图像大小。

    【讨论】:

      【解决方案7】:

      有一种简单的方法 - 但您会在上传按钮下方看到图片。 SonataAdmin 允许将原始 HTML 放入任何给定表单字段的“帮助”选项中。您可以使用此功能嵌入图像标签:

      protected function configureFormFields(FormMapper $formMapper) {
      
          $object = $this->getSubject();
      
          $container = $this->getConfigurationPool()->getContainer();
      
          $fullPath =     $container->get('request')->getBasePath().'/'.$object->getWebPath();
      
      
          $formMapper->add('file', 'file', array('help' => is_file($object->getAbsolutePath() . $object->getPlanPath()) ? '<img src="' . $fullPath . $object->getPlanPath() . '" class="admin-preview" />' : 'Picture is not avialable')
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多