问题
I'm working on a Symfony 3 website and I need to call a URL of my website with a cron job.
My website is hosted on OVH where I can configure my cron job.
For now, I have setup the command : ./demo/Becowo/batch/emailNewUser.php
emailNewUser.php content :
<?php
header("Location: https://demo.becowo.com/email/newusers");
?>
In the log I have :
[2017-03-07 08:08:04] ## OVH ## END - 2017-03-07 08:08:04.448008 exitcode: 0
[2017-03-07 09:08:03] ## OVH ## START - 2017-03-07 09:08:03.988105 executing: /usr/local/php5.6/bin/php /homez.2332/coworkinwq/./demo/Becowo/batch/emailNewUser.php
But emails are not sent. How should I configure my cron job to execute this URL ? Or should I call directly my controller ? How ?
回答1:
ok, finally it works !!!
Here are the step I followed for others :
1/ You need a controller to send emails :
As the controller will be called via command, you need to injec some services
em : entity manager to flush data
mailer : to access swiftMailer service to send the email
templating : to access TWIG service to use template in the email body
MemberController.php
<?php
namespace Becowo\MemberBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Becowo\CoreBundle\Form\Type\ContactType;
use Becowo\CoreBundle\Entity\Contact;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
class MemberController extends Controller
{
private $em = null;
private $mailer = null;
private $templating = null;
private $appMember = null;
public function __construct(EntityManager $em, $mailer, EngineInterface $templating, $appMember)
{
$this->em = $em;
$this->mailer = $mailer;
$this->templating = $templating;
$this->appMember = $appMember;
}
public function sendEmailToNewUsersAction()
{
// To call this method, use the command declared in Becowo\CronBundle\Command\EmailNewUserCommand
// php bin/console app:send-email-new-users
$members = $this->appMember->getMembersHasNotReceivedMailNewUser();
$nbMembers = 0;
$nbEmails = 0;
$listEmails = "";
foreach ($members as $member) {
$nbMembers++;
if($member->getEmail() !== null)
{
$message = \Swift_Message::newInstance()
->setSubject("Hello")
->setFrom(array('toto@xxx.com' => 'Contact Becowo'))
->setTo($member->getEmail())
->setContentType("text/html")
->setBody(
$this->templating->render(
'CommonViews/Mail/NewMember.html.twig',
array('member' => $member)
))
;
$this->mailer->send($message);
$nbEmails++;
$listEmails = $listEmails . "\n" . $member->getEmail() ;
$member->setHasReceivedEmailNewUser(true);
$this->em->persist($member);
}
}
$this->em->flush();
$result = " Nombre de nouveaux membres : " . $nbMembers . "\n Nombre d'emails envoyes : " . $nbEmails . "\n Liste des emails : " . $listEmails ;
return $result;
}
}
2/ Call you controller as a service
app/config/services.yml
app.member.sendEmailNewUsers :
class: Becowo\MemberBundle\Controller\MemberController
arguments: ['@doctrine.orm.entity_manager', '@mailer', '@templating', '@app.member']
3/ Create a console command to call your controller
Doc : http://symfony.com/doc/current/console.html
YourBundle/Command/EmailNewUserCommand.php
<?php
namespace Becowo\CronBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
class EmailNewUserCommand extends ContainerAwareCommand
{
protected function configure()
{
// the name of the command (the part after "php bin/console")
$this->setName('app:send-email-new-users')
->setDescription('Send welcome emails to new users')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// outputs a message to the console followed by a "\n"
$output->writeln('Debut de la commande d\'envoi d\'emails');
// access the container using getContainer()
$memberService = $this->getContainer()->get('app.member.sendEmailNewUsers');
$results = $memberService->sendEmailToNewUsersAction();
$output->writeln($results);
}
}
4/ Test your command !
In the console, call you command : php bin/console app:send-email-new-users
5/ Create a script to run the command
Doc (french) : http://www.christophe-meneses.fr/article/deployer-son-projet-symfony-sur-un-hebergement-perso-ovh
..Web/Batch/EmailNewUsers.sh
#!/bin/bash
today=$(date +"%Y-%m-%d-%H")
/usr/local/php5.6/bin/php /homez.1111/coworkinwq/./demo/toto/bin/console app:send-email-new-users --env=demo > /homez.1111/coworkinwq/./demo/toto/var/logs/Cron/emailNewUsers-$today.txt
Here it took me some time to get the correct script.
Take care of php5.6 : it has to match your PHP version on OVH
Don't forget to upload bin/console file on the server
homez.xxxx/name has to match with your config (I found mine on OVH, and then in the logs)
IMPORTANT : when you upload the file on the server, add execute right (CHMOD 704)
6/ Create the cron job in OVH
Call your script with the command : ./demo/Becowo/web/Batch/EmailNewUsers.sh
Language : other
7/ Wait !
You need to wait for the next run. Then have a look on OVH cron logs, or on your own logs created via the command in the .sh file
It took me several days to get it.. Enjoy !!
回答2:
As commented above, you should do it with a symfony commaad. This is an example for you.
NOTE: Although it is working, you can always improve this example. Especially the way command calls your endpoint.
Controller service definition:
services:
yow_application.controller.default:
class: yow\ApplicationBundle\Controller\DefaultController
Controller itself
namespace yow\ApplicationBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Response;
/**
* @Route("", service="yow_application.controller.default")
*/
class DefaultController
{
/**
* @Method({"GET"})
* @Route("/plain", name="plain_response")
*
* @return Response
*/
public function plainResponseAction()
{
return new Response('This is a plain response!');
}
}
Command service definition
services:
yow_application.command.email_users:
class: yow\ApplicationBundle\Command\EmailUsersCommand
arguments:
- '@http_kernel'
tags:
- { name: console.command }
Command itself
namespace yow\ApplicationBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class EmailUsersCommand extends Command
{
private $httpKernel;
public function __construct(HttpKernelInterface $httpKernel)
{
parent::__construct();
$this->httpKernel = $httpKernel;
}
protected function configure()
{
$this->setName('email:users')->setDescription('Emails users');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$request = new Request();
$attributes = [
'_controller' => 'yow_application.controller.default:plainResponseAction',
'request' => $request
];
$subRequest = $request->duplicate([], null, $attributes);
$response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
$output->writeln($response);
}
}
Test
$ php bin/console email:users
Cache-Control: no-cache, private
X-Debug-Token: 99d025
X-Debug-Token-Link: /_profiler/99d025
This is a plain response!
1.0
200
OK
来源:https://stackoverflow.com/questions/42643974/trigger-an-url-with-a-cron-job