The method name must start with either findBy, findOneBy, countBy - symfony

I've got a command tryng to access a repository method. But I can't succeed.
services.yml
app.command.app_checkOfferDemand:
class: AppRefactoredBundle\Command\CheckOfferAndDemand
arguments: ['#doctrine.orm.entity_manager']
tags:
- { name: console.command }
app_OfferRepository
class app_OfferRepository extends \Doctrine\ORM\EntityRepository
{
private function checkAndUpdate(){
$em = $this->getContainer()->get('doctrine')->getManager();
$qb = $em->createQueryBuilder();
$q = $qb->update('app_Offer', 'o')
->set('o.status_id', 2)
->where('o.createdAt < DATE_SUB(NOW(), INTERVAL 2 HOUR)')
->getQuery();
return $q->execute();
}
}
CheckOfferAndDemand
class CheckOfferAndDemand extends Command{
private $em;
public function __construct(EntityManager $em)
{
parent::__construct();
$this->em=$em;
}
protected function configure()
{
// On set le nom de la commande
$this->setName('app:check_OfferDemand');
// On set la description
$this->setDescription("Permet de controler le timeout des offres et demandes");
// On set l'aide
$this->setHelp("Cette commande ne prend pas d'argument et travailler sur toutes les offres et demandes");
}
public function execute(InputInterface $input, OutputInterface $output){
$output->writeln("update des offres");
$this->em->getRepository('AppRefactoredBundle:app_Offer')->checkAndUpdate();
$output->writeln("update des demandes");
$this->em->getRepository('AppRefactoredBundle:app_Demand')->checkAndUpdate();
$this->em->flush();
$output->writeln("DONE");
}
}
The command by itself is working (the first update print is made).
But then the error is triggered
Undefined method 'checkAndUpdate'. The method name must start with either findBy, findOneBy or countBy!
The entities seems to be well declared too
/**
* app_Offer
*
* #ORM\Table(name="app__offer")
* #ORM\Entity(repositoryClass="AppRefactoredBundle\Repository\app_OfferRepository")
*/
class app_Offer
Thanks for your help.

Your Repository method cannot be accessed because it's denoted as private.
Change
private function checkAndUpdate() {
to
public function checkAndUpdate() {

Related

Could not instanciate mail function with PhpMailer

I'm using Laminas framework for a project I'm developing. I installed Node.js to use maildev as SMTP server for sending mail e-mails with PHPMailer and everything is working well.
The next step is to create scripts with Laminas framework laminas-cli and this one also works fine. The problem is that at the end on the execution of my script, I would like to send e-mail to the user and I'm getting this error :
Additional params: -fnanguisamuel#gmail.com 2022-01-19 19:44:06
Result: false 2022-01-19 19:44:06 Could not instantiate mail
function. 2022-01-19 19:44:06 Sending with mail() 2022-01-19
19:44:06 Sendmail path: 2022-01-19 19:44:06 Envelope sender:
nanguisamuel#gmail.com 2022-01-19 19:44:06 To:
nanguisamuel#gmail.com 2022-01-19 19:44:06 Subject: TEST LAMINAS
2022-01-19 19:44:06 Headers: Date: Wed, 19 Jan 2022 19:44:06 +0000
From: nanguisamuel#gmail.com
Reply-To: nanguisamuel#gmail.com
Message-ID: <bYYlElEH6jBVhViNmZY2Mpqd6EteZ1DLZKbNDK1O4#DESKTOP-D4AB8IN>
X-Mailer: PHPMailer 6.5.3 (https://github.com/PHPMailer/PHPMailer)
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: base64 2022-01-19 19:44:06 Additional params:
-fnanguisamuel#gmail.com
I have to say that when I call my custom class function with from my controllers, I get the e-mail in my localhost page for maildev but from the console I do not get anything.
Here are my code snippets :
My ConsoleGenerationRelances command :
<?php
declare(strict_types=1);
namespace Commun\Scripts;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
class ConsoleGenerationRelances extends Command
{
/** #var string */
private $mapper;
private $cronEnv;
private $MAIL;
protected static $defaultName = 'console-generation-relances';
public function __construct($mapper=[],$cronEnv=[],$MAIL=NULL){
$this->mapper = $mapper;
$this->cronEnv = $cronEnv;
$this->MAIL = $MAIL;
parent::__construct();
}
protected function configure() : void
{
$this->setName(self::$defaultName);
//$this->addOption('name', null, InputOption::VALUE_REQUIRED, 'Module name');
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$mapperAbonnementPrestation = $this->mapper['mapperAbonnementPrestation'];
$relances = $mapperAbonnementPrestation->getDataRelancesForConsole();
$output->writeln('Démarrage du script des relances |~> : '.date('Y-m-d H:i:s'));
$nbreJourAvantRelance = $this->cronEnv['cron'];
//$output->writeln(json_encode($this->MAIL));
foreach ($relances as $relance){
if(empty($nbreJourAvantRelance) || empty($relance['dateLimitePaiement']) ){ // Si parametre de relance non defini alors on saute l'execution
continue;
}
$now = strtotime(date('Y-m-d H:i:s')); // or your date as well
$dateLimitePaiement = strtotime($relance['dateLimitePaiement']);
$datediff = $now-$dateLimitePaiement;
$nombreJour = abs(round($datediff / 86400));
if($nombreJour<=$nbreJourAvantRelance){ // On envoie le mail
//sleep(10); //$this->MAIL->envoiMailCreationCompte(['emailTo' => ['nanguisamuel#gmail.com'],'nomPrenoms' => 'Samuel NANGUI','motDePasse' => 'test']); //On envoie un mail au user avec ses parametres
$this->MAIL->test(['nanguisamuel#gmail.com']);
}
}
$output->writeln('Fin du script des relances |~> : '.date('Y-m-d H:i:s'));
return 0;
}
}
Factory of my ConsoleGenerationRelances
<?php
declare(strict_types=1);
namespace Commun\Scripts\Factory;
use Commun\Scripts\ConsoleGenerationRelances;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Commun\Controller\Plugin\NslabsMail;
use Commun\Scripts\Mail\CronMail;
class ConsoleGenerationRelancesFactory implements FactoryInterface
{
/**
* #param ContainerInterface $container
* #param string $requestedName
* #param null|array $options
* #return $requestedName Entity
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$mappers = ['mapperAbonnementPrestation' => $container->get('TABONNEMENTPRESTATION')];
$mailConfig = $container->get('config')['sendMailParameters'];
$host = $mailConfig['host'];
$smtpSecure = $mailConfig['smtpSecure'];
$port = $mailConfig['port'];
$debug = $mailConfig['debug'];
$smtpAuth = $mailConfig['smtpAuth'];
$username = $mailConfig['username'];
$password = $mailConfig['password'];
$useSMTP = $mailConfig['useSMTP'];
return new ConsoleGenerationRelances($mappers,
$container->get('config'),
new CronMail(new NslabsMail($host,$smtpSecure,$port,$debug,$smtpAuth,$username,$password,$useSMTP))
);
}
}
My Custom CronMail class below :
<?php
/**
* #module Commun
* #subpackage Scripts/Mail
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2022 Nslabs
*/
namespace Commun\Scripts\Mail;
use Commun\Controller\Plugin\NslabsMail;
class CronMail
{
protected $classMail;
function __construct(NslabsMail $_classMail)
{
$this->classMail = $_classMail;
}
public function test($to){
$this->classMail->ajouterDestinataire($to);
$this->classMail->ajouterReplyTo('nanguisamuel#gmail.com');
$this->classMail->ajouterExpediteur('nanguisamuel#gmail.com');
$message = $this->classMail->enteteEmail()
.'Cher/Chère SAM,<br/><br/>'
."Ca marche avec PHP MAILER.<br/><br/>"
."<br/><br/>"
.$this->classMail->ajoutSignature();
try{
$this->classMail->setMessage('TEST LAMINAS', $message);
$this->classMail->send();
} catch (\Exception $e){
//var_dump($e->getMessage());
//die();
}
$this->classMail->clearAllAddressesAndAttachments();
}
public function envoiMailCreationCompte($params){
$this->classMail->ajouterDestinataire($params['emailTo']);
$this->classMail->ajouterReplyTo('nanguisamuel#gmail.com');
$this->classMail->ajouterExpediteur(EXPEDITEUR_MAIL_GENERAL);
$this->classMail->ajouterDestinaireCopieCarbone(['nanguisamuel#gmail.com']);
$message = $this->classMail->enteteEmail()
.'Cher/Chère ' . $params['nomPrenoms'] . ',<br/><br/>'
."Nous avons le plaisir de vous informer de la création de votre compte utilisateur avec le mot de passe suivant : ".$params['motDePasse']." <br/><br/>"
."Nous vous recommandons de le changer dès votre première connexion a la platefome.<br/>"
."<br/><br/>"
.$this->classMail->ajoutSignature();
try{
$this->classMail->setMessage('['.PORTAIL.'] Confirmation de création de compte utilisateur', $message);
$this->classMail->send();
} catch (\Exception $e){
//var_dump($e->getMessage());
//die();
}
$this->classMail->clearAllAddressesAndAttachments();
}
}
And finally my NslabsMail Class :
<?php
/**
* #module Commun
* #subpackage Controller/Plugin
* #author Samuel NANGUI <nanguisamuel#gmail.com>
* #copyright Copyright (c) 2020 Nslabs
*/
namespace Commun\Controller\Plugin;
Use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require APPLICATION_PATH.'/vendor/autoload.php';
class NslabsMail extends PHPMailer
{
/*private $host;
private $smtpAuth;
private $username;
private $password;
private $smtpSecure;
private $port;
private $debug;*/
public function __construct($host='localhost',$smtpSecure=PHPMailer::ENCRYPTION_SMTPS,$port=25,$debug=SMTP::DEBUG_SERVER,$smtpAuth=FALSE,$username=NULL,$password=NULL,$useSMTP=FALSE,$exceptions=null) {
parent::__construct($exceptions);
$this->Host = $host;
$this->SMTPAuth = $smtpAuth;
if($smtpAuth){
$this->Username = $username;
$this->Password = $password;
}
$this->SMTPSecure = $smtpSecure;
$this->Port = $port;
$this->SMTPDebug = $debug;
$this->CharSet = 'UTF-8';
$this->Encoding = 'base64';
if($useSMTP){
$this->isSMTP();
}else{
$this->isMail();
}
}
public function clearAllAddressesAndAttachments(){
$this->clearAddresses();
$this->clearAllRecipients();
$this->clearAttachments();
$this->clearBCCs();
$this->clearReplyTos();
$this->clearCCs();
}
public function ajouterExpediteur($email,$username=''){
$this->setFrom($email, $username);
}
public function ajouterDestinataire($adressesDestinataire=[]){
if(empty($adressesDestinataire)){
throw new Exception("Aucun destinaire précise");
}
foreach ($adressesDestinataire as $adresse){
$this->addAddress($adresse, !empty($adresse['username']) ? $adresse['username'] : '');
}
}
public function ajouterDestinataireCopie($adressesCC=[]){
if(!empty($adressesCC)){
foreach ($adressesCC as $adresse){
$this->addCC($adresse, !empty($adresse['username']) ? $adresse['username'] : '');
}
}
}
public function ajouterReplyTo($email){
$this->addReplyTo($email);
}
public function ajouterDestinaireCopieCarbone($adressesBCC=[]){
if(!empty($adressesBCC)){
foreach ($adressesBCC as $adresse){
$this->addBCC($adresse, !empty($adresse['username']) ? $adresse['username'] : '');
}
}
}
public function ajouterPiecesJointes($attachments=[]){
if(!empty($attachments)){
foreach ($attachments as $file){
$this->addAttachment($file);
}
}
}
public function setMessage($subject='',$message='',$isHTML=TRUE){
$this->Subject = $subject;
$this->Body = $message;
$this->isHTML($isHTML);
}
public function enteteEmail() {
$str =
'<div style="width:600px;">'.
'<div style="font-family:Arial;font-size:11px;">'.
//'<img style="margin-bottom:5px" src="'.$racine_site.'/'.$baseUrl->baseUrl('/img/logo/logo-dgi-email.png').'"><br />'.
'<span style="color:#fdd116;font-size:18px;font-weight:bold">'.PORTAIL.'</span>
<p style="color:#009177;">
Ceci est un email envoyé automatiquement par '.PORTAIL.'.<br/>
</p>
<hr style="color:#009177;">
<br/>
</div>'
.'<div style="font-family:Arial;">'
;
return $str;
}
public function ajoutSignature() {
$str =
'</div>'. // ouvert dans l'entete
'<br/>'.
'<br/>'.
'<div style="font-family:Arial;font-size:11px;">'.
'<span style="font-size:16px;font-weight:bold;margin-bottom:5px;">'.NSLabs.'</span><br/>'.
'<span style="font-size:14px;font-weight:bold;color:#d03630;">'.PORTAIL.'</span>'.
'<p style="margin-top:10px;color:grey;">Pour nous contacter :<br/>'.
'<span style="font-weight:bold;color:grey;">Tél : '.SIGNATURE_MAIL_TELEPHONE .'</span><br/>'.
'<span style="font-weight:bold;color:grey;">Email : '.SIGNATURE_MAIL_EMAIL_CONTACT.'</span><br/>'.
'<br/>'.
SIGNATURE_MAIL_ADRESSE1.'<br/>'.
'</p>'.
$this->warningNoRetour().
'</div>'.
'</div>'
;
return $str;
}
public function warningNoRetour() {
$str =
'<hr>'.
'<span style="font-size:14px;font-weight:bold;color:red">Attention aux emails frauduleux ! </span><br/>'.
'<p style="color:red;">
Pour votre sécurité, ne répondez jamais à un e-mail vous demandant vos identifiants de connexion et/ou vos comptes de paiement, <br/>
et/ou vous informant d’un changement vos identifiants de connexion.'.
'</p>'
;
return $str;
}
}
Any help will be very appreciated

App\Entity\Site object not found by the #ParamConverter annotation

I'm trying to create a new tempate in my project in symfony to put a climbing converter. But it doesn't work. I have the error:
App\Entity\Site object not found by the #ParamConverter annotation
I put the function in the entity "site" as following :
/**
* #Route("/site")
*/
class SiteController extends AbstractController
{
public function upload( KernelInterface $kernel): Response
{
$imagesDir = $kernel->getProjectDir().'/public/uploads'; // équivalent à $this->getParameter('images_directory')
dump($imagesDir) ;
return $this->render('site/show.html.twig');
}
/**
* #Route("/", name="site_index", methods={"GET"})
*/
public function index(SiteRepository $siteRepository): Response
{
return $this->render('site/index.html.twig', [
'sites' => $siteRepository->findAll(),
]);
}
/**
* #Route("/new", name="site_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$site = new Site();
$form = $this->createForm(SiteType::class, $site);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//on recupère les medias transmises
$media = $form->get('site')->getData();
//on boucle sur les medias
foreach($media as $medi){
//on génère un nouveau nom de fichier
$fichier = md5(uniqid()) . '.' . $medi->guessExtension();
//on copie le fichier dans le dossier img
$medi->move(
$this->getParameter('images_directory'),
$fichier
);
//on stocke l'image dans la bdd
$img = new Media();
$img->setNom($fichier);
$site->addMedium($img);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($site);
$entityManager->flush();
return $this->redirectToRoute('site_index');
}
return $this->render('site/new.html.twig', [
'site' => $site,
'form' => $form->createView(),
]);
}
/**
* #Route("/{id}", name="site_show", methods={"GET"})
*/
public function show(Site $site, MediaRepository $mediarepository, $id): Response
{
$media = $mediarepository->findBy(
['site'=>$id]
);
return $this->render('site/show.html.twig', [
'site' => $site,
'media' => $media,
]);
}
/**
* #Route("/{id}/edit", name="site_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Site $site): Response
{
$form = $this->createForm(SiteType::class, $site);//j'appelle le form
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//on recupère les medias transmises
$media = $form->get('site')->getData();
//on boucle sur les medias
foreach($media as $medi){
//on génère un nouveau nom de fichier
$fichier = md5(uniqid()) . '.' . $medi->guessExtension();
//on copie le fichier dans le dossier img
$medi->move(
$this->getParameter('images_directory'),
$fichier
);
//on stocke l'image dans la bdd
$img = new Media();
$img->setNom($fichier);
$site->addMedium($img);
}
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('site_index');
}
return $this->render('site/edit.html.twig', [
'site' => $site,
'form' => $form->createView(),
]);
}
/**
* #Route("/{id}", name="site_delete", methods={"POST"})
*/
public function delete(Request $request, Site $site): Response
{
if ($this->isCsrfTokenValid('delete'.$site->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($site);
$entityManager->flush();
}
return $this->redirectToRoute('site_index');
}
/**
* #Route("/conv", name="site_converter")
*/
public function converter():Response
{
return $this->render('site/converter.html.twig');
}
}
I checked others answers about this problem, but I still can't find out the solution. Do you have any ideas?
I put some more code so that it would be easier to understand. I hope this would be usefull. It's the route for converter that makes me problem. Thanks
This happens because you have a route called /conv, you should declare it before declaring /{id} route, instead Symfony searches for a Site object with id: conv which is not found.
Move converter route and method declaration before your show route and method declaration.

Symfony 4 relation ManyToOne return only id not the whole objet

hello I have two entity Patient and Appointement I work with Api platform and the relation between Appointement and Patient is ManyToOne when I try to get Appointement I get only the id of patient not the whole objet
My function get
/**
* #Route("/appointement", methods={"GET"})
*/
public function findAppointement(AppointementRepository $appointementRepository,SerializerInterface $serializer)
{
//AVOIR AU MOINS LE ROLE_SECRETAIRE POUR RECUPERER LES APPOINTEMENT
$this->denyAccessUnlessGranted('ROLE_SECRETAIRE',null,"Accès non autorisé");
$appointement= $appointementRepository->findAll();
$data=$serializer->serialize($appointement,"json", [
'circular_reference_handler' => function ($object) {
return $object->getId();
}
]);
return new JsonResponse($data,Response::HTTP_OK,[],true);
}
My Patient entity
/**
* #ORM\OneToMany(targetEntity="App\Entity\Appointement", mappedBy="patient")
*/
private $appointements;
/**
* #ORM\OneToMany(targetEntity="App\Entity\PatientData", mappedBy="patient")
*/
private $patientData;
public function __construct()
{
$this->appointements = new ArrayCollection();
$this->patientData = new ArrayCollection();
}
My Appointement entity
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Patient", inversedBy="appointements")
* #ORM\JoinColumn(nullable=false)
*/
private $patient;
thank you
You are only getting the id because you defined your circular_reference_handler to only get the id. You can modify it and get more information from your patient.
$data=$serializer->serialize($appointement,"json", [
'circular_reference_handler' => function ($object) {
if($object instanceof Patient){
return ['value1' => $object->getValue1(), 'value2' => $object->getValue2()]
}
return $object->getId();
}
]);

fosuserbundle: set api key using event listner

I'm using symfony 2.3 and FosUserBundle ~2.0#dev. I want to set an api key for every user after a success registration. I implemented an event listner for this purpose but it doesn't work. I didn't find where is exactly the problem.
RegistrationConfirmListener
class RegistrationConfirmListener implements EventSubscriberInterface {
private $router;
private $em;
public function __construct(UrlGeneratorInterface $router, \Doctrine\ORM\EntityManager $em) {
$this->em = $em;
$this->router = $router;
}
/**
* {#inheritDoc}
*/
public static function getSubscribedEvents() {
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess'
);
}
public function onRegistrationSuccess(\FOS\UserBundle\Event\FormEvent $event) {
$user = $event->getForm()->getData();
// génération d'un unique key ,ici on a le id comme prefix donc garantie pas de duplication du key
$user->setApiKey(md5(uniqid($user->getId(), TRUE)));
$url = $this->router->generate('biginfo_admin_homepage');
$event->setResponse(new RedirectResponse($url));
}
}
service.yml
services:
biginfo_user.registration_complet:
class: Biginfo\UserBundle\EventListener\RegistrationConfirmListener
arguments: [#router,#doctrine.orm.entity_manager]
tags:
- { name: kernel.event_subscriber}
You should listen for FOSUserEvents::REGISTRATION_SUCCESS event. Because REGISTRATION_COMPLETED event listener method receives a FOS\UserBundle\Event\FilterUserResponseEvent instance, which is not fit for your situation.

Inject a flash on specific exception

I'm extending a custom exception for all my handled "application errors"
abstract class AbstractApplicationException extends \Exception
{
public function __construct(array $context = array())
{
$this->context = $context;
parent::__construct('exceptions.'.lcfirst(self::classname()));
}
}
And I use messages.xx.yml to describe the error to the user
exceptions:
incompatibleSettings: Vos réglages ne sont pas compatibles
I'd like to automatically inject a flash with the translated message on exception (of kind AbstractApplicationException) so I don't have to do it on all my controllers
public myControllerAction()
try {
$someService->someFunction();
} catch (AbstractApplicationException $e) {
$flashBag->add('error',
$this->get('translator')->trans(
$e->getMessage(), $e->getContext()
)
);
}
$this->render('related_template.html.twig');
}
I know how to redirect the user with a listener, but I actually want the user to land on the specific action reponse, only with a flash injected.
You can create an Exception listener:
# app/config/services.yml
services:
kernel.listener.your_listener_name:
class: AppBundle\EventListener\AcmeExceptionListener
arguments: [#router, #session]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
Then set flash message and redirect user to the action you want, which will render it:
class AcmeExceptionListener
{
/**
* #var UrlGeneratorInterface
*/
private $router;
/**
* #var SessionInterface
*/
private $session;
public function __construct(UrlGeneratorInterface $router, SessionInterface $session)
{
$this->router = $router;
$this->session = $session;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof YourExceptionType) {
$this->session->getFlashBag()->add('error', $exception->getMessage());
$event->setResponse(new RedirectResponse($this->router->generate('your_route')));
}
}
}
Be careful with this though: if during exception handling you again throw YourExceptionType, you will end up having infinite redirect loop.
I finally used a trait to be able to continue the execution of my controllers with the flash injected.
/**
* Class ControllerTrait
* #requirement The using class must be containerAware
*/
trait ControllerTrait {
public function injectExceptionFlash(AbstractApplicationException $e) {
if (!isset($this->container)) {
throw new \Exception(sprintf('You must containerAware to use %s',
__TRAIT__
));
}
$flashBag = $this->container->get('session')->getFlashBag();
$flashBag->add('error',
$this->container->get('translator')->trans(
$e->getMessage(), $e->getContext()
)
);
}
public function tryFlash($lambda) {
try {
$lambda();
} catch (AbstractApplicationException $e) {
$this->injectExceptionFlash($e);
}
}
}
Here is how I use it from my controllers
use ControllerTrait;
public myControllerAction()
$this->tryFlash(function () (use $someParam) {
$someService->someFunction($someParam);
});
$this->render('related_template.html.twig');
}
tryFlash() is a shortcut using a lambda function to do the try/catch/flash jobs
Don't hesitate to tell me if there is a bad practice somewhere

Resources