hi, i'm try your bundle, but i don't understand how to use custom namer.
Can you explain how to implement a custom namer , or show an example for a custom namer.
thanks for help.
Sorry for my english,
Hi, you can do something like this:
in MySite\MyBundle\Entity\Entity.php:
/**
* @Assert\File(maxSize="20000000")
* @Vich\UploadableField(mapping="media_file", fileNameProperty="filename")
*
* @var File $file
*/
public $file;
in app/config/config.yml:
vich_uploader:
mappings:
media_file:
upload_dir: %kernel.root_dir%/../uploads/media
delete_on_remove: true
namer: namer.media_file
in MySite\MyBundle\Resources\config\services.yml:
services:
namer.media_file:
class: MySite\MyBundle\Namer\Namer
tags:
- { name: namer }
notice that if you want to use MySite\MyBundle\Resources\config\services.yml instead of MySite\MyBundle\Resources\config\services.xml, you have to edit MySite\MyBundle\DependencyInjectionMySiteMyExtension.php in this way:
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
in MySite\MyBundle\Namer\Namer.php:
<?php
namespace MySite\MyBundle\Namer;
use Vich\UploaderBundle\Naming\NamerInterface;
/**
* Namer class.
*/
class Namer implements NamerInterface
{
/**
* Creates a name for the file being uploaded.
*
* @param object $obj The object the upload is attached to.
* @param string $field The name of the uploadable field to generate a name for.
* @return string The file name.
*/
function name($obj, $field)
{
$file = $obj->file;
$extension = $file->getExtension();
return uniqid('', true).'.'.$extension;
}
}
got it!
@doncandid did you solved ?
yes it's solved. thanks
I've been trying to repeat the Namer example on Symfony 2.0.16 with no success. My code is exactly the same as inmarelibero's but I get this notice message:
Notice: Undefined property: Acme\DemoBundle\Entity\Product::$file in /home/sfprojects/vichuploader/src/Acme/DemoBundle/Namer/Namer.php line 21
making reference to the line
$file = $obj->file;
so the logical movement is inspect the $obj object to see what it has, using print_r($obj). This is what I get:
Acme\DemoBundle\Entity\Product Object
(
[id:protected] =>
[image:protected] => Symfony\Component\HttpFoundation\File\UploadedFile Object
(
[test:Symfony\Component\HttpFoundation\File\UploadedFile:private] =>
[originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 7794932098_10a55dc4ea_b.jpg
[mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => image/jpeg
[size:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 269071
[error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
[pathName:SplFileInfo:private] => /tmp/phpNRJRuk
[fileName:SplFileInfo:private] => phpNRJRuk
)
[imageName:protected] => pop-rocker
)
No file property in the $obj object. Now if I use the image property (which is a property is my entity class), obviously it will lead to an error message because is a protected property.
Fatal error: Cannot access protected property Acme\DemoBundle\Entity\Product::$image in /home/sfprojects/vichuploader/src/Acme/DemoBundle/Namer/Namer.php on line 21
I know I''m missing something quite obvious here, but I don't know what it is. Do I have to extend my entity class in the Namer? It doesn't make sense (and it doesn't works anyway).
I knew I was missing something from the very beggining: I was declaring $image as protected instead public in the entity class, that's why it could not be accessed from the Namer class:
/**
* @Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* @Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
*
* @var File $image
*/
protected $image; // WRONG! this attribute could not be accessed from non-child classes
But I got into another unsuspected error (no reported, by the way). the method getExtension() doesn't work at all. Diving into the Symfony code, looking for that method, I found this:
/**
* Returns the extension of the file.
*
* \SplFileInfo::getExtension() is not available before PHP 5.3.6
*
* @return string The extension
*
* @api
*/
public function getExtension()
{
return pathinfo($this->getBasename(), PATHINFO_EXTENSION);
}
And it just happend that libapache2-mod-php5 is in the 5.3.5-1ubuntu7.10 version, so getExtension() is available but it won't work. But wait a minute! I still have the guessExtension() method!
function name($obj, $field)
{
$file = $obj->image;
$extension = $file->guessExtension();
return uniqid('', true).'.'.$extension;
}
And voil脿, finally it works!
Hope be useful for someone.
grat thx all now work
only not understand how to use namer for folder...
now i have this error...
You have requested a non-existent service "namer.property_image".
?
You have requested a non-existent service
That's because you're missing some DIC configuration. I can't debug this without reading looking at all your code but you should be able to fix this reading again the documentation and having a double check on your config.
only not understand how to use namer for folder...
For directory you should implement a DirectoryNamer, the login is similar to the FileNamer. The doc explains how to do that, have a look at it and let me know which parts aren't clear.
hi.. I follow @doncandid said and get this error.. any suggestion? thanks
Compile Error: Declaration of AdminBundle\Service\Namer\Namer::name() must be compatible with Vich\UploaderBundle\Naming\NamerInterface::name($object, Vich\UploaderBundle\Mapping\PropertyMapping $mapping)
@sokphea-chea. I think what you're missing is the propertymapping.
use Vich\UploaderBundle\Naming\NamerInterface;
use Vich\UploaderBundle\Mapping\PropertyMapping;
class FileNamer implements NamerInterface
{
/**
* Creates a name for the file being uploaded
*
* @param object $obj The object the upload is attached to
* @param string $field The name of the uploadable field to generate a name for
*
* @return string The file name
*/
public function name($object, PropertyMapping $mapping)
{
$file = $object->file;
$extension = $file->getExtension();
return uniqid('', true).'.'.$extension;
}
You guys should put all this useful info into the documentation. It took me through many posts to get here and find proper configuration.
@jesusmartinez feel free to propose a PR to integrate documentation
Have spent a few hours on this - I'm guessing I'm missing something obvious. Happened when I went from 1.7.1 to 1.8.3. I'm getting same error as above, but the fix is eluding me:
Compile Error: Declaration of RC\RosterBundle\File\UserPhotoNamer::name($user, Vich\UploaderBundle\Mapping\PropertyMapping $mapping) must be compatible with Vich\UploaderBu
ndle\Naming\NamerInterface::name($object, Vich\UploaderBundle\Mapping\PropertyMapping $mapping): string
In my bundle, the config code is:
rc.user_photo.namer:
class: RC\RosterBundle\File\UserPhotoNamer
In the app config.yml, I have:
vich_uploader:
db_driver: orm
mappings:
user_photo:
uri_prefix: /uploads/user_photos
upload_destination: %kernel.root_dir%/../web/uploads/user_photos
namer:
service: vich_uploader.namer_origname
inject_on_load: false
delete_on_remove: false
Finally, the class that is the cause of all this:
<?php
namespace RC\RosterBundle\File;
use Vich\UploaderBundle\Mapping\PropertyMapping;
use Vich\UploaderBundle\Naming\NamerInterface;
class UserPhotoNamer implements NamerInterface
{
/**
* Creates a name for the file being uploaded.
*
* @param object $obj The object the upload is attached to.
* @param PropertyMapping $mapping The mapping to use to manipulate the given object.
* @return string The file name.
*/
public function name($user, PropertyMapping $mapping)
{
$name = '';
$name .= $user->getClient()->getId().'_';
$name .= $user->getId().'_';
$name .= date('YmdHi');
$name .= '.'.$user->getPhoto()->guessExtension();
return $name;
}
}
Any ideas? This is the only thing stopping me from pulling this app from 2.8 up to 3.4...
OK - solved the previous one by looking at the existing code - I was missing the ': string' after the function definition.... hope this helps someone else.
This saved me
class FileNamer implements NamerInterface
{
public function name($object, PropertyMapping $mapping): string
{
$fileType = ucfirst($mapping->getFilePropertyName());
$functionName = 'get' . $fileType;
list($type, $extension) = explode('/', $object->{$functionName}()->getMimeType());
return uniqid('', true).'.'.$extension;
}
}
Most helpful comment
Hi, you can do something like this:
in
MySite\MyBundle\Entity\Entity.php:in
app/config/config.yml:in
MySite\MyBundle\Resources\config\services.yml:notice that if you want to use
MySite\MyBundle\Resources\config\services.ymlinstead ofMySite\MyBundle\Resources\config\services.xml, you have to editMySite\MyBundle\DependencyInjectionMySiteMyExtension.phpin this way:in
MySite\MyBundle\Namer\Namer.php:got it!