Вероятно, следует назвать :«SonataMediaBundle -, где недостающее руководство?».
Я сделал некоторый админ-бэкенд с помощью sonataAdminBundle и sonataDoctrineORMAdminBundle (и некоторых других ), большинство вещей работало, как и ожидалось, но я оставил загрузку файлов и обработку на потом, потому что подумал: «Как сложно это может быть? ".
Короче говоря -, есть ли ЛЮБАЯ документация о самых простых вещах -, то есть о прикреплении изображений к сообщению или записи, о том, как настроить класс администратора сонаты, как отображать миниатюры изображений в форме редактирования и т. д.?
Первая страница документации заканчивается фразой «вы можете посетить панель администратора», как будто я могу ожидать там каких-то соответствующих изменений, может быть, медиа-менеджер запущен и работает или что-то в этом роде. Но это не так.
На следующей странице кратко рассматриваются heplers, а затем еще одна страница с довольно сложным примером провайдера vimeo.
Я искал по всему Интернету, и лучшее, что я мог придумать, это поле загрузки с всплывающим окном ajax и список загруженных файлов.
В моем классе администратора у меня есть:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('general')
->add('title')
->add('body')
->add('categories')
->end()
->with('media')
->add('images', 'sonata_type_model')
в моем классе новостей:
/**
* @ORM\ManyToMany(targetEntity="Application\Sonata\MediaBundle\Entity\Media")
*/
public $images;
и все конфиги yaml и роутинги реализованы.
Результат:Fatal error: Call to a member function add() on a non-object in [some-entity].php
при попытке загрузить изображение и выбираемый список идентификаторов изображений со знаком «плюс» (соната _тип _поле модели, я думаю, ).
Я застрял. Я смог создать медиа-менеджер просто в простом sf2 за час или два, но это был другой проект, и переписывать текущий по этому шаблону означает начинать «с нуля». Итак, -что нужно сделать, чтобы sonataMediaBundle вместе с sonataAdminBundle работали должным образом?
РЕДАКТИРОВАТЬ :вот что я сделал вместо этого:
Мой курс новостей (или любой другой, который требует загрузки изображения):
documents = new ArrayCollection();
}
[...]
/**
* Add documents
*
* @param Festus\SiteBundle\Entity\Document $documents
*/
public function addDocument(\Festus\SiteBundle\Entity\Document $document)
{
$this->documents[] = $document;
}
/**
* set document
*
* @param Festus\SiteBundle\Entity\Document $documents
*/
public function setDocument(\Festus\SiteBundle\Entity\Document $document)
{
foreach ($this->documents as $doc) {
$this->documents->removeElement($doc);
}
$this->documents[] = $document;
}
/**
* Get documents
*
* @return Doctrine\Common\Collections\Collection
*/
public function getDocuments()
{
return $this->documents;
}
// setters, getters...
Моему классу документов (нужно было изменить имя таблицы, потому что я столкнулся с проблемами с зарезервированными словами на некоторых серверах):
createdAt = new \DateTime();
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path;
}
public function getWebPath()
{
return null === $this->path ? null : $this->getUploadDir().'/'.$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
return 'uploads/documents';
}
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->theFile) {
//var_dump($this);
// do whatever you want to generate a unique name
$this->path = uniqid().'.'.$this->theFile->guessExtension();
}
}
/**
* @ORM\PostPersist()
* @ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->theFile) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->theFile->move($this->getUploadRootDir(), $this->path);
unset($this->theFile);
}
/**
* @ORM\PostRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
public function __toString()
{
return 'Document';
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set file
*
* @param string $file
*/
public function setTheFile($file)
{
$this->theFile = $file;
}
/**
* Get file
*
* @return string
*/
public function getTheFile()
{
return $this->theFile;
}
/**
* Set path
*
* @param string $path
*/
public function setPath($path)
{
$this->path = $path;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set type
*
* @param string $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* Get type
*
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* Gets an object representing the date and time the user was created.
*
* @return DateTime A DateTime object
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Gets an object representing the date and time the user was created.
*
* @return DateTime A DateTime object
*/
public function getCreatedAtString()
{
return date_format($this->createdAt, "Y-m-d");
}
/**
* Set createdAt
*
* @param datetime $createdAt
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
}
}
Как видите, большая часть скопирована из туториала по symfony2.
Теперь о контроллере:
setFormTheme(array_merge($this->getFormTheme(),
array('FestusSiteBundle:Form:image_form.html.twig')
));
}
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('ogólne')
->add('title', NULL, array('label' => 'tytuł:'))
->add('body', NULL, array('label' => 'treść:', 'attr' => array(
'class' => 'tinymce', 'data-theme' => 'simple')))
->add('categories', NULL, array('label' => 'kategorie:'))
->end()
->with('media')
->add('fileName', 'text', array(
"label" => 'tytuł obrazka:',
'property_path' => false,
'required' => false
))
->add('theFile', 'file', array(
"label" => 'wybierz plik',
'property_path' => false,
'required' => false
))
->end()
;
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title')
->add('body')
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title')
->add('categories')
->add('_action', 'actions', array(
'actions' => array(
'view' => array(),
'edit' => array(),
)
))
;
}
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper->add('title')
->add('body');
}
public function validate(ErrorElement $errorElement, $object)
{
$errorElement
->with('title')
->assertMinLength(array('limit' => 2))
->end()
;
}
public function prePersist($news) {
$this->saveFile($news);
}
public function preUpdate($news) {
$this->saveFile($news);
}
public function saveFile($news) {
$request = Request::createFromGlobals();
$requestData = current($request->request->all());
$filesData = current($request->files->all());
$document = new Document();
$theFile = $filesData['theFile'];
$name = $requestData['fileName'];
if($theFile != NULL){
$document->setName($name);
$document->setTheFile($theFile);
$news->setDocument($document);
}
}
}
Мой базовый класс пакета расширяет класс административного пакета, потому что я могу перезаписывать шаблоны:
И в SomeSiteBundle/resources/views/CRUD/base_edit.html.twig
я немного изменил шаблон, чтобы пользователь мог видеть текущее установленное изображение:
{% for field_name in form_group.fields %}
{% if admin.formfielddescriptions[field_name] is defined %}
{% if field_name == 'fileName' %}
Obecny obrazek:
{% if object.documents[0] is defined %}
{% else %}
brak
{% endif %}
Wczytaj nowy:
{% endif %}
{{ form_row(form[field_name])}}
{% endif %}
{% endfor %}
Прямо сейчас я использую только одно изображение для каждой новости («избранное изображение» ), и в любом случае это немного излишне, потому что я использую tinyMCE с плагином jbiimages, поэтому я все равно могу помещать изображения в тело новости. Чтобы заставить плагин jbiimages работать правильно, вам нужно установить некоторые параметры tinyMCE:
------эта часть посвящена пакету tinymce и tinymce, а также плагину tinymce :---------
$config['img_path'] = '/web/uploads/documents';
(. или любой другой путь, который Вам подходит )в web/bundles/stfalcontinymce/vendor/tiny_mce/plugins/jbimages/config.php
. (Конечно, сначала необходимо установить пакет stfalcon tinymce ). Затем я немного отредактировал web/bundles/stfalcontinymce/js/init.jquery.js
, чтобы можно было прочитать больше параметров из config.yml
:
themeOptions.script_url = options.jquery_script_url;
//mine:
themeOptions.convert_urls = options.convert_urls;
themeOptions.relative_urls = options.relative_urls;
themeOptions.remove_script_host = options.remove_script_host;
themeOptions.document_base_url = options.document_base_url;
. И, наконец, вconfig.yml
:
[...]
stfalcon_tinymce:
include_jquery: true
tinymce_jquery: true
textarea_class: "tinymce"
relative_urls : false
convert_urls : false
remove_script_host : false
document_base_url : "http://somesite.home.pl/web/"
theme:
[...]
И это все, AFAIR. Надеюсь это поможет ;-)