product_show:
path: /product/{id}
controller: App\Controller\ProductController::show
methods: GET
requirements:
id: \d+
<?php
declare(strict_types=1);
namespace App\Entity;
use App\Repository\ProductRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=ProductRepository::class)
*/
class Product
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
private int $id;
/**
* #ORM\Column(type="boolean", options={"default": true})
*/
private bool $active = true;
public function getId(): int
{
return $this->id;
}
public function active(): bool
{
return $this->active;
}
}
<?php
namespace App\Controller;
use App\Entity\Product;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class ProductController extends AbstractController
{
public function show(Product $product): Response
{
return $this->render('product/show.html.twig', [
'product' => $product,
]);
}
}
When $product->active() return false, I want to send 404 response.
But it should be done without adding an if in controller action.
Perhaps I should modify something in ParamConverter. How can I do this? How can I overwrite ParamConverter behavior?
You can fetch via an Expression and use a custom function in your repository.
For example:
class ProductController extends AbstractController
{
/**
* #Route("/product/{product_id}")
* #Entity("product", expr="repository.findOneActive(product_id)")
*/
public function show(Product $product): Response
{
return $this->render('product/show.html.twig', [
'product' => $product,
]);
}
}
And in your ProductRepository:
class ProductRepository
{
public function findOneActive($productId)
{
// your query here...
}
}
Related
I want to have post by id or by slug, use ParamConverter but I find App error: Post object not found by the #ParamConverter annotation.knowing that I am a beginner at symfony and I followed a training.
I tried the route http://127.0.0.1:8000/blog/post/1
BlogController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Post;
/**
* #Route("/blog")
*/
class BlogController extends AbstractController {
/**
* #Route("/post/{id}", requirements={ "id" : "\d+" }, name="get_one_post_by_id", methods={"GET"})
* #ParamConverter("post", class="App:Post")
*/
public function postById($post){
return $this->json($post);
}
/**
* #Route("/post/{slug}", methods={"GET"})
* #ParamConverter("post", class="App:Post", options={"mapping": {"slug": "slug"}})
*/
public function postBySlug($post){
return $this->json($post);
}
/**
* #Route("/post/{id}", name="delete-post", methods={"DELETE"})
*/
public function destroy(Post $post){
$em = $this->getDoctrine()->getManager();
$em->remove($post);
$em->flush();
return $this->json(null, 204);
}
it should looks like:
use App\Entity\Post;
/**
* #Route("/post/{id}", requirements={ "id" : "\d+" }, name="get_one_post_by_id", methods={"GET"})
*/
public function postById(Post $post){
return $this->json($post);
}
that's all
hi im trying to encode My password for My app user So i tried to encrypted in my setPassword function
unfortunately i get this error that i don't understand: Call to a member function encodePassword() on null error pic
<?php
namespace App\Entity;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Gedmo\Mapping\Annotation as Gedmo;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\File;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Admin
*#Vich\Uploadable
* #ORM\Table(name="admin")
* #ORM\Entity
*/
class Admin implements UserInterface
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* Undocumented variable
*
* #var UserPasswordEncoderInterface
*/
private $passwordEncoder ;
/**
* #see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$hash= $this->passwordEncoder->encodePassword($this,$password);
$this->password=$hash;
return $this ;
}
.......
whats wrong, and how can i fix it ! thnx
but this one work
<?php
namespace App\Controller\Admin;
use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\FormField;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserCrudController extends AbstractCrudController
{
/** #var UserPasswordEncoderInterface */
private $passwordEncoder;
public static function getEntityFqcn(): string
{
return User::class;
}
public function configureFields(string $pageName): iterable
{
return [
FormField::addPanel('Change password')->setIcon('fa fa-key'),
Field::new('plainPassword', 'New password')->onlyOnForms()
->setFormType(RepeatedType::class)
->setFormTypeOptions([
'type' => PasswordType::class,
'first_options' => ['label' => 'New password'],
'second_options' => ['label' => 'Repeat password'],
]),
];
}
public function createEditFormBuilder(EntityDto $entityDto, KeyValueStore $formOptions, AdminContext $context): FormBuilderInterface
{
$formBuilder = parent::createEditFormBuilder($entityDto, $formOptions, $context);
$this->addEncodePasswordEventListener($formBuilder);
return $formBuilder;
}
public function createNewFormBuilder(EntityDto $entityDto, KeyValueStore $formOptions, AdminContext $context): FormBuilderInterface
{
$formBuilder = parent::createNewFormBuilder($entityDto, $formOptions, $context);
$this->addEncodePasswordEventListener($formBuilder);
return $formBuilder;
}
/**
* #required
*/
public function setEncoder(UserPasswordEncoderInterface $passwordEncoder): void
{
$this->passwordEncoder = $passwordEncoder;
}
protected function addEncodePasswordEventListener(FormBuilderInterface $formBuilder)
{
$formBuilder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
/** #var User $user */
$user = $event->getData();
if ($user->getPlainPassword()) {
$user->setPassword($this->passwordEncoder->encodePassword($user, $user->getPlainPassword()));
}
});
}
}
i tried to add an Event listener so i create this class
<?php
namespace App\Controller\Admin;
use App\Entity\Admin;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use EasyCorp\Bundle\EasyAdminBundle\EventListener\AdminContextListener;
class AdminController extends AdminContextListener
{
/**
* #var UserPasswordEncoderInterface
*/
private $encoder ;
public function __construct(UserPasswordEncoderInterface $encoder)
{
$this->encoder=$encoder;
}
public static function getSetPasswordEvent()
{
return [
BeforeEntityPersistedEvent::class => ['setPassword'],
];
}
public function setPassword(BeforeEntityPersistedEvent $event)
{
$entity = $event->getEntityInstance();
if (!($entity instanceof Admin)) {
return;
}
$encoded = $this->encoder->encodePassword($entity, $entity->getPassword());
$entity->setPassword($encoded);
}
}
and it didn't work too
You should do that when User register, so add this before doing flush(); for new user:
$user = new UserEntity();
$user->setEmail($request->getEmail());
if ($request->getPassword())
{
$createUser->setPassword($this->encoder->encodePassword($user, $request->getPassword()));
}
$this->entityManager->persist($createUser);
$this->entityManager->flush();
$this->entityManager->clear();
Notice: $request containe payload comes form frontend {"email": "", "passwprd": ""}.
Notice: $createUser is a user object to flush.
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
I am calling the \prelaunchroute in my application and this is how it is defined in my routes.php:
`Route::get('/prelaunch', [ 'uses' => 'SubscriptionController#getReferrer', 'as' => 'subscriber.referral'], function () {
return view('prelaunch');
});`
But unfortunately, I am getting:
Call to undefined method App\Http\Controllers\SubscriptionController::getMiddleware()
This is a draft of my SubscriptionController code:
namespace App\Http\Controllers;
use App\Http\Manager\SubscriptionManager;
use Illuminate\Support\Facades\Request;
/**
* Class SubscriptionController
* #package App\Http\Controllers
*/
class SubscriptionController
{
/**
* #var \SubscriptionManager $subscriptionManager
*/
protected $subscriptionManager;
/**
* SubscriptionController constructor.
*/
//public function __construct(SubscriptionManager $subscriptionManager)
public function __construct(SubscriptionManager $subscriptionManager)
{
$this->subscriptionManager = $subscriptionManager;
}
/**
* #param Request $request
* #return void
*/
public function subscribe(Request $request)
{
$this->subscriptionManager->subscribeToList($request);
}
/**
* #param Request $request
* #return void
*/
public function unsubscribe(Request $request)
{
$this->subscriptionManager->unsubscribeFromList($request);
}
/**
* #return void
*/
public function getReferrer()
{
print_r(Input::all());
die;
$utm_source = \Input::get('utm_source');
return view('prelaunch');
}
}
Any thoughts on this one? Please bare in mind that I am fairly new to Laravel.
You forgot to extend the abstract controller:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Manager\SubscriptionManager;
use Illuminate\Support\Facades\Request;
/**
* Class SubscriptionController
* #package App\Http\Controllers
*/
class SubscriptionController extends Controller
Try to extends Controller
/**
* Class SubscriptionController
* #package App\Http\Controllers
*/
class SubscriptionController extends Controller
{
I'm building an API and I would ask something about using namespaces on a Symfony2 controller.
Is there a real difference doing :
<?php
namespace My\APIBundle\Controller;
use FOS\RestBundle\Controller\Annotations\View,
FOS\RestBundle\Controller\Annotations\Post,
FOS\RestBundle\Controller\Annotations\Get;
use [...]
class MyRestController extends Controller {
[...]
/**
* #View()
* #Get()
*/
public function getAction(Thing $thing) {
return $thing;
}
/**
* #View()
* #Post()
*/
public function postAction() {
}
or doing
<?php
namespace My\APIBundle\Controller;
use FOS\RestBundle\Controller\Annotations as Rest;
use [...]
class MyRestController extends Controller {
[...]
/**
* #Rest\View()
* #Rest\Get()
*/
public function getAction(Thing $thing) {
return $thing;
}
/**
* #Rest\View()
* #Rest\Post()
*/
public function postAction() {
}
Would the alias load everything in the given namespace, losing perfs ?
Or will it load only annoted classes, unitary ?