I'm trying to display data from database.
This is my routing:
pages:
pattern: /pages/{id}
defaults:
_controller: DprocMainBundle:Index:show
This is the method for that route:
public function showAction($id)
{
$page = $this->getDoctrine()
->getRepository('DprocMainBundle:Pages')
->find($id);
if (!$page) {
throw $this->createNotFoundException('No product found for id '.$id);
}
return $this->render('DprocMainBundle:Dproc:single.html.twig',array('pages' => $page));
}
print_r($page) displays:
Dproc\MainBundle\Entity\Pages Object
(
[Id:protected] => 1
[page_title:protected] => A Foo Bar
[page_content:protected] => Test content for page
[page_category:protected] => 3dsmax
)
In single.html.twig im trying to display that information:
{% for page in pages %}
{{ page.page_title }}
{% endfor %}
It shows nothing, what i'm doing wrong?
The method find() will just return a single result, not an array. If you did findBy(array('id'=>$id)) then you would get an array back with one result. Alternatively you could just not loop through in your template because there's no need when you have only one result. Just change your variable name to page and use {{ page.page_title }}
You used two differents entity.. one is in getRepository('DprocMainBundle:Pages') and other is in render('DprocMainBundle:Dproc:single.html.twig',array('pages' => $page)). You should put there the same entity i.e DprocMainBundle:Pages . I hope this you success.
Try it without the for loop. Because you have post data from the database, you can try this:
{{ pages.page_title }}
Related
I am new to symfony/doctrine and when setting up my first table and query I am struggling with the best way to output results in Twig.
So, I have this method on \AppBundle\Controller\BrandsController
public function showAction($brand)
{
$product = $this->getDoctrine()
->getRepository('AppBundle:Brands')
->findOneByBrand($brand);
if (!$product) {
throw $this->createNotFoundException(
'No product found for id '.$brand
);
}
return $this->render('brands/brands.html.twig', [
'product' => $product
]);
}
This produces an object like below, which I cannot iterate over.
Brands {#459 ▼
-brand_id: 24
-brand: "Ford"
-active: "Y"
-img_logo: "/img/brand/ford.png"
-img_logo_small: "/img/brand/ford_20.png"
-img_logo_big: "/img/brand/ford-big.png"
}
Of course I can create a query like below, but that negates the benefit of the findBy() method:
$repository = $this->getDoctrine()
->getRepository('AppBundle:Brands');
$query = $repository->createQueryBuilder('p')
->where('p.brand = :brand')
->setParameter('brand', $brand)
->getQuery();
$product = $query->getSingleResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
I found similar questions, like this one, but they mess up with the array keys by giving a array that looks like:
array:6 [▼
"\x00AppBundle\Entity\Brands\x00brand_id" => 24
"\x00AppBundle\Entity\Brands\x00brand" => "Ford"
"\x00AppBundle\Entity\Brands\x00active" => "Y"
"\x00AppBundle\Entity\Brands\x00img_logo" => "/img/brand/ford.png"
"\x00AppBundle\Entity\Brands\x00img_logo_small" => "/img/brand/ford_20.png"
"\x00AppBundle\Entity\Brands\x00img_logo_big" => "/img/brand/ford-big.png"
]
By the way, that's the simple version of the code on brands/brands.html.twig:
{% for item in product %}
<p> This is my {{ item }}</p>
{% endfor %}
Is there a clean way to do it?
Thanks
The idea is to use Entity Serializer Doctrine Script , look to the link below :
https://github.com/borisguery/bgylibrary/blob/master/library/Bgy/Doctrine/EntitySerializer.php
Just copy the script into a new class : EntitySerializer.php , under AppBundle\Controller , then in your BrandsController class:
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AppBundle:Brands') ->findOneByBrand($brand);
$serializer = new EntitySerializer($em);
$product = $serializer->toArray($product);
and finnally you can easily iterate the array :
foreach ($array as $key => $value) {
echo 'the key is '.$key.'<br>';
echo 'the value is '.$value;
}
General...
It's kinda bad idea to iterate through your product in twig like an array. Just because it's matter of time till you'll need more controll like show/do this if product is active or not... and so on. So pretty soon you'll have to do somthing like this (just an wild example of possible usecase...)
{% if product|default %}
{# if logo isn't there or empty or similar use path to no-logo.png as fallback #}
{% set _product_logo_path = product.img_logo|default('/assets/images/no-logo.png') %}
{{ product.brand }} <img src="{{- _product_logo_path -}}" title="blah blah" />
{% if not product.isActive|default %}
<span>currently unavailable</span>
{% endif %}
{% endfi %}
Architectual...
You can use your repository for that kind of "manipulation"
something like :
in your controller:
$product = $this->getDoctrine()
->getRepository('AppBundle:Brands')
->findOneForViewByBrand($brand);
// concider to use instanceof since you expecting Brands object
// if not stay with !$product
if( false === $product instanceof Brands )
{
// not found exception..
}
in your Repo-Class
public function findOneForViewByBrand( $brand )
{
// you ca make use of PARTIAL SELECTS
// NOTE: if you use PARTIAL selects you have to select at least id, like PARTIAL p.{brand_id}
$query = $this->createQueryBuilder('p')
->select('PARTIAL p.{brand_id, brand, active, img_logo, img_logo_small, img_logo_big}')
->where('p.brand = :brand')
->setParameter('brand', $brand)
->getQuery();
// If found you'll get a Brand BUT ONLY field in curly brackets will be populated with data, others will be just NULL
return $query->getOneOrNullResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
}
and then in your twig
{% for fieldName, fieldValue in product %}
{# should skip null values #}
{% if fieldValue is defined and fieldValue is not empty % }
<p> This is my {{ fieldValue }}</p>
{% endif %}
{% endfor %}
About Partial Selects
P.S. code is untested and it's here so you can get an idea ;) I don't know what version of symfony you use and what version of doctrine is installed, so if one of mentioned methods doesn't exists - please don't be angry :)
Hello in my project I using VentureCraft/revisionable https://github.com/VentureCraft/revisionable This is addition to recording the history of changes to records in databse. Everything works fine, but when I returned the history on page, the script returns the results in the form of id. This is my table "products" products_table and this is table "revisions" revisions_table This table is connected to the tables: articles, users and categories. Now the history change looks like this:
"User 1 change name article from 2 to 1"
I want to the history change looked like:
"User JACK change name article from SHOES to BALL"
I try using this link.
method identifiableName() with file Revisionable.php looks like this:
public function identifiableName()
{
return $this->getKey();
}
In model product.php I added:
public function identifiableName(){
return $this->article_name;
}
or this:
public function identifiableName(){
return $this->article()->article_name;
}
but it does not work.
OK I found solution to this problem:
Only just use:
whereId or find or faindOrFail
example:
article::whereId( $hist->old_value )->first()->article_name
or
article::find( $hist->old_value )->article_name
or
article::findOrFail( $hist->old_value )->article_name
Where article:name is name column in articles table.
you can use
$history->userResponsible()->first_name
like the documentation says
#foreach($resource->revisionHistory as $history)
#if($history->key == 'created_at' && !$history->old_value)
<li>{{ $history->userResponsible()->first_name }} created this resource at {{ $history->newValue() }}</li>
#else
<li>{{ $history->userResponsible()->first_name }} changed {{ $history->fieldName() }} from {{ $history->oldValue() }} to {{ $history->newValue() }}</li>
#endif
#endforeach
or if you want to use it as response api, you can manipulate the response to get their relations
$response = $question->revisionHistory->map(function($history) {
return ['history' => $history, 'users' => $history->userResponsible()];
});
return response()->json($response);
i'm trying to make a loop in php while using twig and inside this loop,
i am creating a parameter which contains the record from the database query.
The problem is that when I use the parameter in my HTML file, it only return 1 record from the while loop, even if there are 3 or 4 or even more..
This is the php code I have:
public function getWidgetsByName($name)
{
global $params;
$get = $this->db->query("SELECT * FROM profile_items
WHERE category = 'widget'
AND username = '". $name ."'");
if($get)
{
while($key = $get->fetch())
{
$params["profile_widget_name"] = $key['name'];
}
}
}
And this is the HTML parameter in my HTML twig rendered file:
{{ profile_widget_name }}
The paremeters just get rendered how they are supposed to be rendered:
echo $twig->render('app/views/'. $_REQUEST['p'] .'.html', $params);
And yes the $params variable is an array, in the config it file it first gets used as $params = array("..." => "..."); and I add things to this array by doing $params["..."] = "...";
So, I hope someone can help me.
Thanks in advance,
Best Regards.
At the moment, the value of $params["profile_widget_name"] is just one string. Every time you go through the while loop, you overwrite the previous value of the key with the current value.
So when you pass $params to Twig, the value of profile_widget_name is the value of name in the last row of the database to be selected.
I think what you want instead is for the value of profile_widget_name to be an array. Then every time you go through the loop, the current value of name is added to the array, instead of overwriting it.
You do this by doing something like:
$params["profile_widget_names"][] = $key['name'];
Now in your Twig template, you'll need to do something like:
{% for profile_widget_name in profile_widget_names %}
{{ profile_widget_name }}
{% endfor %}
Using Multiple Parameters
If you want multiple parameters to be on there, you can do this:
$params["profile_widgets"][] = [
'pos_x' => $key['pos_x'],
'name' => $key['name'],
];
And in Twig:
{% for profile_widget in profile_widgets %}
Name: {{ profile_widget.name }}
Pos X: {{ profile_widget.pos_x }}
{% endfor %}
I am brand new to Laravel, and following a super basic tutorial.
However the tutorial did not come with an edit record section, which I am attempting to extend myself.
Route:
Route::controller('admin/products', 'ProductsController');
Controller:
class ProductsController extends BaseController
{
public function getUpdate($id)
{
$product = Product::find($id);
if ($product) {
$product->title = Input::get('title');
$product->save();
return Redirect::to('admin/products/index')->with('message', 'Product Updated');
}
return Redirect::to('admin/products/index')->with('message', 'Invalid Product');
}
..ECT...
I realise the controller is requesting an ID to use, but I cannot figure out how to pass it a product ID when the form is posted/get.
Form:
{{Form::open(array("url"=>"admin/products/update",'method' => 'get', 'files'=>true))}}
<ul>
<li>
{{ Form::label('title', 'Title:') }}
{{ Form::text('title') }}
{{ Form::hidden('id', $product->id) }}
..ECT...
{{ Form::close() }}
my initial idea was to pass the product id within the form URL like:
{{Form::open(array("url"=>"admin/products/update/{{product->id}}", 'files'=>true))}}
But no luck with that either.
The error I get is:
Missing argument 1 for ProductsController::postUpdate()
Interestingly if I type directly into the URL:
http://localhost/laravel/public/admin/products/update/3
It works and the item with id 3 is altered fine.
So can anyone help and inform me how to pass the id with a form?
Thanks very much
The first Problem here ist the following:
{{Form::open(array("url"=>"admin/products/update/{{product->id}}", 'files'=>true))}}
the {{product->id}} is wrong in two ways:
it should be {{$product->id}}
BUT it wouldn't work anyway because the inner {{..}} inside of the {{Form::...}} won't be recognized since it is inside a string and therefore part of the string itself.
You either have to write it this way:
{{Form::open(array("url"=>"admin/products/update/".$product->id, 'files'=>true))}}
or you give your route a name in your routes.php file and do it this way:
{{Form::open(array('route' => array('route.name', $product->id, 'files'=>true)))}}
I prefer the second way.
You also might want to look into Form Model Bingin
I`am rendering a twig template in symfony2 and its possible to get a variable with value of array type but i am trying to preview the variable and this error pops:
Array to string conversion ...
So my qustion is not how to print out the array, but is it possible in twig to disable this error, so when an array comes and it cannot be outputed, to set an empty value.
In config.yml, under twig i have set
strict_variables: false
But this dose not include printing arrays.
EDIT:
In controller I pass this array to twig, for example:
'data' => array(
'description' => array(
'desc1',
'desc2'
)
);
In twig I am trying to print {{ data['description'] }} and I got the following error:
Array to string conversion ...
This is the normal error that must pop, but I need if I try to print this a no error to pop but instead I need to print nothing(empty value), same way like trying to print an non existing variable with twig set with
strict_variables: false
ANSWER:
Make a custom function:
public function getFunctions()
{
return array(
'to_string' => new \Twig_Function_Method($this, 'toString')
);
}
public function toString($data) {
if(is_array($data)) {
return '';
}
return $data;
}
And in twig template:
{{ to_string(data['description']) }}
You have two desc: desc1 and desc2, what do you want to print? If both you have to use this notation (for instance)
{{ data['description'][desc1] }} - {{ data['description'][desc2] }}
More in general:
{% for desc in data['description'] %}
{{ desc }}
{% endfor %}
EDIT
Ok, now I got it (from your comment):
{% if data['description'] is iterable %}
//echo here an empty string
{% else %}
{{ data['description'] }}
{% endif %}