I've got a problem.
When I want to create an article, it shows me this error.
And when I want to edit one, it doesn't change anything.
It was working before, but then I've added category and comment section.
Can you help me ?
here is my Controller:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\Article;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\Form\Forms;
use Symfony\Component\HttpFoundation\Request;
use App\Form\ArticleType;
class BlogController extends AbstractController
{
#[Route('/blog', name: 'blog')]
public function index(ManagerRegistry $doctrine): Response
{
$articles = $doctrine->getRepository(Article::class)->findAll();
return $this->render('blog/index.html.twig', [
'controller_name' => 'BlogController',
'articles' => $articles,
]);
}
#[Route("/", name: 'home')]
public function home() {
return $this->render('blog/home.html.twig', [
'title' => "Bienvenue",
'age' => 31,
]);
}
#[Route("/blog/new", name: 'blog_create')]
#[Route("/blog/{id}/edit", name: 'blog_edit')]
public function form(Article $article = null, Request $request, EntityManagerInterface $manager) {
// si on a pas d'article, donc on est en new
if(!$article){
$article = new Article();
}
$form = $this->createForm(ArticleType::class);
$form->handleRequest($request);
//si on a appuyer sur le bouton et que infos valides, on peut envoyer
if($form->isSubmitted() && $form->isValid()){
$manager->persist($article);
$manager->flush();
// on redirige vers l'article crée ou modifié
return $this->redirectToRoute('blog_show', ['id' => $article->getId()]);
}
return $this->render('blog/create.html.twig', [
'formArticle' => $form->createView(),
// edit Mode a true si il y a un article
'editMode' => $article->getId() !== null,
]);
}
#[Route("/blog/{id}", name: 'blog_show')]
public function show(ManagerRegistry $doctrine , $id){
$repo = $doctrine->getRepository(Article::class);
$article = $repo->find($id);
return $this->render('blog/show.html.twig', [
'article' => $article,
]);
}
}
And now, my form:
<?php
namespace App\Form;
use App\Entity\Article;
use App\Entity\Category;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('category', EntityType::class, [
'class' => Category::class,
'choice_label' => 'title',
])
->add('content')
->add('image')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Article::class,
]);
}
}
To end with my Entities:
Article
<?php
namespace App\Entity;
use App\Repository\ArticleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: ArticleRepository::class)]
class Article
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\Length(
min: 2,
max: 50,
)]
private $title;
#[ORM\Column(type: 'text')]
private $content;
#[ORM\Column(type: 'string', length: 255)]
private $image;
#[ORM\ManyToOne(targetEntity: Category::class, inversedBy: 'articles')]
private $category;
#[ORM\OneToMany(mappedBy: 'article', targetEntity: Comment::class)]
private $comments;
public function __construct()
{
$this->comments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getImage(): ?string
{
return $this->image;
}
public function setImage(string $image): self
{
$this->image = $image;
return $this;
}
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
/**
* #return Collection<int, Comment>
*/
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setArticle($this);
}
return $this;
}
public function removeComment(Comment $comment): self
{
if ($this->comments->removeElement($comment)) {
// set the owning side to null (unless already changed)
if ($comment->getArticle() === $this) {
$comment->setArticle(null);
}
}
return $this;
}
}
Category
<?php
namespace App\Entity;
use App\Repository\CategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CategoryRepository::class)]
class Category
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $title;
#[ORM\Column(type: 'text', nullable: true)]
private $description;
#[ORM\OneToMany(mappedBy: 'category', targetEntity: Article::class)]
private $articles;
public function __construct()
{
$this->articles = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
/**
* #return Collection<int, Article>
*/
public function getArticles(): Collection
{
return $this->articles;
}
public function addArticle(Article $article): self
{
if (!$this->articles->contains($article)) {
$this->articles[] = $article;
$article->setCategory($this);
}
return $this;
}
public function removeArticle(Article $article): self
{
if ($this->articles->removeElement($article)) {
// set the owning side to null (unless already changed)
if ($article->getCategory() === $this) {
$article->setCategory(null);
}
}
return $this;
}
}
Thanks in advance guys :))
I won't add the twig file cause it's normal file
I succeeded.
In the controllers, I just added:
$this->createForm(ArticleType::class, $article);
Related
Hello to the community,
I would like your help with two problems I am having with sending documents via my form and how I can display them in easyadmin please.
I've been stuck for some time on these two problems and all the answers I've found on the net haven't managed to get me out of this situation :'(
My documentsTypephp
<?php
namespace App\Form;
use App\Entity\Documents;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class DocumentsType extends AbstractType
{
public function buildForm(
FormBuilderInterface $builder,
array $options
): void {
$builder
->add('description', TextType::class, [
'label' => 'Description',
'attr' => [
'placeholder' => 'Description',
],
])
->add('ui_ux', FileType::class, [
'multiple' => false,
'data_class' => null,
'label' => ' Si UX/ UI',
'mapped' => true,
'required' => false,
'empty_data' => '',
'constraints' => [
new File([
'maxSize' => '1024k',
'mimeTypes' => [
'application/pdf',
'application/x-pdf',
'application/doc',
'application/docx',
'application/figx',
'application/odt',
'application/ott',
'application/jpg',
],
'mimeTypesMessage' =>
'Please upload a valid PDF, document, Figma file',
]),
],
])
this is my documentsphp
<?php
namespace App\Entity;
use App\Repository\DocumentsRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: DocumentsRepository::class)]
class Documents
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private ?\DateTime $sending_date = null;
#[ORM\ManyToOne(inversedBy: 'documents')]
#[ORM\JoinColumn(nullable: true)]
private ?User $users = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $description = null;
#[ORM\Column(length: 400, nullable: true)]
private ?string $ui_ux = null;
#[ORM\Column(length: 400, nullable: true)]
private ?string $seo = null;
#[ORM\Column(length: 400, nullable: true)]
private ?string $image_service = null;
#[ORM\ManyToMany(targetEntity: Services::class, inversedBy: 'documents')]
private Collection $services;
public function __construct()
{
$this->services = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getSendingDate(): ?\DateTime
{
return $this->sending_date;
}
public function setSendingDate(\DateTime $sending_date): self
{
$this->sending_date = $sending_date;
return $this;
}
public function getUsers(): ?User
{
return $this->users;
}
public function setUsers(?User $users): self
{
$this->users = $users;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getUiUx(): ?string
{
return $this->ui_ux;
}
public function setUiUx(?string $ui_ux): self
{
$this->ui_ux = $ui_ux;
return $this;
}
public function getSeo(): ?string
{
return $this->seo;
}
public function setSeo(?string $seo): self
{
$this->seo = $seo;
return $this;
}
public function getImageService(): ?string
{
return $this->image_service;
}
public function setImageService(?string $image_service): self
{
$this->image_service = $image_service;
return $this;
}
/**
* #return Collection<int, Services>
*/
public function getServices(): Collection
{
return $this->services;
}
public function addService(Services $service): self
{
if (!$this->services->contains($service)) {
$this->services->add($service);
}
return $this;
}
public function removeService(Services $service): self
{
$this->services->removeElement($service);
return $this;
}
}
and my second probleme realted to this one is how can i watch the documents in my easyadmin ?
I have this when i can send just one document
thank you very much indeed for your time to you all.
I'm trying to create/expand upon a basic app following the Symfony Sonata Admin Bundle documentation. There are BlogPost, Category, and Author entities and their respective admins. BlogPost has a ManyToOne relationship to both Category and Author.
I notice from the start that I had trouble applying different Form Types to 'Category' but thought maybe I was missing something. After adding 'Author,' running migrations, etc I found that I was able to add form types other than ModelType, such as ModelAutocompleteType or ModelListType to my author listing on BlogPostAdmin's configureFormFields without any issue. However when I tried to do the same to Category I'd get the error:
The current field `category` is not linked to an admin. Please create one for the target model: ``.
I have dropped and recreated the database and caches, even created a new MyCategory entity in case something was wrong when Category was generated. (Provided in examples)
I cannot seem to figure out why I can add different form types to Author but not Category.
Entities:
Entity/BlogPost.php
<?php
namespace App\Entity;
use App\Repository\BlogPostRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: BlogPostRepository::class)]
class BlogPost
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $title;
#[ORM\Column(type: 'boolean', nullable: true)]
private $draft;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $body;
#[ORM\ManyToOne(targetEntity: Author::class, inversedBy: 'posts')]
private $author;
#[ORM\ManyToOne(targetEntity: MyCategory::class, inversedBy: 'posts')]
private $myCategory;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function isDraft(): ?bool
{
return $this->draft;
}
public function setDraft(bool $draft): self
{
$this->draft = $draft;
return $this;
}
public function getBody(): ?string
{
return $this->body;
}
public function setBody(?string $body): self
{
$this->body = $body;
return $this;
}
public function getAuthor(): ?Author
{
return $this->author;
}
public function setAuthor(?Author $author): self
{
$this->author = $author;
return $this;
}
public function getMyCategory(): ?MyCategory
{
return $this->myCategory;
}
public function setMyCategory(?MyCategory $myCategory): self
{
$this->myCategory = $myCategory;
return $this;
}
}
Entity/Author.php
<?php
namespace App\Entity;
use App\Repository\AuthorRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AuthorRepository::class)]
class Author
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\OneToMany(mappedBy: 'author', targetEntity: BlogPost::class)]
private $posts;
public function __construct()
{
$this->posts = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* #return Collection<int, BlogPost>
*/
public function getPosts(): Collection
{
return $this->posts;
}
public function addPost(BlogPost $post): self
{
if (!$this->posts->contains($post)) {
$this->posts[] = $post;
$post->setAuthor($this);
}
return $this;
}
public function removePost(BlogPost $post): self
{
if ($this->posts->removeElement($post)) {
// set the owning side to null (unless already changed)
if ($post->getAuthor() === $this) {
$post->setAuthor(null);
}
}
return $this;
}
public function __toString(): string
{
return $this->getName();
}
}
Entity/MyCategory.php
<?php
namespace App\Entity;
use App\Repository\MyCategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: MyCategoryRepository::class)]
class MyCategory
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\OneToMany(mappedBy: 'myCategory', targetEntity: BlogPost::class)]
private $posts;
public function __construct()
{
$this->posts = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* #return Collection<int, BlogPost>
*/
public function getPosts(): Collection
{
return $this->posts;
}
public function addPost(BlogPost $post): self
{
if (!$this->posts->contains($post)) {
$this->posts[] = $post;
$post->setMyCategory($this);
}
return $this;
}
public function removePost(BlogPost $post): self
{
if ($this->posts->removeElement($post)) {
// set the owning side to null (unless already changed)
if ($post->getMyCategory() === $this) {
$post->setMyCategory(null);
}
}
return $this;
}
}
Admins:
Admin/BlogPostAdmin.php
<?php
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\DataGrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use App\Entity\MyCategory;
use App\Entity\Author;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\Type\ModelType;
use Sonata\AdminBundle\Form\Type\ModelListType;
use App\Entity\BlogPost;
use Sonata\AdminBundle\Form\Type\ModelAutocompleteType;
final class BlogPostAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->tab('Post')
->with("Content", ['class' => 'col-md-9'])
->add('title', TextType::class)
->add('body', TextareaType::class)
->end()
->with('Meta data', ['class' => 'col-md-3'])
->add('mycategory', ModelAutocompleteType::class, ['property' => 'name']) // Causing the error
->add('author', ModelAutocompleteType::class, ['property' => 'name'])
->add('draft')
->end()
->end()
->tab('Publish Options')
// ...
->end();
}
protected function configureListFields(ListMapper $list): void
{
$list
->addIdentifier('title')
->add('author.name')
->add('draft');
}
protected function configureDatagridFilters(DatagridMapper $datagrid): void
{
$datagrid
->add('title')
->add('author', null, [
'field_type' => EntityType::class,
'field_options' => [
'class' => Author::class,
'choice_label' => 'name',
],
])
;
}
protected function configureShowFields(ShowMapper $show): void
{
$show
->tab('Post')
->with('Content', ['class' => 'col-md-9'])
->add('id')
->add('title')
->add('body')
->add('author.name')
->end()
->with('Meta data', ['class' => 'col-md-3'])
// ->add('category.name')
->end()
->end()
}
public function toString(object $object): string
{
return $object instanceof BlogPost ? $object->getTitle() : 'Blog Post'; // Shown in the breadcrumb on the create view
}
}
Admin/AuthorAdmin.php
<?php
namespace App\Admin;
use App\Entity\Author;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class AuthorAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form->add('name', TextType::class);
}
protected function configureDatagridFilters(DatagridMapper $datagrid): void
{
$datagrid->add('name');
}
protected function configureListFields(ListMapper $list): void
{
$list->addIdentifier('name');
}
protected function configureShowFields(ShowMapper $show): void
{
$show->add('name');
}
public function toString(object $object): string
{
return $object instanceof Author ? $object->getName() : 'Author'; // Shown in the breadcrumb on the create view
}
}
Admin/CategoryAdmin.php
<?php
namespace App\Admin;
use App\Entity\MyCategory;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class MyCategoryAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form->add('name', TextType::class);
}
protected function configureDatagridFilters(DatagridMapper $datagrid): void
{
$datagrid->add('name');
}
protected function configureListFields(ListMapper $list): void
{
$list->addIdentifier('name');
}
protected function configureShowFields(ShowMapper $show): void
{
$show->add('name');
}
public function toString(object $object): string
{
return $object instanceof MyCategory ? $object->getName() : 'Category'; // Shown in the breadcrumb on the create view
}
}
Config:
config/services.yaml
parameters:
locale: "en"
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
admin.category:
class: App\Admin\MyCategoryAdmin
tags:
- {
name: sonata.admin,
model_class: App\Entity\MyCategory,
manager_type: orm,
label: Category,
}
admin.blog_post:
class: App\Admin\BlogPostAdmin
tags:
- {
name: sonata.admin,
model_class: App\Entity\BlogPost,
manager_type: orm,
label: "Blog post",
}
admin.author:
class: App\Admin\AuthorAdmin
tags:
- {
name: sonata.admin,
model_class: App\Entity\Author,
manager_type: orm,
label: "Author",
}
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: "../src/"
exclude:
- "../src/DependencyInjection/"
- "../src/Entity/"
- "../src/Kernel.php"
I use symfony6 for the first time with php 8.0.17. I want to make a small form that allows me to retrieve "Card" objects. My "Card" objects are bound to many to many color properties. I thought I could retrieve the cards objects via a findBy but I have the following error: Warning: Trying to access array offset on value of type null.
I looked at the documentation but I don't understand where my error comes from.
Cannot use findBy with related object ? Or maybe it's not a good idea to use entity field in form ? As you see the code is simple and it's that i don't understand it's not okay
The code is here :
My Card entity :
<?php
namespace App\Entity;
use App\Repository\CardRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: CardRepository::class)]
class Card
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\ManyToMany(targetEntity: Color::class, inversedBy: 'card')]
private $color;
public function __construct()
{
$this->color = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* #return Collection<int, Color>
*/
public function getColor(): Collection
{
return $this->color;
}
public function addColor(Color $color): self
{
if (!$this->color->contains($color)) {
$this->color[] = $color;
}
return $this;
}
public function removeColor(Color $color): self
{
$this->color->removeElement($color);
return $this;
}
}
My Color entity :
<?php
namespace App\Entity;
use App\Repository\ColorRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ColorRepository::class)]
class Color
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\ManyToMany(targetEntity: Card::class, mappedBy: 'color')]
private $card;
public function __construct()
{
$this->card = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function __toString()
{
return $this->getName();
}
/**
* #return Collection<int, Card>
*/
public function getCard(): Collection
{
return $this->card;
}
public function addCard(Cards $card): self
{
if (!$this->card->contains($card)) {
$this->card[] = $card;
$card->addColor($this);
}
return $this;
}
public function removeCard(Cards $card): self
{
if ($this->cards->removeElement($card)) {
$card->removeColor($this);
}
return $this;
}
}
My Search Form :
<?php
namespace App\Form;
use App\Entity\Color;
use App\Entity\Keyword;
use App\Entity\Type;
use App\Form\DataTransformer\ColorToStringTransformer;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
class CardSearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['required' => false])
->add('color', EntityType::class, [
'class' => Color::class,
// uses the Cards.name property as the visible option string
'choice_label' => 'name',
// used to render a select box, check boxes or radios
// 'multiple' => true,
// 'expanded' => true,
// To add little test for empty value
'placeholder' => 'Choose a color.',
'required' => false,
])
->add('save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
}
}
And to finish the controller action :
class DeckBuilderController extends AbstractController
{
#[Route('/deck/builder', name: 'app_deck_builder')]
public function index(Request $request, CardRepository $cardRepository): Response
{
$form = $this->createForm(CardSearchType::class);
$form->handleRequest($request);
$cards = null;
if ($form->isSubmitted() && $form->isValid())
{
// $form->getData() holds the submitted values
$cardData = $form->getData();
$cards = $cardRepository->findBy($cardData); => error Warning: Trying to access array offset on value of type null
}
return $this->render('deck_builder/index.html.twig', [
'controller_name' => 'DeckBuilderController',
'form' => $form->createView(),
'cards' => $cards,
]);
}
Thank in advance for your response.
$form->getData() doesn't return an array but an object with the form content.
My guess is that you want to use $form->get('color')->getData() instead
Correcting your code, I would try something like this :
public function index(Request $request, CardRepository $cardRepository): Response {
$cards = array();
$form = $this->createForm(CardSearchType::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$cards = $cardRepository->findBy(array('color'=>$form->get('color')->getData()));
}
return $this->renderForm('deck_builder/index.html.twig', array(
'controller_name' => 'DeckBuilderController',
'form' => $form,
'cards' => $cards,
));
}
To solve my problem I finally created a query by hand and made the join in DQL.
Here is my problem:
In fact when I retrieve the logged in user data with $currentUser = $this->getUser();
Afterwards I cannot access the method->getNewPassword(). I am told that it is not defined yet I have previously defined it on the User entity. Could this be due to my version of symfony ?
I don't understand why this error occurs when everything seems very normal.
Here's my User entity file:
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[UniqueEntity(fields:"email", message:"Email déjà pris")]
class User implements UserInterface, PasswordAuthenticatedUserInterface {
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;// par défault
#[ORM\Column(type: 'string', length: 180, unique: true)]
#[Assert\Email(message:'Veuillez entrer un email valide.')]
#[Assert\NotBlank(message:'Veuillez renseigner votre email.')]
private $email; // par défault
#[ORM\Column(type: 'json')]
private $roles = []; // par défault
#[ORM\Column(type: 'string')]
#[Assert\Length(min: 6, minMessage:'Le mot de passe doit avoir au moins 6 caractères.')]
#[Assert\NotBlank(message:'Veuillez renseigner un mot de passe.')]
private $password; // par défault
#[Assert\Length(min: 6, minMessage:'Le mot de passe doit avoir au moins 6 caractères.')]
private $newPassword;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\NotBlank(message:'Veuillez renseigner votre prénom.')]
private $firstname;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\NotBlank(message:'Veuillez renseigner votre nom.')]
private $lastname;
#[ORM\OneToMany(mappedBy: 'author', targetEntity: Question::class, orphanRemoval: true)]
private $questions;
#[ORM\OneToMany(mappedBy: 'author', targetEntity: Comment::class, orphanRemoval: true)]
private $comments;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\Url(message:'Veuillez renseigner une Url.')]
#[Assert\NotBlank(message:'Veuillez renseigner une image de profil.')]
private $picture;
#[ORM\OneToMany(mappedBy: 'author', targetEntity: Vote::class, orphanRemoval: true)]
private $votes;
public function __construct()
{
$this->Questions = new ArrayCollection();
$this->comments = new ArrayCollection();
$this->votes = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* #see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
public function getRoles():array
{
return $this->roles;
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getNewPassword(): ?string
{
return $this->newPassword;
}
public function setNewPassword(string $password): self
{
$this->newPassword = $password;
return $this;
}
/**
* #see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getLastname(): ?string
{
return $this->lastname;
}
public function setLastname(string $lastname): self
{
$this->lastname = $lastname;
return $this;
}
/**
* #return Collection|Question[]
*/
public function getQuestions(): Collection
{
return $this->questions;
}
public function addQuestion(Question $question): self
{
if (!$this->questions->contains($question)) {
$this->questions[] = $question;
$question->setAuthor($this);
}
return $this;
}
public function removeQuestion(Question $question): self
{
if ($this->Questions->removeElement($question)) {
// set the owning side to null (unless already changed)
if ($question->getAuthor() === $this) {
$question->setAuthor(null);
}
}
return $this;
}
/**
* #return Collection|Comment[]
*/
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setAuthor($this);
}
return $this;
}
public function removeComment(Comment $comment): self
{
if ($this->comments->removeElement($comment)) {
// set the owning side to null (unless already changed)
if ($comment->getAuthor() === $this) {
$comment->setAuthor(null);
}
}
return $this;
}
public function getPicture(): ?string
{
return $this->picture;
}
public function setPicture(string $picture): self
{
$this->picture = $picture;
return $this;
}
public function getFullname(): ?string {
return $this->firstname.' '.$this->lastname;
}
/**
* #return Collection|Vote[]
*/
public function getVotes(): Collection
{
return $this->votes;
}
public function addVote(Vote $vote): self
{
if (!$this->votes->contains($vote)) {
$this->votes[] = $vote;
$vote->setAuthor($this);
}
return $this;
}
public function removeVote(Vote $vote): self
{
if ($this->votes->removeElement($vote)) {
// set the owning side to null (unless already changed)
if ($vote->getAuthor() === $this) {
$vote->setAuthor(null);
}
}
return $this;
}
}
Here's my UserController.php file:
<?php
namespace App\Controller;
use App\Entity\User;
use App\Form\UserType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\ManagerRegistry;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class UserController extends AbstractController
{
#[Route('/user/{id}', name: 'user')]
#[IsGranted('IS_AUTHENTICATED_REMEMBERED')]
public function userProfile(User $user): Response {
$currentUser = $this->getUser();
if($currentUser === $user) {
return $this->redirectToRoute('current_user');
}
return $this->render('user/show.html.twig', [
'user' => $user,
]);
}
#[Route('/myprofile', name: 'current_user')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function currentUserProfile(Request $request, EntityManagerInterface $em, UserPasswordHasherInterface $passwordHasher): Response
{
$currentUser = $this->getUser(); // on récupère l'utilisateur connecté.
$userForm = $this->createForm(UserType::class, $currentUser); // création du formulaire
$userForm->remove('password'); // suppression du champ password
$userForm->add('newPassword', PasswordType::class, ['label' => 'Nouveau mot de passe']);
$userForm->handleRequest($request);
if($userForm->isSubmitted() && $userForm->isValid()) {
// dump($currentUser);
$newPassword = $currentUser->getNewPassword();
if($newPassword) {
$hash = $passwordHasher->hashPassword($currentUser, $newPassword);
$currentUser->setPassword($hash);
}
$em->flush();
// dump($currentUser);
}
return $this->render('user/index.html.twig', [
'form' => $userForm->createView(),
]);
}
}
Here is my UserType form:
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('email', null, ['label' =>'*Email'])
->add('firstname', null, ['label' =>'*Prénom'])
->add('lastname', null, ['label' =>'*Nom'])
->add('picture', null, ['label' =>'*Image'])
->add('password', PasswordType::class, ['label' =>'*Mot de passe','empty_data' => ''])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
I think I was clear about my question. If you need additional information to help me please leave it in the comments. Please I am waiting for answers to my question.
I am doing a crud for an entity in my application. The form have to upload a file, so i added the assert in the entity file. But when i submit my form the validator give me an error and said to me that the field image have to be a string. I've done upload of file a hundred times, that why i don't understand this time why the validator bundles react like that.
My entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\AlgorithmeRepository")
*/
class Algorithme
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $titre;
/**
* #ORM\Column(type="date")
*/
private $dateCreationArticle;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Assert\File(mimeTypes={ "image/jpeg","image/png"})
*/
private $image;
/**
* #ORM\Column(type="array")
*/
private $analyse = [];
public function getId(): ?int
{
return $this->id;
}
public function getTitre(): ?string
{
return $this->titre;
}
public function setTitre(string $titre): self
{
$this->titre = $titre;
return $this;
}
public function getDateCreationArticle(): ?\DateTimeInterface
{
return $this->dateCreationArticle;
}
public function setDateCreationArticle(\DateTimeInterface $dateCreationArticle): self
{
$this->dateCreationArticle = $dateCreationArticle;
return $this;
}
public function getImage()
{
return $this->image;
}
public function setImage($image)
{
$this->image = $image;
return $this;
}
public function getAnalyse(): ?array
{
return $this->analyse;
}
public function setAnalyse(array $analyse): self
{
$this->analyse = $analyse;
return $this;
}
}
The form :
<?php
namespace App\Form;
use App\Entity\Algorithme;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AlgorithmeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titre')
->add('dateCreationArticle',DateType::class,[
'widget' => 'single_text',
// prevents rendering it as type="date", to avoid HTML5 date pickers
'html5' => false,
// adds a class that can be selected in JavaScript
'attr' => ['class' => 'js-datepicker'],
])
->add('image',FileType::class,[
'required' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Algorithme::class,
]);
}
}
And the controller:
<?php
namespace App\Controller;
use App\Entity\Algorithme;
use App\Form\AlgorithmeType;
use App\Repository\AlgorithmeRepository;
use App\Services\CreateFormForArray;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/algorithme")
*/
class AlgorithmeController extends AbstractController
{
/**
* #Route("/new", name="algorithme_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$algorithme = new Algorithme();
$form = $this->createForm(AlgorithmeType::class, $algorithme);
$form->handleRequest($request);
// die();
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$CreateFormForArray = new CreateFormForArray();
$CreateFormForArray->handleArrayString($request,$algorithme,"analyse");
$entityManager->persist($algorithme);
$entityManager->flush();
return $this->redirectToRoute('algorithme_index');
} else {
}
return $this->render('algorithme/new.html.twig', [
'algorithme' => $algorithme,
'form' => $form->createView(),
]);
}
}
I found the problem for those who will wondering is was
#auto_mapping:
# App\Entity\: []
that was uncomment in config/packages/validator.yaml