Generate file name on file upload that contains file's username - symfony

I want to have the filename looks like: Username-OriginalFileName.
My first solution was to use the preUpload callback in my File Entity as described in Symfony cookbook here
/**
* #Assert\File(maxSize="6000000")
*/
public $FILE_file;
public $path;
public function getPath()
{
return $this->path;
}
public function setPath($path)
{
return $this->path=$path;
}
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()
{
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
return 'uploads/files';
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->FILE_file) {
$username=$this->get('security.context')->getToken()->getUser()->getUsername();
$this->path = $username.'-'.$this->path;
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->FILE_file) {
return;
}
$this->FILE_file->move($this->getUploadRootDir(), $this->FILE_file->getClientOriginalName());
$this->path = $this->FILE_file->getClientOriginalName();
$this->FILE_file = null;
}
But it seems that I can't get the container from the Entity.
So I've tried to do this in my File Controller:
$filename=$username.'-'.$file->path;
$file->setPath($filename);
$file->setFILEFormat($ext);
...
$em1->persist($file);
$em1->flush();
$file->upload();
$content=$file->getContent();
getContent is a function that opens the file and stores its content in an array of strings. For some reason the file is persisted and uploaded with its OriginalName from the upload form not with $filename. What am I doing wrong?

isnt there any relation between the file an the user?
else you could do something like:
File Entity:
/**
*
* #ORM/ManyToOne(targetEntity="User" …)
*/
private $user;
public function preUpload()
{
if (null !== $this->FILE_file) {
$this->path = $this->user->getUsername().'-'.$this->path;
}
}

Related

Doctrine throwing error connected with field not related to current operation

I'm currently doing app that's similar to imgur and I'm receiving following error
An exception occurred while executing 'INSERT INTO user_gallery_views (gallery_id, user_id) VALUES (?, ?)' with params [1, 1]:
SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: user_gallery_views.gallery_id, user_gallery_views.user_id
It occurs while calling path to add object as saved in users collection
Related part of App Controller
/**
* #Route("/image/{id}", name="imgDisp", methods={"GET"})
*/
public function imgDisp($id)
{
$img = $this->gR->findBy(['id'=>$id]);
if ($img) {
$img = $img[0];
$img->setImage(stream_get_contents($img->getImage()));
}
if($this->ls)
{
$this->viewMod($id);
}
return $this->render('app/imgDisp.html.twig', [
'img'=>$img
]);
}
/**
* #Route("/image/{id}/like", name="likeImg", methods={"POST"})
*/
public function likeImg($id)
{
$img = $this->gR->findBy(['id'=>$id])[0];
$user = $this->uR->findBy(['id'=>$this->session->get('user')->getId()])[0];
if(!$img->getLikes()->contains($user))
{
$img->addLike($user);
}
else
{
$img->removeLike($user);
}
$this->em->flush();
return $this->redirectToRoute('imgDisp', ['id'=>$id]);
}
/**
* #Route("/image/{id}/save", name="saveImg", methods={"POST"})
*/
public function saveImg($id)
{
$img = $this->gR->findBy(['id'=>$id])[0];
$user = $this->uR->findBy(['id'=>$this->session->get('user')->getId()])[0];
if(!$img->getSaves()->contains($user))
{
$img->addSave($user);
}
else
{
$img->removeSave($user);
}
$this->em->flush();
return $this->redirectToRoute('imgDisp', ['id'=>$id]);
}
private function viewMod($id)
{
$img = $this->gR->findBy(['id'=>$id])[0];
$user = $this->uR->findBy(['id'=>$this->session->get('user')->getId()])[0];
if(!$img->getViews()->contains($user))
{
$img->addView($user);
$this->em->flush();
}
}
Gallery entity (part related to problem)
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User", inversedBy="likes")
* #ORM\JoinTable(name="user_gallery_likes")
*/
private $likes;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User", inversedBy="collection")
* #ORM\JoinTable(name="user_gallery_saves")
*/
private $saves;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User", inversedBy="views")
* #ORM\JoinTable(name="user_gallery_views")
*/
private $views;
/**
* #return Collection|User[]
*/
public function getLikes(): Collection
{
return $this->likes;
}
public function addLike(User $like): self
{
if (!$this->likes->contains($like)) {
$this->likes[] = $like;
}
return $this;
}
public function removeLike(User $like): self
{
if ($this->likes->contains($like)) {
$this->likes->removeElement($like);
}
return $this;
}
/**
* #return Collection|User[]
*/
public function getSaves(): Collection
{
return $this->saves;
}
public function addSave(User $save): self
{
if (!$this->saves->contains($save)) {
$this->views[] = $save;
}
return $this;
}
public function removeSave(User $save): self
{
if ($this->saves->contains($save)) {
$this->saves->removeElement($save);
}
return $this;
}
/**
* #return Collection|User[]
*/
public function getViews(): Collection
{
return $this->views;
}
public function addView(User $view): self
{
if (!$this->views->contains($view)) {
$this->views[] = $view;
}
return $this;
}
Users entity (part related to problem)
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Gallery", mappedBy="saves")
*/
private $collection;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Gallery", mappedBy="likes")
*/
private $likes;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Gallery", mappedBy="views")
*/
private $views;
/**
* #return Collection|Gallery[]
*/
public function getCollection(): Collection
{
return $this->collection;
}
public function addCollection(Gallery $collection): self
{
if (!$this->collection->contains($collection)) {
$this->collection[] = $collection;
}
return $this;
}
public function removeCollection(Gallery $collection): self
{
if ($this->collection->contains($collection)) {
$this->collection->removeElement($collection);
}
return $this;
}
/**
* #return Collection|Gallery[]
*/
public function getLikes(): Collection
{
return $this->likes;
}
public function addLike(Gallery $like): self
{
if (!$this->likes->contains($like)) {
$this->likes[] = $like;
$like->addLike($this);
}
return $this;
}
public function removeLike(Gallery $like): self
{
if ($this->likes->contains($like)) {
$this->likes->removeElement($like);
$like->removeLike($this);
}
return $this;
}
/**
* #return Collection|Gallery[]
*/
public function getViews(): Collection
{
return $this->views;
}
public function addView(Gallery $view): self
{
if (!$this->views->contains($view)) {
$this->views[] = $view;
$view->addView($this);
}
return $this;
}
The point I don't get is why error concern user_galler_views when it's not even used in /image/{id}/save?
I'm for sure not seeing something but don't even know what, so I'm full of hope u gonna help me
It looks like you are storing the entity to the wrong Array.
public function addSave(User $save): self
{
if (!$this->saves->contains($save)) {
$this->views[] = $save;
}
return $this;
}
You check for $this->saves->contains($save) but then you store the data not to saves but to views.
$this->views[] = $save;
It is probably a coincidence that the save entity has the same id as another view entity that is already assigned to the gallery.

Upload multiple files for each entity

I am using doctrine2 with symfony2.
This is my entity to upload the file.
First, it call the setFile() and put the path to $this->temp,
then,preUpload is called ,upload called.
It is OK for uploading onefile for each entity,however, I would like to upload multiple files for each entity.
How can I handle this ?
Do you have any samples for this purpose?
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
public $path = "nophoto.jpeg";
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
// check if we have an old image path
if (is_file($this->getAbsolutePath())) {
// store the old name to delete after the update
$this->temp = $this->getAbsolutePath();
} else {
$this->path = 'initial';
}
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->getFile()) {
$this->path = $this->getId().'.'.$this->getFile()->guessExtension();
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->getFile1()) {return;}
if (isset($this->temp)) {
// delete the old image
unlink($this->temp);
// clear the temp image path
$this->temp = null;
}
// you must throw an exception here if the file cannot be moved
// so that the entity is not persisted to the database
// which the UploadedFile move() method does
$this->getFile()->move(
$this->getUploadRootDir(),
$this->getId().'.'.$this->getFile()->guessExtension()
);
$this->setFile(null);
}
public function getAbsolutePath()
{
return null === $this->path
? null
: $this->getUploadRootDir().'/'.$this->getId().'.'.$this->path;
}
public function getFile1()
{
return $this->file;
}
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 up
// when displaying uploaded doc/image in the view.
return 'uploads/documents';
}
You need new entity which will represent uploaded file with many-to-one (or many-to-many) association to your entity. This is most universal approach.
Alternatively you can store file names in array but that will complicate your validation and forms.

Symfony2 - Undefined property in entity for file upload

I am getting the following error when trying to upload a file, it's odd because I've used the same code on other projects without any problems/errors.
What am I missing here?
Notice: Undefined property: Acme\DemoBundle\Entity\Article::$file in /var/www/html/InsideFight/src/Acme/DempBundle/Entity/Article.php line 277
The problem line is:
if (null !== $this->file) {
I do not have any file upload code in my controller it's being handled in the entity.
Entity
public $file;
public function getUploadDir()
{
return 'images/';
}
public function getUploadRootDir()
{
return __DIR__ . '/../../../../web/' . $this->getUploadDir();
}
public function getWebPath()
{
return null === $this->image ? null : $this->getUploadDir() . '/' . $this->image;
}
public function getAbsolutePath()
{
return null === $this->image ? null : $this->getUploadRootDir() . '/' . $this->image;
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->file) {
$this->image = uniqid() . '.' . $this->file->guessExtension();
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->file) {
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->file->move($this->getUploadRootDir(), $this->image);
unset($this->file);
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
Thats because you do unset($this->file);. Change it to $this->file = null.
Include the following namespace.
use Symfony\Component\HttpFoundation\File\UploadedFile;
Make the file variable private and create a temp file variable.
private $file;
private $tempFile
Then create getter and setter methods for $file.
public function getFile()
{
return $this->file;
}
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
if (isset($this->image)) {
// store the old name to delete after the update
$this->tempfile = $this->image;
$this->image = null;
} else {
$this->image = 'initial';
}
}
Then, modify preUpload and upload functions.
public function upload()
{
if (null === $this->getFile()) {
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->getFile()->move($this->getUploadRootDir(), $this->image);
// check if we have an old image
if (isset($this->tempFile)) {
// delete the old image
unlink($this->getUploadRootDir() . '/' . $this->tempFile);
// clear the temp image path
$this->tempFile = null;
}
$this->file = null;
}
public function preUpload()
{
if (null !== $this->getFile()) {
// generate a unique name
$filename = uniqid();
$this->image = $filename . '.' . $this->getFile()->guessExtension();
}
}

Finding out what changed via postUpdate listener in Symfony 2.1

I have a postUpdate listener and I'd like to know what the values were prior to the update and what the values for the DB entry were after the update. Is there a way to do this in Symfony 2.1? I've looked at what's stored in getUnitOfWork() but it's empty since the update has already taken place.
You can use this ansfer Symfony2 - Doctrine - no changeset in post update
/**
* #param LifecycleEventArgs $args
*/
public function postUpdate(LifecycleEventArgs $args)
{
$changeArray = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($args->getObject());
}
Found the solution here. What I needed was actually part of preUpdate(). I needed to call getEntityChangeSet() on the LifecycleEventArgs.
My code:
public function preUpdate(Event\LifecycleEventArgs $eventArgs)
{
$changeArray = $eventArgs->getEntityChangeSet();
//do stuff with the change array
}
Your Entitiy:
/**
* Order
*
* #ORM\Table(name="order")
* #ORM\Entity()
* #ORM\EntityListeners(
* {"\EventListeners\OrderListener"}
* )
*/
class Order
{
...
Your listener:
class OrderListener
{
protected $needsFlush = false;
protected $fields = false;
public function preUpdate($entity, LifecycleEventArgs $eventArgs)
{
if (!$this->isCorrectObject($entity)) {
return null;
}
return $this->setFields($entity, $eventArgs);
}
public function postUpdate($entity, LifecycleEventArgs $eventArgs)
{
if (!$this->isCorrectObject($entity)) {
return null;
}
foreach ($this->fields as $field => $detail) {
echo $field. ' was ' . $detail[0]
. ' and is now ' . $detail[1];
//this is where you would save something
}
$eventArgs->getEntityManager()->flush();
return true;
}
public function setFields($entity, LifecycleEventArgs $eventArgs)
{
$this->fields = array_diff_key(
$eventArgs->getEntityChangeSet(),
[ 'modified'=>0 ]
);
return true;
}
public function isCorrectObject($entity)
{
return $entity instanceof Order;
}
}
You can find example in doctrine documentation.
class NeverAliceOnlyBobListener
{
public function preUpdate(PreUpdateEventArgs $eventArgs)
{
if ($eventArgs->getEntity() instanceof User) {
if ($eventArgs->hasChangedField('name') && $eventArgs->getNewValue('name') == 'Alice') {
$eventArgs->setNewValue('name', 'Bob');
}
}
}
}

how to get the path of a file upload and save in db using symfony2

I have created a file uploads page. In my controller I want to get the uploaded path of the view and add it in the database for a particular id. For that I want the path of the file ans send it to the repository. The problem when I am using in my controller
if ($request->getMethod() == 'POST')
{
$form->bind($request);
$file = $form["file"]->getData();
/* here it is giving the path like /tmp/phpkR4kgD */
$em = $this->getDoctrine()->getManager();
$user->upload();
}
this is my entity
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
public function upload()
{
if (null === $this->file)
{
return;
}
$this->file->move($this->getUploadRootDir(), $this->file->getClientOriginalName());
$this->path = $this->file->getClientOriginalName();
$this->file = null;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function getAbsolutePath()
{
return null === $this->path
? null
: $this->getUploadRootDir() . DIRECTORY_SEPARATOR . $this->path;
}
public function getWebPath()
{
return null === $this->path
? null
: $this->getUploadDir() . DIRECTORY_SEPARATOR . $this->path;
}
protected function getUploadRootDir()
{
return __DIR__ . '/../../../../web/'. $this->getUploadDir();
}
protected function getUploadDir()
{
return 'uploads/';
}
I have created my uploads folder in web folder of symfony
while calling upload() method from it takes the temporary path to entity.
In entity it will get the orginal path $this->path = $this->file->getClientOriginalName();
so use return statement which returns the original path to controller from there you can save it in database...

Resources