I am using Uploadable extension and very happy with that.
I have entity with one field as an Uploadable (photo), and another field is annotation for that photo (annotation). When I first create entity I choose the file, and put annotation and everything works okay, but when I want to update just annotation it loses the stored path of the previously uploaded photo. Is there a way to keep old values if null coming for that field?
This is my entity.
/**
* Photo
*
* #ORM\Table()
* #ORM\Entity
* #Gedmo\Uploadable(
* path="up/photo",
* allowOverwrite=false,
* appendNumber=true,
* allowedTypes="image/jpeg,image/pjpeg,image/png,image/x-png"
* )
*/
class Photo
{
/**
* #var array
*
* #Gedmo\Translatable
* #ORM\Column(name="annotation", type="string", length=255, nullable=true)
*/
private $annotation;
/**
* #var string
*
* #Gedmo\UploadableFilePath
* #Assert\File(
* mimeTypes={"image/jpeg", "image/pjpeg", "image/png", "image/x-png"}
* )
* #ORM\Column(name="photo", type="string", length=255)
*/
private $photo;
And this is my Controller part:
if ($entity->getPhoto()) {
$uploadableManager = $this->get('stof_doctrine_extensions.uploadable.manager');
$uploadableManager->markEntityToUpload($entity, $entity->getPhoto());
}
You can change setter on your entity:
public function setPhoto($photo) {
if (!$photo) {return $this;}
$this->photo = $photo;
return $this;
Related
I have to internationalize an app and particularly an entity called Program. To do so, I created an other entity ProgramIntl which contains a "locale" attribute (en_GB, fr_FR, etc) and strings which must be internationalized. I want the programIntl attribute in Program to be an associative array (with locale as key).
We have an API to read/write programs. GET and POST works fine but when I want to update data (PUT), the programIntl is not updated: an insert query is launched (and fails because of the unique constraint, but that's not the question).
Here is the code:
In Program.php:
/**
* #var
*
* #ORM\OneToMany(targetEntity="ProgramIntl", mappedBy="program", cascade={"persist", "remove", "merge"}, indexBy="locale", fetch="EAGER")
* #ORM\JoinColumn(nullable=false, onDelete="cascade")
* #Groups({"program_read", "program_write"})
*/
private $programIntl;
public function addProgramIntl($programIntl)
{
$this->programIntl[$programIntl->getLocale()] = $programIntl;
$programIntl->setProgram($this);
return $this;
}
public function setProgramIntl($programIntls)
{
$this->programIntl->clear();
foreach ($programIntls as $locale => $programIntl) {
$programIntl->setLocale($locale);
$this->addProgramIntl($programIntl);
}
}
public function getProgramIntl()
{
return $this->programIntl;
}
In ProgramIntl.php:
/**
* #ORM\Entity(repositoryClass="App\Repository\ProgramIntlRepository")
* #ORM\Table(name="program_intl",uniqueConstraints={#ORM\UniqueConstraint(name="program_intl_unique", columns={"program_id", "locale"})})
*/
class ProgramIntl
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"program_read", "program_write"})
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Program", inversedBy="programIntl")
* #ORM\JoinColumn(nullable=false)
*/
private $program;
/**
* #ORM\Column(type="string", length=5, options={"fixed" = true})
*/
private $locale;
/**
* #ORM\Column(type="string", length=64)
* #Assert\NotBlank()
* #Groups({"program_read", "program_write"})
*/
private $some_attr;
/* ... */
}
Any idea of what could be the reason of the "insert" instead of "update" ?
Thanks
I forgot to mention that we use api-platform.
But I found the solution myself. In case anyone is interested, adding the following annotation to classes Program and ProgramIntl solved the problem:
/* #ApiResource(attributes={
* "normalization_context"={"groups"={"program_read", "program_write"}},
* "denormalization_context"={"groups"={"program_read", "program_write"}}
* }) */
I use Doctrine ORM and Gedmo\Slug and i have class with related entitty job with title field and i want generate slug by job title. I'm configured SlugHandler like this:
/**
*
* #Gedmo\Slug(handlers={
* #Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", options={
* #Gedmo\SlugHandlerOption(name="relationField", value="job"),
* #Gedmo\SlugHandlerOption(name="relationSlugField", value="title"),
* #Gedmo\SlugHandlerOption(name="separator", value="-"),
* })
* }, fields={"slug"})
* #ORM\Column(type="string", unique=true, nullable=true)
*/
private $slug = '';
/**
* #var Job
*
* #ORM\OneToOne(targetEntity="Job", inversedBy="estimation")
* #ORM\JoinColumn(name="job_id", referencedColumnName="id", nullable = false)
*/
private $job;
But in slug field setting title value exactly the same as the title field value (without lowercase, separators and with spaces).
I don't understand what's the matter
If you suddenly encounter a similar problem, you need set option urilize in true:
/**
*
* #Gedmo\Slug(handlers={
* #Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\RelativeSlugHandler", options={
* #Gedmo\SlugHandlerOption(name="relationField", value="job"),
* #Gedmo\SlugHandlerOption(name="relationSlugField", value="title"),
* #Gedmo\SlugHandlerOption(name="separator", value="-"),
* #Gedmo\SlugHandlerOption(name="urilize", value="true"),
* })
* }, fields={"slug"})
* #ORM\Column(type="string", unique=true, nullable=true)
*/
private $slug;
Serialization groups work for me fine when i fetch one entity but
when i try fetch array of results i got empty result set.
I do this like that:
* #\FOS\RestBundle\Controller\Annotations\View(serializerGroups={"client"})
but also tried manually set context on view object, and same situation.
When i don't set group or set to "Default":
* #\FOS\RestBundle\Controller\Annotations\View(serializerGroups={"Default"})
i got proper serialized result set.
My entity:
use JMS\Serializer\Annotation as JMS;
[...]
/**
* Document
*
* #ORM\Table(name="documents")
* #ORM\Entity(repositoryClass="AppBundle\Entity\DocumentRepository")
* #ORM\EntityListeners({"DocumentListener"})
* #JMS\ExclusionPolicy("all")
* #JMS\AccessorOrder("custom", custom = {"id", "folderId", "title"})
*/
class Document implements ResourceInterface
{
/**
* #var integer
*
* #ORM\Column(type="integer", name="id")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #JMS\Groups({"client"})
* #JMS\Expose()
*/
protected $id;
/**
* #var string
*
* #ORM\Column(type="text", name="description")
* #JMS\Groups({"client"})
* #JMS\Expose()
*/
protected $description;
[...]
and my controller:
// not working
/**
* #\FOS\RestBundle\Controller\Annotations\View(serializerGroups={"client"})
* #return Paginator
* #Get("/documents")
*/
public function documentsAction(ParamFetcher $params)
{
[...]
return ($this->getPaginator(
$params,
$documentBundle->get()
));
}
//works fine
/**
* Get document
*
* #QueryParam(name="id", requirements="\d+", nullable=false)
* #param ParamFetcher $params
* #\FOS\RestBundle\Controller\Annotations\View(serializerGroups={"client"})
*/
public function documentAction(ParamFetcher $params)
{
/** #var DocumentRepository $documentBundle */
$documentBundle = $this->getDoctrine()->getRepository('AppBundle:Document');
return $documentBundle->findByDocumentId($params->get('id'));
}
PS.
fosrestbundle 1.7.9
jmsserializer 0.16.0
In Symfony 3, its not allowed to use cascade_validation anymore. So you have to make an Assert for the types. But it doesn't work, the form is valid even when a field is BLANK but the Assert said NOtBlank. I have a class Participants and I want to check the Adults ArrayCollection when checking my participant Model.
//Participant Model
/**
* #var ArrayCollection
* #Assert\All({
* #Assert\Type(type="My\WebsiteBundle\Model\Adult"),
* })
*/
protected $adults;
//Adult Model
class Adult
{
/**
* #var string
*
* #Assert\NotBlank()
*/
protected $salutation;
/**
* #var string
*
* #Assert\NotBlank()
*/
protected $firstname;
/**
* #var string
*
* #Assert\NotBlank()
*/
protected $lastname;
You should use the Valid assetion as described here http://symfony.com/doc/current/reference/constraints/Valid.html in the doc
As example:
/**
* #var ArrayCollection
*
* #Assert\All({
* #Assert\Type(type="My\WebsiteBundle\Model\Adult"),
* })
* #Assert\Valid
*/
protected $adults;
Hope this help
I'm trying to combine Doctrine's Extensions Blameable and Softdeleteable: when I execute $em->remove($myEntity);, I want to get the fields deleted and deletedBy updated accordingly.
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #Gedmo\SoftDeleteable(fieldName="deleted", timeAware=false)
*/
[...]
/**
* DateTime of softdeletion
* #var \DateTime
*
* #ORM\Column(name="deleted", type="datetime", nullable=true)
* #Assert\DateTime()
*/
private $deleted;
/**
* Softdeleted by
* #var MyProject\UserBundle\Entity\User $deletedBy
*
* #Gedmo\Blameable(on="change", field="deleted")
* #ORM\ManyToOne(targetEntity="MyProject\UserBundle\Entity\User")
* #ORM\JoinColumn()
*/
private $deletedBy;
I have a similar configuration for created/createdBy (with Blameable(on="create")) and updated/updatedBy (with Blameable(on="update")).
Even weirder, if I replace the code above by the one below, the field deletedBy is correctly updated:
/**
* Softdeleted by
* #var MyProject\UserBundle\Entity\User $deletedBy
*
* #Gedmo\Blameable(on="update")
* #ORM\ManyToOne(targetEntity="MyProject\UserBundle\Entity\User")
* #ORM\JoinColumn()
*/
private $deletedBy;
So it seems that it is only the Blameable(on="change", field="deleted") part which doesn't work, and I have no idea why...