Getting value from a twig to a controller - symfony

I'm using Symfony2 and my view is a twig/php. Can I get a value from a view? I tried like this:
listcurrency.twig.html:
{% for currency in liste %}
<TR>
<TH> <a href="{{ path('devises_disable', { 'id': currency.id }) }}"> {{currency.id}} </TH>
<TD> {{ currency.Name}} </TD>
<TD> {{currency.Enabled}}</TD>
</TR>
{% endfor %}
I call a route 'devises_disable' and pass a parameter currency.id.
EDIT:this is what i do with the value:
controller:
public function disableAction($id)
{
$em = $this->getDoctrine()->getManager();
$currency = $em->getRepository('DevisesBundle:Currency')->findOneById($id);
if (!$currency) {
throw $this->createNotFoundException(
'Aucun currency trouvée pour cet id : '.$id
);
}
$i=$currency->getEnabled();
if($i==0){$i=1;}else if($i==1){$i=0;}
$currency->setEnabled($i);
$em->flush();
$em->refresh($currency);
}
the route:
devises_disable:
path: /webmaster/listcurrency
defaults: {_controller: DevisesBundle:Default:disable}
the entity i'm trying to update doesn't change.No error message too!!

Try changing your route into :
devises_disable:
path: /webmaster/listcurrency/{id}
defaults: {_controller: DevisesBundle:Default:disable}
For checking the variable success or not passed into your controller put this in top of your controller :
echo 'This is the variable : '.$id;

Related

Symfony Twig : get Object property with a variable property

Symfony 3.0 :
In my project, I have many entities which contain more than 50 fields, so for the twig which shows every entity, I decided to automate the display of the 50 fields by a simple loop.
First problem: how to get entity's all fields names, I resolved this by creating a custom twig filter:
<?php
// src/HomeBundle/Twig/HomeExtension.php
namespace HomeBundle\Twig;
class HomeExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('object_keys', array($this, 'getObjectKeys')),
);
}
public function getObjectKeys($object)
{
//Instantiate the reflection object
$reflector = new \ReflectionClass( get_class($object) );
//Now get all the properties from class A in to $properties array
$properties = $reflector->getProperties();
$result=array();
foreach ($properties as $property)
$result[] = $property->getName();
return $result;
}
public function getName()
{
return 'app_extension';
}
}
?>
The second problem which generates the error right now is: how to access object properties within a loop:
{% for property in article|object_keys%}
<tr>
<th>
{{property|capitalize}}
{# that's work clean #}
</th>
<td>
{{ attribute(article,property) }}
{# that's generate the error #}
</td>
</tr>
{% endfor %}
The error :
An exception has been thrown during the rendering of a template
("Notice: Array to string conversion"). 500 Internal Server Error -
Twig_Error_Runtime
Finally, the error is fixed on the getObjectKeys method of the filter,
so when it returns an array that I create manually it works:
return array("reference","libelle");
But, when I send an array created within a loop => Error.
I dumped the two arrays in the twig, they were equivalents, but the second still generating an error.
Most likely one of your properties is returning an array rather than a simple string, integer, .... A solution here could be to store the value in a variable and check whether the stored value is an array. Depending on that check do something with the value or otherwise just output the variable
{% for property in article|object_keys%}
<tr>
<th>
{{property|capitalize}}
</th>
<td>
{% set value = attribute(article,property) %}
{% if value is iterable %}{# test if value is an array #}
{{ value | join(', ') }}
{% else %}
{{ value }}
{% endif %}
</td>
</tr>
{% endfor%}

Twig and Doctrine- Count each related entity and display in Twig loop

I have a one to many relationship in doctrine.I want to count each related field and display them in Twig for loop
so far
A Vp is related to Voters.Vp has many Voters and Voters has one Vp
I want to count each related Voters per Vp
public function getAllVp()
{
return $this
->createQueryBuilder('v')
->select('vp.id,COUNT(v.id) as num')
->from('Voters', 'v')
->join('v.Vp', 'vp')
->orderBy('v.id', 'ASC')
->getQuery()
->getResult()
;
}
I want this in Twig like
{% for vp in vps %}
{{ vp.firstname }}
{{ vp.num }}//number of voters
{% endfor %}
controller
$vice_president = $em->getRepository('Bundle:Vp')->getAllVp();
return $this->render('Bundle:Vp:all_vp.html.twig', array(
'vps' => $vice_president,
));
doctrine
fields:
firstname:
type: string
length: 255
lastname:
type: string
length: 255
photo:
type: string
length: 255
oneToMany:
voters:
targetEntity: Voters
mappedBy: vp
I got this error
[Semantical Error] line 0, col 94 near 'vp, Voters v': Error: Class Project\Bundle\DuterteBundle\Entity\Vp has no association named Vp
How to correctly achieve this in Doctrine?
Update
voters.orm.yml
manyToOne:
vp:
targetEntity: Vp
cascade: { }
mappedBy: null
inversedBy: voters
joinColumn:
name: vp_id
referencedColumnName: id
orphanRemoval: false
I can achieved this by simply calling the related 'voters' and add a filter in Twig.But my intention is to count the data in doctrine, reuse it in other templates or convert it to json for the future,e.g in Angular JS
{% if vp.voters|length > 0 %}
<tr {% if loop.index is odd %}class="color"{% endif %}>
<td>{{ vp.id }}</td>
<td>{{ vp.getFullName() }}</td>
<td>{{ vp.voters|length|number_format }}</td>
</tr>
{% endif %}
Above is a working code but I want to do the count in Doctrine , not in template
Expected result
id fullname counts
1 George Bush 45
2 ali gail 1999
4 Mae Young 45
......
First of all, you can remove mappedBy: null in your Voter mapping.
PHP oriented :
Ok you can try this PHP solution to add a new method in your entity Vp like :
public function getVotersCount(){
return count($this->voters);
}
And in your twig view you can do :
{{ vp.getVotersCount() }}
Doctrine oriented : (http://docs.doctrine-project.org/en/latest/reference/events.html#lifecycle-events)
In your Vp Entity orm mapping :
fields:
firstname:
type: string
length: 255
lastname:
type: string
length: 255
photo:
type: string
length: 255
oneToMany:
voters:
targetEntity: Voters
mappedBy: vp
lifecycleCallbacks:
postLoad: [ countVotersOnPostLoad ]
And also a new attribute, a getter and countVoters method :
protected $votersCount;
public function getVotersCount(){
return $this->votersCount;
}
public function countVotersOnPostLoad ()
{
$this->votersCount = count($this->voters);
}
And in your view, simply do :
{{ vp.votersCount }}
My work around for this is to create a service.
<?php
namespace Project\Bundle\DutBundle\Twig;
class AllVpExtension extends \Twig_Extension
{
protected $em;
public function __construct($em)
{
this->em = $em;
}
public function getFunctions()
{
return array(
//this is the name of the function you will use in twig
new \Twig_SimpleFunction('number_votes_vp', array($this, 'b'))
);
}
public function getName()
{
//return 'number_employees';
return 'vp_app_extension';
}
public function b($id)
{
$qb=$this->em->createQueryBuilder();
$qb->select('count(v.id)')
->from('DutBundle:Voters','v')
->join('v.vp','c')
->where('c.id = :x')
->setParameter('x',$id);
$count = $qb->getQuery()->getSingleScalarResult();
return $count;
}
}
Now in order to count each vp's related voters, I can call a service and send the result to twig
public function all_vpAction()
{
$em = $this->getDoctrine()->getManager();
$vice_president = $em->getRepository('DutBundle:Vp')->findAll();
//communicate to service container
$data = $this->container->get('duterte.twig.vp_app_extension');
$datas = array();
foreach ($vice_president as $value) {
$datas[] = array('id' => $value->getId(),'firstname' => $value->getFirstname() . ' ' . $value->getLastname(),'numbers' => (int)$data->b($value->getId()));
}
$vice = $datas;
return $this->render('DutBundle:Vp:all_vp.html.twig', array(
'vps' => $vice,
));
//or we can wrap this in json
$serializer = $this->container->get('jms_serializer');
$jsonContent= $serializer->serialize($vice,'json');
return $jsonContent;
}
With this set up, I can wrap this into json and and using custom twig filter, I can display data sorted either in Angular or in plain Twig template or both
By the way, my view
{% extends '::base.html.twig' %}
{% block body %}
{% block stylesheets %}
{{ parent() }}
<style type="text/css">
#img-responsive{
height: 320px;
/*width: 300px;*/
}
</style>
{% endblock %}
<div class="section-heading">
<h2>Best Tandem Of the Day</h2>
</div>
<div class="row">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img src="/img/dut.jpg" id="img-responsive">
<div class="caption">
<h3>President</h3>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img src="/img/unknown.jpg" id="img-responsive">
<div class="caption">
<h3>Vice-President</h3>
</div>
</div>
</div>
</div>
<hr />
<div ng-app="myApp" ng-controller="customersCtrl">
Search Here: <input type="text" placeholder="search" ng-model="searchMe"/><br />
<table class="table">
//names//
<thead>
<tr>
<th>Full Name</th>
<th>Middlename</th>
<th>Lastname</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in names">
<td>//x.id//</td>
<td>//x.firstname//</td>
<td>//x.numbers//</td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table table-hover table-bordered table-condensed" id="table1">
<thead>
<tr>
<th>#</th>
<th>Bet</th>
<th>Votes</th>
<!--th>Photo</th-->
</tr>
</thead>
<tbody>
{% for v in vps | sortbyfield('numbers') %}
{% if v.numbers > 0 %}
<tr>
<td>{{ v.id }}</td>
<td>{{ v.firstname }}</td>
<td>{{ v.numbers }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="//code.angularjs.org/1.4.8/angular.js"></script>
<script>
var app = angular.module('myApp', []);
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
});
app.controller('customersCtrl',['$scope','$http',function($scope, $http) {
$http.get("{{ path('vp_president') }}")
.success(function (response) {
$scope.names= JSON.parse(response);
});
</script>
{% endblock %}

Display image stored in BLOB database in symfony

I load my image (blob data ) in my GETer Entity
When I just return ($this->foto) in my GETer I see :Resource id #284 on the screen
When I change my GETer like this : return stream_get_contents($this->foto);
I see these : ���JFIF��� ( ,,,,,,,, ( and more )
In my Controller a call the index.html.twig to show all my entities
/**
* Lists all Producten entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CustomCMSBundle:Producten')->findAll();
return $this->render('CustomCMSBundle:Producten:index.html.twig', array(
'entities' => $entities,
));
}
Now in my views ( index.html.twig ) I like to show the picture
{% for entity in entities %}
<tr>
<td>
<img src="{{ entity.foto}}" alt="" width="80" height="80" />
</td>
<td>
{{ entity.foto }}
</td>
<td>
<ul>
<li>
show
</li>
<li>
edit
</li>
</ul>
</td>
</tr>
{% endfor %}
But I don't see the picture ?
Can anyone help me?
You are using <img src="(raw image)"> instead of <img src="(image's url)">
A quick solution is to encode your image in base64 and embed it.
Controller
$images = array();
foreach ($entities as $key => $entity) {
$images[$key] = base64_encode(stream_get_contents($entity->getFoto()));
}
// ...
return $this->render('CustomCMSBundle:Producten:index.html.twig', array(
'entities' => $entities,
'images' => $images,
));
View
{% for key, entity in entities %}
{# ... #}
<img alt="Embedded Image" src="data:image/png;base64,{{ images[key] }}" />
{# ... #}
{% endfor %}
in your entity write your image getter like this:
public function getFoto()
{
return imagecreatefromstring($this->foto);
}
and use it instead of the object "foto" property.
php doc for the function: http://php.net/manual/de/function.imagecreatefromstring.php
A more direct way, without extra work in the controller:
In the Entity Class
/**
* #ORM\Column(name="photo", type="blob", nullable=true)
*/
private $photo;
private $rawPhoto;
public function displayPhoto()
{
if(null === $this->rawPhoto) {
$this->rawPhoto = "data:image/png;base64," . base64_encode(stream_get_contents($this->getPhoto()));
}
return $this->rawPhoto;
}
In the view
<img src="{{ entity.displayPhoto }}">
EDIT
Thanks to #b.enoit.be answer to my question here, I could improve this code so the image can be displayed more than once.
As it is said before you must use base64 method, but for a better performance and usability, the correct option is creating a custom twig filter (Twig extension) as described here .
<?php
namespace Your\Namespace;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class TwigExtensions extends AbstractExtension
{
public function getFilters()
{
return [
new TwigFilter('base64', [$this, 'twig_base64_filter']),
];
}
function twig_base64_filter($source)
{ if($source!=null) {
return base64_encode(stream_get_contents($source));
}
return '';
}
}
In your template:
<img src="data:image/png;base64,{{ entity.photo | base64 }}">

send in link id of username symfony2

want to send an email from my Symfony2 application, this email must contain a link of confirmation and when the user clicks on this link the state of a field in DB to change.
i have this in my controller:
$message = \Swift_Message::newInstance()
->setSubject('demande de conge ')
->setFrom($col->getEmailCollaborateur())
->setTo($form->get("emailcdp")->getData())
->setBody($this->render('AcmeBundle:Conge:demandeCongeNormal.html.twig', array('conge' => $conge, 'id'=> $this->getUser()->getId())))
;
$this->get('mailer')->send($message);
in the twig :
id de collab: {{ id }}
pour confirmer la demande :
{{ url('confirmer_conge' ,{'username': ' id '}) }}
but in the Email i have this :
http://local.symfony2.com/app_dev.php/confirm/?username=+id+
i want to get the id of user that send the message in another controller for update my DB
in my routing.yml:
confirmer_conge:
pattern: /confirm/{username}
defaults: { _controller: acmeBundle:Conge:confirme }
and in the controller i have this function:
public function confirmeAction()
{return $this->render('acmeBundle:Conge:confirmer.html.twig');
}
Remove the quotes from around id, it is a variable.
{{ url('confirmer_conge', {'username': id}) }}
As for accessing the ID in your controller it should work like this:
public function confirmeAction($username)
//...
}

symfony2 form is not displaying

I am learning symfony2 and i have created one form in controller which is as bellow.
the controller file as DefaultController.php
namespace Banner\TestBundle\Controller;
use Banner\TestBundle\Entity\Contact;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Banner\TestBundle\Entity\Task;
use Symfony\Components\HttpFoundation\Request;
class DefaultController extends Controller
{
public function newAction(Request $request)
{
echo "The controller is called ";
$task = new Task();
$task->setTask("Write a blog Post ");
$task->setDueDate(new DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task','text ')
->add('duedate','date')
->getForm();
return $this->render('BannerTestBundle:default:zoo.html.twig',array('form'=>$form->createView()));
}
}
my routing file is as below.
routing.yml
task_new:
pattern: /task/{request}
defaults: { _controller: BannerTestBundle:Default:new}
and the zoo.html.twig file is as bellow.
{% extends '::page.html.twig' %}
{% block title %}The Zoo{% endblock %}
{% block content %}
<form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit">
</form>
{% endblock %}
as i am passing the "task/GET" in my url it will shows the 'Request does not exist. error 500'.
what i basically want to do is when i pass the url the zoo.html.twig will be called. i want to display the form in zoo.html.twig.
You don't need to pass $request to your action and you don't need to put it in your route. The request object is available in global context. So
task_new:
pattern: /task-new
defaults: { _controller: BannerTestBundle:Default:new}
You can either leave it this way
public function newAction(Request $request)
or have
public function newAction()
and access request object like this
$request = $this->getRequest();
Your routing file is not properly indented so the yaml will not parse properly. Try:
task_new:
pattern: /task/{request}
defaults: { _controller: BannerTestBundle:Default:new}
Also:
It is probably a bad idea to override request that way
You don't appear to be doing anything with request in your controller

Resources