Laravel with TwigBridge method_field not working - php

I'm following the basic quickstart with laravel 5. I'm deviating only in that I'm using TwigBridge to allow me to use twig templates instead of blade. I'm getting in error when I tried to load my view.
Unknown "method_field" function in "/home/vagrant/laravel-test/resources/views/tasks.twig" at line 63.
method_field should be an available default helper function in laravel. I'm not really sure why twigbridge isn't finding it. Is there something I'm missing I need to make this function available to TwigBridge?
Edit
Here's my code:
{% if tasks|length > 0 %}
<div class="panel panel-default">
<div class="panel-heading">
Current Tasks
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<!-- Table Headings -->
<thead>
<th>Task</th>
<th> </th>
</thead>
<!-- Table Body -->
<tbody>
{% for task in tasks %}
<tr>
<!-- Task Name -->
<td class="table-text">
<div>{{ task.name }}</div>
</td>
<td>
<form action="{{ url('task/'~task.id) }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button>Delete Task</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
Edit 2
I partially figured it out. I had to add method_field to the config/twigbridge.php file in the functions array:
'functions' => [
'elixir',
'head',
'last',
'method_field',
].
This got it to run the function, however the output is converted to html entities because it actually renders the input tag text instead of the tag itself. So I need to figure out away to make it not escape the output.

The answer is that you have to add the function to the config/twigbridge.php with an is_safe option. That can be done this way:
in /app/config/twigbridge.php
'functions' => [
// Other functions
'method_field' => [
'is_safe' => [true],
],
],

Related

Cannot retrieve object information passed from php to twig

I have a course description web page as a university project, where I'm currently working on the page where I'm displaying information regarding the approval status of all the courses. I'm retrieving all the courses stored in a database to an array in php, and then passing this array to the twig-file where I want to iterate through the course-array.
However twig doesn't seem to recognize what the 'course' variable in 'courseList' is, as no information is displayed.
Twig
<tbody>
{% for course in courseList %}
<tr>
<th scope="row">{{ loop.index }}</th>
<td>{{ course.getCourseCode }}</td>
<td>{{ course.getCourseName(0, course.getCourseId) }}</td>
<td class="font-weight-bold">{{ course.getCourseApprovalDue }}</td>
<td>
<div class="progress">
<div class="progress-bar {% if course.getStatus == 0 %} bg-warning
{% elseif coruse.getStatus == 1 %} bg-danger {% else %} bg-success {% endif %}" role="progressbar"
style="width: 100%" aria-valuenow="10" aria-valuemin="0" aria-valuemax="10">{{ course.getStatus }}
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
PHP
if ($session->has('loggedin')) {
$courseList = $database->getAllCourses();
echo $twig->render('courseStatus.twig', array('user' => $session->get('user'), 'loggedIn' => true, 'courseList' => $courseList));
} else {
echo $twig->render('login.twig');
}
The database queries and the php functions are working properly. I can verify this by passing a hardcoded course object to the twig file. The coruseList array isn't empty either, as the twig file displays 5 rows when rendering it, which is the same amount as the courses stored in the database.
The array returned from getAllCourses() does not create a new instance of Course, it's just an array containing arrays with Course-data. The solution is to get the arrays, and create a new array with Course-objects with the information returned, and pass this array to the php-file.

Symfony custom form table

I use form theme like it is explain in the documentation https://symfony.com/doc/current/form/form_themes.html with :
{% form_theme form.methodes 'form_table_layout.html.twig' %}
In order to have table and not "div".
My problem is :
For a normal form with "div", i use this code to modify and adapt a collection :
{% block _Examplebundle_methodes_entry_widget %}
Documentation "How to Customize a Collection Prototype" : https://symfony.com/doc/3.4/form/form_customization.html
It work for theme with "div" but with the theme 'form_table_layout.html.twig' it didn't work. I don't know how to custom block with the table theme.
here is a part of my code :
{% form_theme form.methodes 'form_table_layout.html.twig' %}
//////// Block to custom the collection/////////////
{% block _Examplebundle_methodes_entry_widget %}
<tr>
<td>
{{ form_widget(form.methodeEssai) }}
{{ form_errors(form.methodeEssai)}}
</td>
<td>
{{ form_widget(form.ind, {'attr' : {'placeholder' : 'Index'}}) }}
{{ form_errors(form.ind)}}
</td>
<td>a</td>
<td>z</td>
<td>e</td>
<td>r</td>
<td>t</td>
</tr>
{% endblock %}
//////// End Block custom /////////////
{% block body %}
{{ form_start(form) }}
....
<table id="eagle_laboratorybundle_pvp_methodes" class="row"
data-prototype="
{{form_widget(form.methodes.vars.prototype)|e('html_attr') }}"
data-index="{{ form.methodes|length }}">
<thead>
<tr>
<th>x</th>
<th>y</th>
<th>z</th>
<th>a</th>
<th>r</th>
<th>e</th>
<th>t</th>
</tr>
</thead>
<tbody>
{{ form_widget(form.methodes) }}
{{ form_errors(form.methodes) }}
</tbody>
</table>
/// Some JS etc...///
So with the block _entry_widget i expected to custom rows of my table like it permit to custom div when i'm using original layout theme.
Someone know how to custom form rendering with table theme ?

passing session variable in laravel 5.2

I have the modal where I am processing the data in the modal and then I need to store 1 value and pass it to the next page but then for some reason it is not working.
My modal code :- I have the variable $doctorName already set
session(['doctorName' => $doctorName]);
My view file
<div class="col-sm-12 row2">
<table width="100%">
<tr>
<td>
<p>Second Opinion from
<br /><span id="dr_Name"></span></p>
</td>
{{ session('doctorName') }}
<td align="right">
<p>INR 3000/-</p>
</td>
</tr>
</table>
</div>
Try {!! session('doctorName') !!} instead of {{ session('doctorName') }}
Do you open new view after modal? Maybe you need:
return view('someview')->with('doctorName');

Symfony2: use flush() or persist() to optimize data handling

Im working with Symfony (const version="2.5.10") and using XAMPP with PHP version of 5.5.19
My problem is I keep on getting out of memory error. Because I think I query thousand of data (rows) in the database. For info, I have a lot of data in the database. I want to use flush() or anything that could be use to optimize my data handling.
Here is my code in my indexAction controller:
public function indexAction(){
$em = $this->getDoctrine()->getManager();
$po = $em->getRepository('MatrixEdiBundle:EdiTransactionDetail')->findDocs('850');
return $this->render('MatrixEdiBundle:Matrix:index.html.twig', array('po' => $po));
}
index.html.twig
{% extends '::layout.html.twig' %}
{# {% include 'MatrixEdiBundle:Matrix:header.html.twig'%} #}
{% block body %}
<div class="content">
</br>
<table id="datTable" class="table table-bordered table-condensed table-hover">
<thead>
<th colspan="8">Edi Matrix</th>
<tr>
<th>Po Numbers</th>
<th>Trading Partner Id</th>
<th>PO 855 Acknowledgement</th>
<th>PO 997 Acknowledgement</th>
<th>Advance Shipment Notice</th>
<th>Invoice</th>
<th>Purchase Order Change</th>
<th>Order Status</th>
</tr>
</thead>
<tbody>
{% for tran in po %}
<tr>
<td><a href="{{ path('matrix_edi_showpo', {'po_num': tran.poNumber}) }}"data-toggle="modal" data-target="#myModal">{{tran.poNumber}}</td>
<td>{{tran.ediTransaction.senderId}}</td>
<td><a href="{{ path('matrix_edi_findAll', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'doc_type': 855}) }}"data-toggle="modal"data-target="#myModal">
{{ render(controller('MatrixEdiBundle:Matrix:matrix', {
'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran. ediTransaction.receiverId, 'doc_type': 855, 'gs_number': tran.ediTransaction.gsNumber })) }}</a>
</td>
<td><a href="{{ path('matrix_edi_poack', {'gs_number': tran.ediTransaction.gsNumber, 'receiver_id': tran.ediTransaction.receiverId, 'sender_id': tran.ediTransaction.senderId}) }}"data-toggle="modal"data-target="#myModal">
{{ render(controller('MatrixEdiBundle:Matrix:matrix', {
'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran. ediTransaction.receiverId, 'doc_type': 997, 'gs_number': tran.ediTransaction.gsNumber })) }}</a>
</td>
<td><a href="{{ path('matrix_edi_findAll', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'doc_type': 856}) }}"data-toggle="modal"data-target="#myModal">{{ render(controller('MatrixEdiBundle:Matrix:matrix', {
'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type': 856, 'gs_number': tran.ediTransaction.gsNumber }))}}</a>
</td>
<td>{{ render(controller('MatrixEdiBundle:Matrix:matrix', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type': 810, 'gs_number': tran.ediTransaction.gsNumber})) }}
</td>
<td>{{ render(controller('MatrixEdiBundle:Matrix:matrix', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type':860, 'gs_number': tran.ediTransaction.gsNumber})) }}
</td>
<td><a href="{{ path('matrix_edi_findAll', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'doc_type': 870}) }}"data-toggle="modal"data-target="#myModal">{{ render(controller('MatrixEdiBundle:Matrix:matrix', {
'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type': 870, 'gs_number': tran.ediTransaction.gsNumber
})) }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false" >
<div class="modal-dialog">
<div class="modal-content" style="width: 650px;">
<div class="modal-header" style="background-color: #2d6ca2; color: white;">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true" style="color: white;">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel" >Details</h4>
</div>
<div class="modal-body">
Loading, please wait......
<div class="bootstrap-table">
<div class="fixed-table-container" style="height: 299px; padding-bottom: 37px;">
<div class="fixed-table-body">
<div class="fixed-table-loading" style="top: 27px; display: none;">Loading, please wait…</div>
</div>
<div class="fixed-table-pagination"></div>
</div>
</div><div class="clearfix"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" >Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
{% endblock %}
{% block javascripts %}
{% javascripts
'bundles/matrixdoc/js/jQuery.js'
'bundles/matrixdoc/js/jquery.dataTables.min.js'
'bundles/matrixdoc/js/dataTables.bootstrap.js'
'bundles/matrixdoc/js/bootstrap.js'
%}
<script src="{{ asset_url }}"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#datTable').dataTable( {
"scrollY": "400px",
"scrollCollapse": true,
"pagingType": "simple",
});
$('body').on('hidden.bs.modal', '.modal', function () {
$(this).removeData('bs.modal');
});
$(document).on("hidden.bs.modal", function (e) {
$(e.target).removeData("bs.modal").find(".modal-content").empty();
});
});
</script>
{% endjavascripts %}
{% endblock %}
You should use pagination getting your data with limits and coupled with partial to get your needed fields if you don't need everything.
http://zrashwani.com/pagination-optimization-symfony2-doctrine/#.VV1av_mSwbg
for partial in DQL , simple example for user:
//partial_fields is an array, which can be passed like this $repo->getPartialUser($user_id, array('field1', 'field2', 'etc..');
public function getPartialUser($id, $partial_fields){
$qb = $this->_em->createQueryBuilder()
->select('partial u.{'.implode(',',$partial_fields).'}')
->from('AcmeUserBundle:User', 'u')
->where('u.id = :id')
->setParameter('id', $id);
$result = $qb->getQuery()->getOneOrNullResult();
return $result;
}
EDIT EXAMPLE CODE :
i will give you an example but you will probably still need to adapt it to your code or maybe it will work out of the box.
First you need a new twig with simple piece of code to show pages numbers for navigation below the table (note that i will not use datatables paginator but we will keep it for table layout rendering) :
pager.html.twig
<div class="pagination">
<div class="pagination-buttons">
{% if pagination.page>1 %}
<a href="{{ path(pagination.route,
pagination.route_params|merge({'page': 1})) }}"><<</a>
<a href="{{ path(pagination.route,
pagination.route_params|merge({'page': pagination.page-1})) }}"><</a>
{% endif %}
{#display p numbers only from p-4 to p+4 but don't go <1 or >pages_count#}
{% for p in range(max(pagination.page-4, 1),
min(pagination.page+4, pagination.pages_count)) %}
<a{% if p == pagination.page %} class="current-page"{% endif %}
href="{{ path(pagination.route,
pagination.route_params|merge({'page': p})) }}">{{ p }}</a>
{% endfor %}
{% if pagination.page<pagination.pages_count %}
<a href="{{ path(pagination.route,
pagination.route_params|merge({'page': pagination.page+1})) }}">></a>
<a href="{{ path(pagination.route,
pagination.route_params|merge({'page': pagination.pages_count})) }}">>></a>
{% endif %}
</div>
</div>
EdiTransactionDetailRepository:
add a function with your field that you use in your table :
public function getPagedDocs($page = 1, $limit = 50)
{
$qb = $this->_em->createQueryBuilder()
->select('partial d.{field1,field2 , etc..},
partial et.{field1,field2, etc..}'
))//select doc fields and second partial for your join select edittransaction fields if you have other joins add another partial etc..
->from('YourBundle:DocsEntity', 'd')
->innerJoin('d.ediTransaction', 'et')//not sure which join you need i have no clue but i believe you will want an inner one since you will want a doc to have a ediTransaction because i didn't see any checks in your twig for it if null.
->setFirstResult(($page - 1) * $limit)
->setMaxResults($limit);
$paginator = new Paginator($qb, $fetchJoinCollection = false);//for more performance fetchjoincollection to false if you have joined tables
$paginator->setUseOutputWalkers(false);//for more performance set to false for more information http://www.doctrine-project.org/jira/browse/DDC-2890
return $paginator;
}
PS: Change limit to how many records you want to show in each page depending on the load of data you have make it lower if it is slow for 50 this is depend on how much data each row have.
Next the indexAction in your controller :
public function indexAction($page){
$em = $this->getDoctrine()->getManager();
$po = $em->getRepository('MatrixEdiBundle:EdiTransactionDetail')->getPagedDocs($page, 50);
$count = $po->count();
$pagination = array(
'page' => $page,
'route' => 'docs_index_route_name', //i dont know which name you have but it should be the route name of this indexAction
'route_params' => array()
);
if ($max_records > 0)
$pagination['pages_count'] = max(ceil($count / $max_records), 1);
return $this->render('MatrixEdiBundle:Matrix:index.html.twig', array('po' => $po,
'pagination' => $pagination
));
}
Routing:
You need to modify the route of your indexAction as we added a parameter page you need to add it for the route too :
index_docs:
pattern: /index/{page}
defaults: { _controller: "YourBundle:Controller:index", page: 1 }
NOTE : you will need to change the names and stuff i dont know you controller names and bundles so normally you will only need to add /{page} to the pattern and , page:1 to your _controller config which is the default value.
Last thing to do is your index.html.twig which need to include our pager.html.twig
include this piece of code after you close your table :
{% if po|length > 0 and pagination['pages_count'] is defined and pagination['pages_count'] > 0 %}
{#---------Pager----------#}
<div style="text-align:center;">
{% include 'YourBundle:EntityDoc:pager.html.twig' %}
</div>
{% endif %}
NOTE : The include is the path to the file where you create the pager.html.twig i assume you are familiar with how this works.
So if i didn't forget anything this should work out of the box , it should enhance greatly your performance but i am afraid that your render controller there for each row may still be problematic. But try this solution first and see, it depends what you put inside those controllers.

symfony2 collection set default values

Using Symfony2, we have a Product form which has a collection of productOption forms. This works fine, however we wish to have some values within the productOption form set to 0 by default.
I have tried solutions given in other StackOverflow questions, but I still just get blank fields. Currently, the desired default values are being set via the Entity's constructor as such:
// ProductOptionValue Entity
public function __construct()
{
$this->option_values = new \Doctrine\Common\Collections\ArrayCollection();
$this->subtract = true;
$this->price = 0.00;
}
The prototype of the form collection is not standard - it's modified via a macro within the template which outputs the form:
{% macro product_option_value_prototype(product_option_value) %}
<td>
<div class="product_option_value_widget">{{ form_widget(product_option_value.option_value) }}</div>
<div class="product_option_value_error">{{ form_errors(product_option_value.option_value) }}</div>
</td>
<td>
<div class="product_option_value_widget">{{ form_widget(product_option_value.quantity) }}</div>
<div class="product_option_value_error">{{ form_errors(product_option_value.quantity) }}</div>
</td>
<td>
<div class="product_option_value_widget">{{ form_widget(product_option_value.subtract) }}</div>
<div class="product_option_value_error">{{ form_errors(product_option_value.subtract) }}</div>
</td>
<td>
<div class="product_option_value_widget">{{ form_widget(product_option_value.price_multiplier) }}</div>
<div class="product_option_value_error">{{ form_errors(product_option_value.price_multiplier) }}</div>
</td>
<td>
<div class="product_option_value_widget">{{ form_widget(product_option_value.taxed_price) }}</div>
<div class="product_option_value_error">{{ form_errors(product_option_value.taxed_price) }}</div>
</td>
{% endmacro %}
... Which, in the same template is used via:
<table class="product_option_values" data-prototype="{{ _self.product_option_value_prototype(form.product_option_values.vars.prototype)|e }}">
I have tried setting other values as the defaults (10 instead of 0) in case Symfony ignored them at 0.
I have also tried implementing this CollectionTypeExtension Gist. Whatever I try, we still get blank fields by default. Because other solutions on StackOverflow seem to give people success, I feel there must be something wrong elsewhere to the entity or FormType, but we are having no success in finding it. Any ideas?

Categories