I'm building a Symfony application and when I work on it, it is too slow. I have wondering what can cause this so I went in the profiler timeline to see what is going on but I was amazed that all those classes have very big data 10 MB, 22 MB and so on. See the picture:
This is my Object bundle. The yellow is my own class with my twigs. I do not understand what is this delay and what is this big data.... Can someone explain to me what is going on and how can be optimized this because on a production if it is like now it is too slow... Total time 3962 ms
Here is the controller - nothing fancy generate from the console with minor changes:
<?php
namespace George\ObjectsBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use George\ObjectsBundle\Entity\Object;
use George\ObjectsBundle\Form\ObjectType;
/**
* Object controller.
*
* #Route("/admin/object")
*/
class ObjectController extends Controller
{
/**
* Lists all Object entities.
*
* #Route("/", name="object")
* #Method("GET")
* #Template()
*/
public function indexAction(Request $request)
{
$session = $request->getSession();
$locale = $request->getLocale();
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('ObjectsBundle:Object')->findAll();
// echo $locale;
/*
$category = new Object();
$category->translate('bg')->setTitle('Chaussures');
$category->translate('en')->setTitle('Shoes');
$category->translate('bg')->setDescription('Chaussures');
$category->translate('en')->setDescription('Shoes');
$category->translate('bg')->setAddress('Chaussures');
$category->translate('en')->setAddress('Shoes');
$category->setMode('a');
$category->setLat('12');
$category->setLongt('12');
echo $category->translate('bg')->getTitle();
$category->mergeNewTranslations(); $em->persist($category);
$em->flush();
*/
return array(
'entities' => $entities,
);
}
/**
* Creates a new Object entity.
*
* #Route("/", name="object_create")
* #Method("POST")
* #Template("ObjectsBundle:Object:new.html.twig")
*/
public function createAction(Request $request)
{
$entity = new Object();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('object'));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Creates a form to create a Object entity.
*
* #param Object $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Object $entity)
{
$form = $this->createForm(new ObjectType(), $entity, array(
'action' => $this->generateUrl('object_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new Object entity.
*
* #Route("/new", name="object_new")
* #Method("GET")
* #Template()
*/
public function newAction()
{
$entity = new Object();
$form = $this->createCreateForm($entity);
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
/**
* Finds and displays a Object entity.
*
* #Route("/{id}", name="object_show")
* #Method("GET")
* #Template()
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
);
}
/**
* Displays a form to edit an existing Object entity.
*
* #Route("/{id}/edit", name="object_edit")
* #Method("GET")
* #Template()
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Creates a form to edit a Object entity.
*
* #param Object $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Object $entity)
{
$form = $this->createForm(new ObjectType(), $entity, array(
'action' => $this->generateUrl('object_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$form->add('submit', 'submit', array('label' => 'Update'));
return $form;
}
/**
* Edits an existing Object entity.
*
* #Route("/{id}", name="object_update")
* #Method("PUT")
* #Template("ObjectsBundle:Object:edit.html.twig")
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('object_edit', array('id' => $id)));
}
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
/**
* Deletes a Object entity.
*
* #Route("/{id}", name="object_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ObjectsBundle:Object')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Object entity.');
}
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('object'));
}
/**
* Creates a form to delete a Object entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('object_delete', array('id' => $id)))
->setMethod('DELETE')
->add('submit', 'submit', array('label' => 'Delete'))
->getForm();
}
}
The main twig for the admin:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block title -%}<title>Admin</title>{% endblock %}
{% block stylesheets %}
{% stylesheets
'#CoreBundle/Resources/public/css/*' %}
<link href="{{ asset(asset_url) }}" rel="stylesheet">
{% endstylesheets %}
{% endblock %}
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
</head>
<body>
{% block menu -%} {% endblock %}
{% block body -%} {% endblock %}
{% block javascripts -%}
{% javascripts
'#CoreBundle/Resources/public/js/jquery-1.11.3.min.js'
'#CoreBundle/Resources/public/js/bootstrap.min.js'
'#CoreBundle/Resources/public/js/fine-uploader.min.js'
'#CoreBundle/Resources/public/js/jquery-ui.min.js'
'#CoreBundle/Resources/public/js/datatables.min.js'
'#CoreBundle/Resources/public/js/Buttons-1.1.0/js/dataTables.buttons.min.js'
'#CoreBundle/Resources/public/js/Buttons-1.1.0/js/buttons.html5.js'
'#CoreBundle/Resources/public/js/Buttons-1.1.0/js/buttons.bootstrap.min.js'
'#CoreBundle/Resources/public/js/JSZip-2.5.0/jszip.min.js'
'#CoreBundle/Resources/public/js/RowReorder-1.1.0/js/dataTables.rowReorder.min.js'
%}
<script src="{{ asset(asset_url) }}" type="text/javascript"></script>
{% endjavascripts %}
{% endblock %}
{% block readyjs -%}
{{ tinymce_init() }}
<script type="text/javascript" >
function post_order ( ord, url)
{
$.ajax({
method: "POST",
url: url,
data: { elem: ord }
})
.done(function( msg ) {
// alert( msg );
});
}
$(document).ready(function () {
var optionsDatatables = {
dom: 'Bfrtip',
buttons: [
'copyHtml5', 'excelHtml5', 'csvHtml5'
]
}
if($('#dattab').hasClass('allow-order'))
{
//if we want more properties
// optionsDatatables.rowReorder = {
//selector: 'tr',
// update: true,
// dataSrc: '.ord-id'
// }
optionsDatatables.rowReorder = true;
}
var table = $('#dattab').DataTable(optionsDatatables);
var order;
if($('#dattab').hasClass('allow-order')) {
$('#dattab').on('draw.dt', function () {
var rows = table.rows().data();
var ord = new Array();
for (var i = 0, ien = rows.length; i < ien; i++) {
ord[i] = rows[i].DT_RowId;
}
order = ord;
$('#save_sort').fadeIn();
});
}
$('#save_sort').click(function(){
console.log(order);
post_order(order,$('#dattab').data('url'));
$(this).fadeOut();
});
});
</script>
{% endblock %}
</body>
</html>
The index which extends the base
{% extends "CoreBundle::admin_inner.html.twig" %}
{% block body -%}
<div class="container">
<div class="row">
<div class="col-xs-12">
{#{{ app.request.locale }}#}
<h1>Object list</h1>
{% for locale in ['en', 'bg'] %}
<li>
<a href="{{ path(app.request.get('_route'), app.request.get('_route_params')| merge({'_locale' : locale})) }}">
{{ locale }}
</a>
</li>
{% endfor %}
{{ app.session.get('_locale') }}{#
{{ app.request.locale }}#}
<div class="table-responsive">
<table class="table table-hover table-bordered" id="dattab">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Description</th>
<th>Mode</th>
<th>Lat</th>
<th>Longt</th>
<th>Address</th>
<th>Created</th>
<th>Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entity.translate(app.session.get('_locale')).title }} </td>
<td>{{ entity.translate(app.session.get('_locale')).description }} </td>
<td>{{ entity.mode }}</td>
<td>{{ entity.lat }}</td>
<td>{{ entity.longt }}</td>
<td>{{ entity.translate(app.session.get('_locale')).address }}</td>
<td>{% if entity.created %}{{ entity.created|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>{% if entity.updated %}{{ entity.updated|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>
<a href="{{ path('object_edit', { 'id': entity.id }) }}"
class="btn btn-primary"> <span class="glyphicon glyphicon-edit"
aria-hidden="true"></span> Edit</a>
<a href="{{ path('admin_floor', { 'id': entity.id }) }}"
class="btn btn-info"> <span class="glyphicon glyphicon-edit"
aria-hidden="true"></span> Floors</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<ul>
<li>
<a href="{{ path('object_new') }}">
Create a new entry
</a>
</li>
</ul>
</div>
</div>
</div>
{% endblock %}
And the inner with the menu:
{% extends "CoreBundle::admin_base.html.twig" %}
{% block menu %}
{{ include('CoreBundle::menu.html.twig') }}
{% endblock %}
I would first check whether all your frontend resources are loading correctly (scripts, images, css).
This can considerably slow down you app.
You can check it in firebug or developer console.
Related
I'm creating an app and I want to enable users to change their data and password. I've created an email changing form and it works, but I've got a problem with password.
I've got a page localhost:8000/user/{id} and here the buttons: edit email and edit password. Edit email is working and when I click on editing password - I got a blank page on localhost:8000/user/{id}/change_password
(enter image description here enter image description here). Th PassType doesn't show there.
There are no syntax error on localhost:8000/user/{id} and localhost:8000/user/{id}/change_password.
I've added a function edit_pass to UserController, crated PassType (where is the form to change password) and make a template edit_password.html.twig.
I don't know where is the problem. I did the same thing as with other Forms which work. I've tried to clear the edit_password template (I've just left the base_html there and put some text) cause I've thought there is a problem in it, but it was still a blank page on localhost:8000/user/{id}/change_password.
PassType:
<?php
/*
* Password type.
*/
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Class PassType.
*/
class PassType extends AbstractType
{
/**
* Builds the form.
*
* This method is called for each type in the hierarchy starting from the
* top most type. Type extensions can further modify the form.
*
* #see FormTypeExtensionInterface::buildForm()
*
* #param FormBuilderInterface $builder The form builder
* #param array $options The options
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(
'password',
RepeatedType::class,
[
'type' => PassType::class,
'required' => true,
'attr' => ['max_length' => 40],
'first_options' => ['label' => 'label.password'],
'second_options' => ['label' => 'label.repeat_password'],
]
);
}
/**
* Configures the options for this type.
*
* #param OptionsResolver $resolver The resolver for the options
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(['data_class' => User::class]);
}
/**
* Returns the prefix of the template block name for this type.
*
* The block prefix defaults to the underscored short class name with
* the "Type" suffix removed (e.g. "UserProfileType" => "user_profile").
*
* #return string The prefix of the template block name
*/
public function getBlockPrefix(): string
{
return 'user';
}
}
edit_password.html.twig
{% extends 'base.html.twig' %}
{% block title %}
{{ 'title_password_edit'|trans({'%id%': user.id|default('')}) }}
{% endblock %}
{% block body %}
<h1 class="display-4 d-flex justify-content-center">{{ 'title_password_edit'|trans({'%id%': user.id|default('')}) }}</h1>
{{ form_start(form, { method: 'PUT', action: url('password_edit', {id: user.id}) }) }}
{{ form_widget(form) }}
<div class="form-group row float-sm-right">
<input type="submit" value="{{ 'action_save'|trans }}" class="btn btn-primary" />
</div>
<div class="form-group row float-sm-left">
<a href="{{ url('user_index') }}" class="btn btn-link">
{{ 'action_back_to_list'|trans }}
</a>
</div>
{{ form_end(form) }}
{% endblock %}
and part of UserController whith edit_pass function
/**
* Edit Password.
*
* #param \Symfony\Component\HttpFoundation\Request $request HTTP request
* #param \App\Entity\User $user User entity
* #param \App\Repository\UserRepository $repository User repository
*
* #return \Symfony\Component\HttpFoundation\Response HTTP response
*
* #throws \Doctrine\ORM\ORMException
* #throws \Doctrine\ORM\OptimisticLockException
*
* #Route(
* "/{id}/change_password",
* methods={"GET", "PUT"},
* requirements={"id": "[1-9]\d*"},
* name="password_edit",
* )
*/
public function edit_pass(Request $request, User $user, UserPasswordEncoderInterface $passwordEncoder, UserRepository $repository): Response
{
$form = $this->createForm(PassType::class, $user, ['method' => 'PUT']);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setPassword(
$passwordEncoder->encodePassword(
$user,
$form->get('password')->getData()
)
);
$repository->save($user);
$this->addFlash('success', 'message.updated_successfully');
return $this->redirectToRoute('user_show', array('id' => $this->getUser()->getId()));
}
return $this->render(
'user/edit_password.html.twig',
[
'form' => $form->createView(),
'user' => $user,
]
);
}
I'm also adding the user/show.html.twig
{% extends 'base.html.twig' %}
{% block title %}
{{ 'label_detail_users'|trans({'%id%': user.id|default('')}) }}
{% endblock %}
{% block body %}
<h1 class="display-4 d-flex justify-content-center">{{ 'label_detail_users'|trans({'%id%': user.id|default('')}) }}</h1>
{% if users is defined and users|length %}
<table class="table table-striped">
<thead>
<tr>
<th>{{ 'label_user_id'|trans }}</th>
<th>{{ 'label_email'|trans }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ users.id }}</td>
<td>{{ users.email }}</td>
</tr>
</tbody>
</table>
<p>
<a class="btn btn-info" href="{{ url('user_edit', {id: users.id}) }}" title="{{ 'edit_email'|trans }}">
{{ 'edit_email'|trans }}
</a>
</p>
<p>
<a class="btn btn-info" href="{{ url('password_edit', {id: users.id}) }}" title="{{ 'edit_password'|trans }}">
{{ 'edit_password'|trans }}
</a>
</p>
<p>
<a class="btn btn-info" href="{{ url('user_index') }}" title="{{ 'action_back_to_list'|trans }}">
{{ 'action_back_to_list'|trans }}
</a>
</p>
{% else %}
<p>
{{ 'message_item_not_found'|trans }}
</p>
{% endif %}
{% endblock %}
You produced an endless loop - its PasswordType in your RepeatedType. PassType is the name of your whole Form - you see the problem?
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(
'password',
RepeatedType::class,
[
'type' => PasswordType::class,
'required' => true,
'attr' => ['max_length' => 40],
'first_options' => ['label' => 'label.password'],
'second_options' => ['label' => 'label.repeat_password'],
]
);
}
And may I ask why you limit the length of a password?
I am trying to build a list filter in Symfony. I'm still new to PHP, MySQL, and twig. The official documentation doesn't help a lot. It is required that I have a page with a list of all classes and next to that a search bar where the user inputs the class they want and it will show on the page without the others. I'll post my code but I think it is missing a lot of code. I only need little help and maybe sources for documentation on how to do it the official documents aren't very clear for someone with zero experience.
My ClassesRepository.php
<?php
namespace App\Repository;
use App\Entity\Classes;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* #method Classes|null find($id, $lockMode = null, $lockVersion = null)
* #method Classes|null findOneBy(array $criteria, array $orderBy = null)
* #method Classes[] findAll()
* #method Classes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ClassesRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Classes::class);
}
public function findbyName()
{
return $this->createQueryBuilder('c')
->getQuery()->getResult();
}
public function getSearchClasses($class){
$qb = $this->createQueryBuilder('c')
->where('c.Title LIKE :Title')
->setParameter('Title', '%' . $class->getTitle() . '%')
->orderBy('c.Title', 'DESC')
->getQuery();
}
}
classesController:
<?php
namespace App\Controller;
use App\Entity\Classes;
use App\Entity\Students;
use App\Entity\Courses;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class ClassesController extends AbstractController
{
/**
* #Route("custom/classes", name="classes_list")
*/
public function index()
{
$classes = $this->getDoctrine()->getRepository(classes::class)->findAll();
return $this->render('classes/index.html.twig', [
'classes' => $classes
]);
}
/**
* #Route("/classes/new", name="new_class")
* #Method({"GET","POST"})
*/
public function new(Request $request)
{
$class = new Classes();
$form = $this->createFormBuilder($class)
->add('Title', TextType::class, array('attr' =>
array('class' => 'form-control')))
->add('save', SubmitType::class,array('label' => 'Create',
'attr' => array('class' => 'btn btn-primary mt-3')))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$class = $form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($class);
$entityManager->flush();
return $this->redirectToRoute('classes_list');
}
return $this->render('classes/new.html.twig', array(
'form' => $form->createView()
));
}
/**
* #Route("/classes/edit/{id}", name="edit_class")
* #Method({"GET","POST"})
*/
public function edit(Request $request, $id)
{
$class = new Classes();
$class = $this->getDoctrine()->getRepository(classes::class)->find($id);
$form = $this->createFormBuilder($class)
->add('Title', TextType::class, array('attr' =>
array('class' => 'form-control')))
->add('save', SubmitType::class,array('label' => 'Create',
'attr' => array('class' => 'btn btn-primary mt-3')))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->flush();
return $this->redirectToRoute('classes_list');
}
return $this->render('classes/edit.html.twig', array(
'form' => $form->createView()
));
}
/**
* #Route("/classes/delete/{id}")
* #Method({"DELETE"})
*/
public function delete(Request $request, $id){
$class = $this->getDoctrine()->getRepository(Classes::class)->find($id);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($class);
$entityManager->flush();
$response = new Response();
$response->send();
}
/**
* #Route("/classes/{id}", name="classes_show")
* #Method({"GET"})
*/
public function show($id){
$_class = $this->getDoctrine()->getRepository(Classes::class)->find($id);
return $this->render('classes/show.html.twig', array('classes' => $_class));
}
// /**
// * #Route("custom/classes/save")
// */
// public function save() {
// $entityManager = $this->getDoctrine()->getManager();
// $classes = new Classes();
// $classes->setTitle('Grade 2');
// $entityManager->persist($classes);
// $entityManager->flush();
// return new Response('Saved an classes with the id of '.$classes->getId());
// }
}
Index.html.twig is Location where I will need to locate the list filter
{% extends 'base.html.twig' %}
{% block title %}Classes{% endblock %}
{% block body %}
<br>
<h1>Classes:</h1>
Create
<br>
{% if classes %}
<div class="alignleft">
<table id="classes" class="table table-striped" style="width:70%">
<thead>
<tr>
<th>Class</th>
<th>Details </th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for classes in classes %}
<tr>
<td> {{ classes.title }}</td>
<td>
Show Class Details
</td>
<td>
Edit
</td>
<td>
X
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
<form method="GET" action="search" style = "position:absolute; left:1100px; top:150px; height:100px; width:100px">
<input type="text" name="q" placeholder="Search Query...">
<select name="column" style = "position:absolute; left:40px; top:30px; width:100px ">
<option value="classes.Title" >Class</option>
</select>
<input type="submit" class="btn btn-warning" value="Find" style = "position:absolute; left:40px; top:56px; width:100px ">
</form>
</div>
{% else %}
<p>No Classes Available</p>
{% endif %}
{% endblock %}
{% block javascripts %}
<script src="/js/classmain.js"></script>
{% endblock %}
I don't understand the behavior you expect from the filter but I hope it will help you..
In your ClassesRepository.php
// if has not $classTitle and $query it will find all
public function getSearchClasses($classTitle = null , $query=null){
$qb = $this->createQueryBuilder('c')
->orderBy('c.Title', 'DESC');
if($classTitle && $classTitle !== '') {
$qb->andWhere('c.Title LIKE :classTitle')
->setParameter('classTitle', '%' . classTitle . '%');
}
if($query && $query !== '') {
// doSomethings with query input
}
return $qb->getQuery()->getResult();
}
In your classesController:
/**
* #Route("custom/classes", name="classes_list")
*/
public function index(Request $request)
{
$classTitle = $request->query->get('classTitle',null);
$query = $request->query->get('query',null);
// if has not $classTitle and $query it will find all
$classes = $this->getDoctrine()->getRepository(classes::class)->getSearchClasses($classTitle,$query);
return $this->render('classes/index.html.twig', [
'classes' => $classes
]);
}
In your index.html.twig
// redirect to the same route that render this template ..
<form method="GET" action="{{ path('classes_list') }}">
<input type="text" name="query" placeholder="Search Query...">
<select name="classTitle">
{% for class in classes%}
<option value="{{class.title}" >{{class.title}}</option>
{% endfor %}
</select>
<input type="submit" class="btn btn-warning" value="Find">
</form>
I have a strange probleme with some rows of my form. I can't add a new lines in my collectionType dates and my collectionType userIduser.
dates is a collectiontype of InterventionHasDate
userIduser is a collection type of Entity : user
When I add new rows with jquery, they are printed in HTML but when I post nothing is saved.
I tried to dump the values of my form but it's like there is no new values in the form.
When I put manualy new dates in the database they are printed and I can modify or delete them in my page.
My form :
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('idtypeinter',EntityType::class, [
// looks for choices from this entity
'class' => 'ssiplanificationBundle:Typeintervention',
'label'=> 'Type de rendez-vous :',
'choice_label' => 'nomtyperdv',
])
->add('Valider',SubmitType::class,['label'=>'Valider'])
->add('site',EntityType::class, [
'class' => 'ssiplanificationBundle:Site',
'choice_label' => 'nomSite',
'label'=>'Site : ',
'placeholder'=> 'Selectionnez votre site',
'required'=>false,
'mapped'=>false,
])->add('batiment',EntityType::class, [
'class' => 'ssiplanificationBundle:Batiment',
'choice_label' => 'nomBatiment',
'label'=>'Batiment : ',
'required'=>false,
'mapped'=>false,
'placeholder' => 'Veuillez choisir un batiment',
])->add('contactCorrespondant',EntityType::class, [
'class' => 'ssiplanificationBundle:Contact',
'choice_label' => 'nomContact',
'label'=>'Contact à rencontrer sur site : ',
'required'=>false,
]);
$builder->add('installationIdinstallation',EntityType::class, [
'class' => 'ssiplanificationBundle:Installation',
'label'=> 'Installations :',
'multiple' => true,
'expanded' => true,
'required'=> false,
])->add('visiteIdvisite',EntityType::class, [
'class' => 'ssiplanificationBundle:Visite',
'label'=> ' Visites :',
'multiple' => true,
'expanded' => true,
'required'=> false,
])->add('AfficherplusInstallations',SubmitType::class,['label'=>'Afficher Plus'])
->add('AfficherplusVisites',SubmitType::class,['label'=>'Afficher Plus'])
->add('Validersite',SubmitType::class,['label'=>'Valider'])
->add('Validerbatiment',SubmitType::class,['label'=>'Valider'])
->add('numerointervention', TextType::Class,array('label'=> "Numéro d'intervention : ",'required'=>false))
->add('contactConfirmation',EntityType::class, [
'class' => 'ssiplanificationBundle:Contact',
'choice_label' => 'nomContact',
'label'=>'Contact de confirmation par mail : ',
'required'=>false,
])
->add('contactRdv',EntityType::class, [
'class' => 'ssiplanificationBundle:Contact',
'choice_label' => 'nomContact',
'label'=>'Contact pour prise de rendez-vous téléphonique : ',
'required'=>false,
])
->add('iduser',EntityType::class, [
'class' => 'ssiplanificationBundle:User',
'query_builder' => function (UserRepository $er) {
return $er->createQueryBuilder('u')
->where('u.estTechnicien = :fonction')
->setParameter('fonction', 'Oui');
},
'choice_label' => 'username',
'label'=>'Technicien : ',
])
->add('userIduser',CollectionType::class,[
'entry_type' => EntityType::class,
'entry_options' => [
'class' => 'ssiplanificationBundle:User',
'choice_label' => 'username',
'label'=> false,
'query_builder' => function (UserRepository $er) {
return $er->createQueryBuilder('u')
->where('u.estTechnicien = :fonction')
->setParameter('fonction', 'Oui');
},
],
'label'=>'Techniciens complémentaires :',
'allow_add' => true,
'allow_delete' => true,
])
->add('dates',CollectionType::class,[
// looks for choices from this entity
'entry_type' => InterventionHasDateType::class,
'allow_add' => true,
'allow_delete' => true,
'label'=>"Jours(s) d'intervention :",
])
->add('nomstatut',EntityType::class, [
// looks for choices from this entity
'class' => 'ssiplanificationBundle:Statut',
// uses the User.username property as the visible option string
'choice_label' => 'nomStatut',
'label'=>'Statut : ',
])
->add('commentaire',TextareaType::class,['label'=>'Commentaire :','required'=>false])
->add('Enregistrer',SubmitType::class,['label'=>'Enregistrer'])
;
$builder->get('site')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) {
$form=$event->getForm();
$this->addCorrespondantField($event->getForm()->getParent(),$event->getForm()->getData());
$this->addBatimentField($event->getForm()->getParent(),$event->getForm()->getData());
}
);
$builder->addEventListener(
FormEvents::POST_SET_DATA,
function (FormEvent $event) {
$data= $event->getData();
$installations= $data ->getInstallationIdinstallation();
$visites= $data ->getVisiteIdvisite();
if($data->getIdtypeinter()=="Vérification")
{
if(! $installations->isEmpty())
{
$batiment=$installations[0]->getZoneIdzone()[0]->getIdbatiment();
}else{
$batiment=NULL;
}
}else{
if(! $visites->isEmpty())
{
$batiment=$visites[0]->getInstallationIdinstallation()->getZoneIdzone()[0]->getIdbatiment();
}else{
$batiment=NULL;
}
}
if($batiment != NULL){
$site=$batiment->getIdsite();
}else{
$batiment=NULL;
$site=NULL;
}
if($site !=NULL){
$this->addCorrespondantField($event->getForm(),$site);
$this->addBatimentField($event->getForm(),$site);
$this->addInstallationField($event->getForm(),$batiment);
$event->getForm()->get('site')->setData($site);
$event->getForm()->get('batiment')->setData($batiment);
$event->getForm()->get('installationIdinstallation')->setData($installations);
$event->getForm()->get('visiteIdvisite')->setData($visites);
$event->getForm()->get('contactCorrespondant')->setData($data ->getContactCorrespondant() );
}else{
$this->addCorrespondantField($event->getForm(),$site);
$this->addBatimentField($event->getForm(),$site);
$this->addInstallationField($event->getForm(),$batiment);
}
}
);
}
My form for date :
class InterventionHasDateType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('dateintervention',DateType::class,array(
'widget' => 'single_text',
'label'=> 'Le'
)
)
->add('heuredebut',TimeType::class,array('widget' => 'single_text',
'attr'=> ['step'=> '900' ] ,
'label'=> 'De'))
->add('heurefin',TimeType::class,array('widget' => 'single_text',
'attr'=> ['step'=> '900' ] ,
'label'=> 'A'))
;
}
My controller:
public function PlanificationInterventionModifyAction(Intervention $intervention=NULL, Request $request)
{
if($intervention==NULL){
$intervention=new Intervention();
}
$originalDates =array();
// Create an ArrayCollection of the current Date objects in the database
foreach ($intervention->getDates() as $inter) {
$originalDates[]=$inter;
}
$originalTech= array();
// Create an ArrayCollection of the current Date objects in the database
foreach ($intervention->getUserIdUser() as $tech) {
$originalTech[]=$tech;
}
$originalVisite= array();
// Create an ArrayCollection of the current Date objects in the database
foreach ($intervention->getVisiteIdvisite() as $visite) {
$originalVisite[]=$visite;
}
$form = $this->createForm(InterventionType::class, $intervention);
$form->handleRequest($request);
if ($form->get('Enregistrer')->isClicked() and $form->isValid()) {
$em = $this->getDoctrine()->getManager();
foreach ($originalVisite as $visite) {
if (false === $form->get("visiteIdvisite")->getData()->contains($visite)) {
// if you wanted to delete the Tag entirely, you can also do that
$visite->removeInterventionIdintervention($intervention);
$em->persist($visite);
}
}
foreach ($form->get("visiteIdvisite")->getData() as $visite) {
if (!in_array($visite,$originalVisite)) {
$visite->addInterventionIdintervention($intervention);
$em->persist($visite);
}
}
foreach ($originalTech as $tech) {
if (false === $form->get("userIduser")->getData()->contains($tech)) {
// if you wanted to delete the Tag entirely, you can also do that
$tech->removeInterventionIdintervention($intervention);
$em->persist($tech);
}
}
foreach ($form->get("userIduser")->getData() as $tech) {
if (!in_array($tech,$originalTech)) {
$tech->addInterventionIdintervention($intervention);
$em->persist($tech);
}
}
dump($form->get("dates"));
dump($form->get("dates")->getData());
foreach ($originalDates as $date) {
if (false === $form->get("dates")->getData()->contains($date)) {
// if you wanted to delete the Tag entirely, you can also do that
$em->remove($date);
}
}
foreach ($form->get("dates")->getData() as $date) {
if (!in_array($date,$originalDates)) {
$date->setInterventionIdintervention($intervention);
$em->persist($date);
}
}
$em->persist($intervention);
$em->flush();
$request->getSession()->getFlashBag()->add('notice', 'Enregistrement effectué.');
//return $this->redirectToRoute('ssiplanification_planification_homepage');
}
return $this->render('planification/InterventionNew.html.twig', array(
'form' => $form->createView()));
}
The entity InterventionHasDate:
/**
* InterventionHasDate
*
* #ORM\Table(name="intervention_has_date", indexes={#ORM\Index(name="intervention_idIntervention", columns={"intervention_idIntervention"})},
* uniqueConstraints={
* #ORM\UniqueConstraint(
* columns={"dateintervention", "HeureDebut","HeureFin","intervention_idIntervention"}
* )
* })
* #ORM\Entity(repositoryClass="ssi\planificationBundle\Repository\InterventionHasDateRepository")
*/
class InterventionHasDate
{
/**
*#Assert\Date
* #var string A "Y-m-d" formatted value
*#ORM\Id
* #ORM\Column(name="dateIntervention", type="string", nullable=false, options={"default"="0000-00-00"})
*
*/
private $dateintervention = '0000-00-00';
/**
* #var \Intervention
*#ORM\Id
* #ORM\ManyToOne(targetEntity="Intervention", inversedBy="dates")
*
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="intervention_idIntervention", referencedColumnName="idIntervention")
* })
*/
private $interventionIdintervention;
/**
* #var \Time
*
* #ORM\Column(name="HeureDebut", type="time", nullable=false)
*/
private $heuredebut;
/**
* #var \Time
*
* #ORM\Column(name="HeureFin", type="time", nullable=false)
*/
private $heurefin;
/**
* #return \DateTime
*/
public function getDateintervention()
{
return \DateTime::createFromFormat('Y-m-d|', $this->dateintervention);
}
public function getHeuredebut(): ?\DateTimeInterface
{
return $this->heuredebut;
}
public function setHeuredebut(\DateTimeInterface $heuredebut): self
{
$this->heuredebut = $heuredebut;
return $this;
}
public function getHeurefin(): ?\DateTimeInterface
{
return $this->heurefin;
}
public function setHeurefin(\DateTimeInterface $heurefin): self
{
$this->heurefin = $heurefin;
return $this;
}
public function getInterventionIdintervention(): ?Intervention
{
return $this->interventionIdintervention;
}
public function setInterventionIdintervention(?Intervention $interventionIdintervention): self
{
$this->interventionIdintervention = $interventionIdintervention;
return $this;
}
/**
* Set dateintervention.
*
* #param \DateTime $dateintervention
*
* #return InterventionHasDate
*/
public function setDateintervention($dateintervention)
{
$this->dateintervention = $dateintervention->format('Y-m-d');
return $this;
}
}
The entity intervention :
/**
* Intervention
*
* #ORM\Table(name="intervention", uniqueConstraints={#ORM\UniqueConstraint(name="idIntervention", columns={"idIntervention"})}, indexes={#ORM\Index(name="contact_rdv_2", columns={"contact_rdv"}), #ORM\Index(name="contact_confirmation", columns={"contact_confirmation"}), #ORM\Index(name="idUser", columns={"idUser"}), #ORM\Index(name="contact_correspondant", columns={"contact_correspondant"}), #ORM\Index(name="nomStatut", columns={"nomStatut"})})
* #ORM\Entity(repositoryClass="ssi\planificationBundle\Repository\InterventionRepository")
*/
class Intervention
{
/**
* #var int
*
* #ORM\Column(name="idIntervention", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idintervention;
.....
/**
* #var \Doctrine\Common\Collections\Collection
*#ORM\OneToMany(targetEntity="InterventionHasDate", mappedBy="interventionIdintervention")
*/
private $dates;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="User", inversedBy="interventionIdintervention")
* #ORM\JoinTable(name="intervention_has_user",
* joinColumns={
* #ORM\JoinColumn(name="intervention_idIntervention", referencedColumnName="idIntervention")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="user_idUser", referencedColumnName="idUser")
* }
* )
*/
private $userIduser;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="Visite", mappedBy="interventionIdintervention")
*/
private $visiteIdvisite;
/**
* #return Collection|InterventionHasDate[]
*/
public function getDates(): Collection
{
return $this->dates;
}
public function addDates(InterventionHasDate $dates): self
{
if (!$this->dates->contains($dates)) {
$this->dates[] = $dates;
$dates->addDates($this);
}
return $this;
}
public function removeDates(InterventionHasDate $dates): self
{
if ($this->dates->contains($dates)) {
$this->dates->removeElement($dates);
$dates->removeDates($this);
}
return $this;
}
/**
* #return Collection|User[]
*/
public function getUserIduser(): Collection
{
return $this->userIduser;
}
public function addUserIduser(User $userIduser): self
{
if (!$this->userIduser->contains($userIduser)) {
$this->userIduser[] = $userIduser;
$userIduser->addInterventionIdintervention($this);
}
return $this;
}
public function removeUserIduser(User $userIduser): self
{
if ($this->userIduser->contains($userIduser)) {
$this->userIduser->removeElement($userIduser);
$userIduser->removeInterventionIdintervention($this);
}
return $this;
}
public function __construct()
{
$this->installationIdinstallation = new \Doctrine\Common\Collections\ArrayCollection();
$this->userIduser = new \Doctrine\Common\Collections\ArrayCollection();
$this->visiteIdvisite = new \Doctrine\Common\Collections\ArrayCollection();
$this->dates=new \Doctrine\Common\Collections\ArrayCollection();
}
My html/twig :
{% extends 'planification/base.html.twig' %}
{% block title %}
Home
{% endblock %}
{% block body %}
<div id="corps">
<h1>Intervention</h1>
<h3>{{ form_start(form)}}</h3>
{{ form_errors(form)}}
<div class="block-position">
{{ form_errors(form.idtypeinter) }}
<h3>{{ form_label(form.idtypeinter)}}{{ form_widget(form.idtypeinter)}}{{ form_widget(form.Valider) }}</h3>
</div>
{% if form.idtypeinter.vars.value == "Dépannage"
or form.idtypeinter.vars.value == "Mise en service"
or form.idtypeinter.vars.value == "Travaux"
or form.idtypeinter.vars.value == "Vérification" %}
<div class="block-position">
{{ form_errors(form.site) }}
<h3>{{ form_label(form.site) }}{{ form_widget(form.site) }}{{ form_widget(form.Validersite) }}</h3>
{{ form_errors(form.batiment) }}
<h3>{{ form_label(form.batiment) }}{{ form_widget(form.batiment) }}{{ form_widget(form.Validerbatiment) }}</h3>
{% if form.idtypeinter.vars.value != "Vérification" %}
<h3>{{ form_errors(form.installationIdinstallation) }}{{ form_label(form.installationIdinstallation) }}</h3>
{% if form.batiment.vars.value != NULL %}
{% for installation in form.installationIdinstallation %}
<h4>{{ form_widget(installation) }}{{ form_label(installation) }}</h4>
{% endfor %}
<h3>{{ form_row(form.AfficherplusInstallations) }}</h3>
{% endif %}
{% else %}
<h3>{{ form_errors(form.visiteIdvisite) }}{{ form_label(form.visiteIdvisite) }}</h3>
{% if form.batiment.vars.value != NULL %}
{% for visite in form.visiteIdvisite %}
<h4>{{ form_widget(visite) }}{{ form_label(visite) }}</h4>
{% endfor %}
<h3>{{ form_row(form.AfficherplusVisites) }}</h3>
{% endif %}
{% endif %}
</div>
<div class="block-position">
{{ form_errors(form.numerointervention) }}
<h3>{{ form_row(form.numerointervention) }}</h3>
{{ form_errors(form.contactCorrespondant) }}
<h3>{{ form_row(form.contactCorrespondant) }}</h3>
{{ form_errors(form.contactRdv) }}
<h3>{{ form_row(form.contactRdv) }}</h3>
{{ form_errors(form.contactConfirmation) }}
<h3>{{ form_row(form.contactConfirmation) }}</h3>
</div>
{% endif %}
<div class="block-position">
{{ form_errors(form.dates) }}
<h3>{{ form_label(form.dates) }}
<ul id="dates-fields-list"
data-prototype="{{form_widget(form.dates.vars.prototype) |e('html_attr')}}"
data-widget-tags="{{ '<li></li>'|e }}"
data-widget-counter="{{ form.dates|length }}">
{% for datesField in form.dates %}
<li id="{{ "list_" ~ datesField.vars.id }}">
{{ form_widget(datesField.dateintervention)}}
{% if form.idtypeinter.vars.value != "Astreinte" %}
{{form_widget(datesField.heuredebut ) }}
{{form_widget(datesField.heurefin )}}
{% endif %}
<button type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_" ~ datesField.vars.id }})">Retirer</button>
</li>
{% endfor %}
</ul><button type="button" class="add-another-collection-widget" data-list-selector="#dates-fields-list">Ajouter</button></h3>
</div>
<div class="block-position">
{{ form_errors(form.iduser) }}
<h3>{{ form_row(form.iduser) }}</h3>
{{ form_errors(form.commentaire) }}
<h3>{{ form_row(form.commentaire) }}</h3>
{{ form_errors(form.nomstatut) }}
<h3>{{ form_row(form.nomstatut) }}</h3>
</div>
<div class="block-position">
{{ form_errors(form.userIduser) }}
<h3>{{ form_label(form.userIduser) }}
<ul id="technicien-fields-list" data-prototype="{{ form_widget(form.userIduser.vars.prototype)|e('html_attr') }}"
data-widget-tags="{{ '<li></li>'|e }}"
data-widget-counter="{{ form.userIduser|length }}">
{% for technicienField in form.userIduser %}
<li id="{{ "list_" ~ technicienField.vars.id }}">
{{ form_errors(technicienField) }}
{{ form_widget(technicienField) }} <button type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_" ~ technicienField.vars.id }})">Retirer</button>
</li>
{% endfor %}
</ul> <button type="button" class="add-another-collection-widget" data-list-selector="#technicien-fields-list">Ajouter</button>
</h3>
<button type="submit">Essayer</button>
</div>
<h3>{{ form_row(form.Enregistrer) }}</h3>
{{ form_row(form._token) }}
{{ form_end(form, {'render_rest': false})}}
</div>
{% endblock %}
The script :
jQuery(document).ready(function () {
jQuery('.add-another-collection-widget').click(function (e) {
var list = jQuery(jQuery(this).attr('data-list-selector'));
// Try to find the counter of the list or use the length of the list
var counter = list.data('widget-counter') || list.children().length;
// grab the prototype template
var newWidget = list.attr('data-prototype');
// replace the "__name__" used in the id and name of the prototype
// with a number that's unique to your emails
// end name attribute looks like name="contact[emails][2]"
newWidget = newWidget.replace(/__name__/g, counter);
// Increase the counter
counter++;
// And store it, the length cannot be used if deleting widgets is allowed
list.data('widget-counter', counter);
// create a new list element and add it to the list
var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
addTagFormDeleteLink(newElem);
newElem.appendTo(list);
});
function addTagFormDeleteLink($tagFormLi) {
var $removeFormButton = $(' <button type="button"> Retirer</button>');
$tagFormLi.append($removeFormButton);
$removeFormButton.on('click', function(e) {
// remove the li for the contact form
$tagFormLi.remove();
});
}
});
function deleteLink(id){
id.remove();
}
The script is working for the other pages of my site.
I am in trouble since some days already... If someone can help me I will be very gratefull.
UPDATE
After sometimes I manage to understand that my script broke my collection.
The only solution I found is to stop using it and add row manually.
The new code:
<h3>{{ form_label(form.dates) }}
<ul>
{% for datesField in form.dates %}
<li id="{{ "list_" ~ datesField.vars.id }}">
{{ form_widget(datesField.dateintervention)}}
{% if form.idtypeinter.vars.value != "Astreinte" %}
{{form_widget(datesField.heuredebut ) }}
{{form_widget(datesField.heurefin )}}
{% endif %}
<button type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_" ~ datesField.vars.id }})">Retirer</button>
</li>
{% endfor %}
{% if form.Ajouterdate.vars.clicked ==1 %}
{% set number = form.dates|length %}
<li id="{{ "list_ssi_planificationbundle_intervention_dates_" ~ number }}">
<input type="date" id="ssi_planificationbundle_intervention_dates_{{number}}_dateintervention" name="ssi_planificationbundle_intervention[dates][{{number}}][dateintervention]" required="required" >
<input type="time" id="ssi_planificationbundle_intervention_dates_{{number}}_heuredebut" name="ssi_planificationbundle_intervention[dates][{{number}}][heuredebut]" required="required" step="900">
<input type="time" id="ssi_planificationbundle_intervention_dates_{{number}}_heurefin" name="ssi_planificationbundle_intervention[dates][{{number}}][heurefin]" required="required" step="900">
<button type="button" class="remove-another-collection-widget" onclick="deleteLink( {{ "list_ssi_planificationbundle_intervention_dates_" ~ number }})">Retirer</button>
</li>
{% endif %}
</ul>{{form_row(form.Ajouterdate)}}
</h3>
</div>
It works but it's not the best solution. Did someone have a better idea?
Privet all!
I'm new to Symfony 4 and generally to PHP and OOP in general. I was helped to make the form using FormCollection the code looks so
AbilityContoller.php
/**
* #Route("/edit", name="ability_edit_all")
*/
public function edit(Request $request)
{
$abilitys = $this->getDoctrine()->getRepository(Ability::class)->findAll();
$form = $this->createForm(AbilityArrayType::class, ['abilitys' => $abilitys]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
foreach ($form->getData()['abilitys'] as $ability){
$this->getDoctrine()->getManager()->persist($ability);
}
$this->getDoctrine()->getManager()->flush();
$this->addFlash('notice', 'Your changes were saved!');
return $this->redirectToRoute('ability_edit_all');
}
return $this->render('ability/edit.all.html.twig', [
'form' => $form->createView()
]);
}
and screenshot
you see that my record with the form has both tags with a choiceType and a simple input
And I also figured out myself with knp_paginator, because if I output more than 15 records with FormCollection, I get an error about the lack of memory in php. I made a static table where I output all my records, sorting and filtering works, pagination is broken as it should.
here is the code
ServiceFile.php
class AbilityService{
protected $em;
protected $container;
public function __construct(EntityManagerInterface $entityManager, ContainerInterface $container)
{
$this->em = $entityManager;
$this->container = $container;
}
public function ReturnData($request){
$em = $this->em;
$container = $this->container;
$query = $em->createQuery(
'
SELECT
t.idItem,
t.code,
t.reloadTime,
t.durationTime,
t.idAbilityType
FROM
App\Entity\Ability t
'
);
dump($query);
//$result = $query->execute();
$pagenator = $container->get('knp_paginator');
$results = $pagenator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 10)
);
return ($results);
}
}
and controller
use App\Service\ServiceFile;
/**
* #Route("/test-edit", name="ability_test_edit_all")
*/
public function edit_test(AbilityService $query, Request $request)
{
$data = $query->ReturnData($request);
return $this->render('ability/edit.alltest.html.twig',[
'form' => $data,
]);
}
here screenshot
Work a perfect!!
I bet I can not figure out how to make the same result, but with FormCollection?
The second question, if it turns out to be pagination, will filtering and sorting work from knp_paginator?
ok,
ok, something happened and it's not right for mine, but Pagination and sorting + filtering work only on <input> tags, inside <select> <option selected> var </ select> nothing works, but the solution is working
controllerFile.php
/**
* #Route("/edit", name="ability_edit_all")
*/
public function edit(AbilityService $abilityService, Request $request)
{
$data = $abilityService->ReturnData($request);
$form = $this->createForm(AbilityArrayType::class, ['abilitys' => $data->getItems()]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
foreach ($form->getData()['abilitys'] as $properties){
dump($properties);
$ability = $this->getDoctrine()->getRepository(Ability::class)->find($properties['id']);
$ability->setIdItem($properties['idItem']);
$ability->setCode($properties['code']);
$ability->setReloadTime($properties['reloadTime']);
$ability->setDurationTime($properties['durationTime']);
$ability->setIdAbilityType($properties['idAbilityType']);
dump($ability);
$this->getDoctrine()->getManager()->persist($ability);
}
$this->getDoctrine()->getManager()->flush();
$this->addFlash('notice', 'Your changes were saved!');//проделать со всеми см edit.html.twig
return $this->redirectToRoute('ability_edit_all');
}
return $this->render('ability/edit.all.html.twig', [
'form' => $form->createView(),
'paginator' => $data
]);
}
twig tempalte
{% extends 'base.html.twig' %}
{% block title %}Ability edit all{% endblock %}
{% block body %}
<style>
label{display:none}
</style>
<h1>Ability edit all</h1>
<a class="btn-add mar-bot-top-20" href="{{ path('ability_new') }}"><i class="fas fa-plus"></i> Create new</a>
<div class="row">
<div class="col-4 text-center">
<div class="navigation">
{{ knp_pagination_render(paginator) }}
</div>
</div>
<div class="col-8 text-left">
<div class="filtration">
{{ knp_pagination_filter(paginator, {
't.idItem': 'IdItem',
't.code': 'Code',
't.reloadTime': 'ReloadTime',
't.durationTime': 'DurationTime',
't.idAbilityType': 'IdAbilityType',
}) }}
</div>
</div>
</div>
<table class="table">
<tr>
<th>{{ knp_pagination_sortable(paginator, 'idItem', 't.idItem') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'Code', 't.code') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'ReloadTime', 't.reloadTime') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'DurationTime', 't.durationTime') }}</th>
<th>{{ knp_pagination_sortable(paginator, 'idAbilityType', 't.idAbilityType') }}</th>
</tr>
{{ form_start(form) }}
{% for ability in form.abilitys %}
<tr>
<td>{{ form_row(ability.idItem) }}</td>
<td>{{ form_row(ability.code) }}</td>
<td>{{ form_row(ability.reloadTime) }}</td>
<td>{{ form_row(ability.durationTime) }}</td>
<td>{{ form_row(ability.idAbilityType) }}</td>
</tr>
{% else %}
<tr>
<td colspan="9">no records found</td>
</tr>
{% endfor %}
{{ form_end(form) }}
</table>
<div class="row">
<div class="col-4 text-center">
<div class="navigation">
{{ knp_pagination_render(paginator) }}
</div>
</div>
<div class="col-8 text-left">
<div class="filtration">
{{ knp_pagination_filter(paginator, {
't.idItem': 'IdItem',
't.code': 'Code',
't.reloadTime': 'ReloadTime',
't.durationTime': 'DurationTime',
't.idAbilityType': 'IdAbilityType',
}) }}
</div>
</div>
</div>
<a class="btn-add" href="{{ path('ability_new') }}"><i class="fas fa-plus"></i> Create new</a>
{% for message in app.flashes('notice') %}
<div class="flash-notice">
{{ message }}
</div>
{% endfor %}
{% endblock %}
and ServiceFile.php
<?php
namespace App\Service;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Ability;
class AbilityService{
protected $em;
protected $container;
public function __construct(EntityManagerInterface $entityManager, ContainerInterface $container)
{
$this->em = $entityManager;
$this->container = $container;
}
public function ReturnData($request){
$em = $this->em;
$container = $this->container;
$query = $em->createQuery(
'
SELECT
t.id,
t.idItem,
t.code,
t.reloadTime,
t.durationTime,
t.idAbilityType,
t.dateCreated,
t.author,
t.dateChange,
t.lastAuthor
FROM
App\Entity\Ability t
'
);
$pagenator = $container->get('knp_paginator');
$results = $pagenator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 6)
);
return ($results);
}
}
if anyone can tell how to implement sorting within <select> <option selected> var </ select>, you can use <th> {{knp_pagination_sortable (paginator, 'idItem', 't.idItem')}} </ th>
write please!
I've a problem with Symfony.
I've a VideoController that renders a twig page.
This twig page includes another twig page that has a rendercontroller. With this render controller, the route crash and it says that the "video" variable that I send with the first controller doesn't exists. What's wrong?
This is the code for VideoController:
public function getVideo(Request $request, $id) {
$entityManager = $this->getDoctrine()->getManager();
$video = $entityManager->getRepository('AppBundle:Video')->getVidById($id);
return $this->render('vids/videos.html.twig', ['video' => $video]); //Needs improvements
}
videos.html.twig:
{% block main %}
<center>
<video controls style="width:720px;height:360px;" poster="poster.png">
<source src="{{ video.link }}" type="video/mp4;" codecs="avc1.42E01E, mp4a.40.2" />
</video>
{{ include ("comments/comment.html.twig") }}
</center>
{% endblock %}
comment.html.twig:
{% block comment %}
<br><br>
<center>
{{ render(controller('AppBundle:Video:commentVideo')) }}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</center>
{% endblock %}
CommentController:
class CommentsController extends Controller
{
/*
* Check if session is valid. If so, user can comment. SECURITY SYSTEM NEEDS TO BE DEVELOPED!!!
* #Route("/", name="comment")
* #Method({"GET", "POST"})
*/
public function commentVideoAction(Request $request) {
$comment = new Comment();
$form = $this->createFormBuilder($comment)
->add('text', TextType::class)
->add('Invia Commento', SubmitType::class)
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$comment = $form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
return $this->render('vids/videos.html.twig');
}
return $this->render('vids/videos.html.twig', array(
'form' => $form->createView(),
));
}
}
In your render (commentVideoAction), you have the twig file "vids/videos.html.twig" and you don't pass the video variable. I think you use the bad template. (
I think there s a mistake in your VideoController.
Try with public function getVideoAction(Request $request, $id) instead of just getVideo
And your structure is bad, you have a loop in your controllers, try like this:
videos.html.twig:
{% block main %}
<center>
<video controls style="width:720px;height:360px;" poster="poster.png">
<source src="{{ video.link }}" type="video/mp4;" codecs="avc1.42E01E, mp4a.40.2" />
</video>
{{ render(controller('AppBundle:Video:commentVideo')) }}
</center>
{% endblock %}
comment.html.twig:
{% block comment %}
<br><br>
<center>
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</center>
{% endblock %}
CommentController:
class CommentsController extends Controller
{
/*
* Check if session is valid. If so, user can comment. SECURITY SYSTEM NEEDS TO BE DEVELOPED!!!
* #Route("/", name="comment")
* #Method({"GET", "POST"})
*/
public function commentVideoAction(Request $request) {
$comment = new Comment();
$form = $this->createFormBuilder($comment)
->add('text', TextType::class)
->add('Invia Commento', SubmitType::class)
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$comment = $form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
return $this->render('vids/videos.html.twig');
}
return $this->render('vids/comment.html.twig', array(
'form' => $form->createView(),
));
}
}