I am using twig as templating engine but my html is not rendering. All is displayed with the HTML tags itself.
Data from Database can be found by clicking here
I searched SO and got many posts that provides solution but none worked for me
below are the solutions:
Use below code [not working]
{{ detailArticle.artdesc|raw }}
or
{% autoescape false %}
{{ detailArticle.artdesc }}
{% endautoescape %}
Use filter and autoload like below [not working]
$app->view = new \Slim\Views\Twig();
$app->view->setTemplatesDirectory("application/view");
$app->view->parserOptions = array(
'debug' => 'true',
'auto_reload' => true,
'autoescape' => true
);
$app->view->parserExtensions = array(new \Slim\Views\TwigExtension());
Clear Twig cache [I do not have CLI on cPanel, so not sure how to do this]
rm -rf app/cache/* OR rm -rf app/cache/prod/twig OR app/console cache:clear --env=prod
None of the solutions working for me. Please guide.
Data is displayed in same way you will see on the link mentioned above.
My composer.json is as below
{
"name":"panique/mini2",
"homepage":"https://github.com/panique/mini2",
"license":"MIT",
"require":{
"php":">=5.3.0",
"slim/slim": "~2.6",
"slim/views": "~0.1",
"twig/twig": "~1.16",
"panique/pdo-debug": "0.2",
"panique/php-sass": "~1.0",
"matthiasmullie/minify": "~1.3"
},
"autoload":{
"psr-4":{
"Mini\\": "Mini"
}
}
}
I solved this same problem a few months ago.
You need write this in your php:
$escaper = new Twig_Extension_Escaper(false);
$app->view->addExtension($escaper);
My code
require_once 'path_to_Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('path_to_views/');
$twig = new Twig_Environment($loader, array());
$escaper = new Twig_Extension_Escaper(false);
$twig->addExtension($escaper);
echo $twig->render($view_name, $data_to_view);
Steps with your code
Download: http://pear.twig-project.org/get/Twig-1.24.0.tgz
Uncompress and place in you proyect.
Write this in your file:
require 'vendor/autoload.php';
// Initialize Slim (the router/micro framework used)
$app = new \Slim\Slim(array(
'mode' => 'production'
));
require_once 'path_to_Twig/Autoloader.php'; //Substitute the Twig path, the path to the uncompress files in the project
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('path_to_views/'); //Substitute with the path with the html files
$twig = new Twig_Environment($loader, array());
$escaper = new Twig_Extension_Escaper(false);
$twig->addExtension($escaper);
echo $twig->render($view_name, $data_to_view); //First the name of the view html file, data that you want pass to the view in one array
You need put all this whe you want render the view in the controller, that is to say, you substitute your code by this.
Ran into the same issue and resolved it by adding the Twig_Extnesion_Escaper:
$v = new \Slim\Views\Twig(__DIR__ . '/../../templates', [
'cache' => __DIR__ . '/../../templates/twigcache'
]);
$v->addExtension(new Twig_Extension_Escaper());
Related
I want to use the markdown_to_html filter to render makrdown inside my template, so I tried following the instructions in the docs but the filter is not added correctly. The error I get when rendering the template is Message: Unknown "markdown_to_html" filter.
Here's my code:
// Load twig and the markdown extension
require_once "../vendor/autoload.php";
$loader = new \Twig\Loader\FilesystemLoader("../templates");
$twig = new \Twig\Environment($loader, [
"cache" => "../cache/twig",
"debug" => true,
"autoescape" => false,
]);
use Twig\Extra\Markdown\DefaultMarkdown;
use Twig\Extra\Markdown\MarkdownRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
public function load($class) {
if (MarkdownRuntime::class === $class) {
return new MarkdownRuntime(new DefaultMarkdown());
}
}
});
// Read md file and render template
$markdown = file_get_contents("content/text.md");
try {
echo $twig->render("template.phtml", ["text" => $markdown]);
}
catch(Exception $e) {
echo 'Message: ' . $e->getMessage();
}
The template:
{% apply markdown_to_html %}
{{ text }}
{% endapply %}
I added twig/twig and twig/markdown-extra, both are version 3.0. Thanks for any help.
You forgot to add the extension with
$twig->addExtension(new MarkdownExtension());
Note how the docs say
If you are not using Symfony, you must also register the extension runtime:
whily you did it instead
This is a continuation of a previous question.
Where is ->getForm() method located for Symfony3 CreateFormFactory
I got past that hurdle and now the system is unable to locate the template directory. I am still following the Symfony guide. https://symfony.com/doc/3.4/components/form.html#rendering-the-form
Referring to line 23 of the guide looks like the real directory needs to be passed to twig. See the image below for reference.
I know it looks redundant but It was an attempt to just tell Twig where the template is located. This returned an error.
Uncaught Twig\Error\LoaderError: The "C:\oerm_dev\www\dev\future5_2\vendor\symfony\twig-bridge../../templates/billing" directory does not exist ("C:\oerm_dev\www\dev\future5_2\vendor\symfony\twig-bridge../../templates/billing"). in C:\oerm_dev\www\dev\future5_2\vendor\twig\twig\src\Loader\FilesystemLoader.php:106
As you can see on the left where the template directory is located. It seems as though Twig wants to look in its own folder instead of the folder location is given. I have tried a couple of different variations.
$loader = new FilesystemLoader(['../../templates/billing',
$vendorTwigBridgeDirectory.'requeueCharge.html.twig']);
This produces an error also.
Uncaught Twig\Error\LoaderError: The "C:\oerm_dev\www\dev\future5_2\vendor\symfony\twig-bridge\requeueCharge.html.twig" directory does not exist
Which the error message is true, the location does not exist. But then I am still left with how to redirect twig to the folder where the view is located?
UPDATE
I just went ahead and created the folder and moved the layout.html.twig file to the location. Now the error message is
Uncaught Symfony\Component\Form\Exception\LogicException: No block "form_start" found while rendering the form.
Template.php(380): Twig\Template->displayWithErrorHandling(Array, Arr in C:\oerm_dev\www\dev\future5_2\templates\billing\requeueCharge.html.twig on line 8
Line 8 in that file reads as follows:
{% extends 'layout.html.twig' %}
{% block title %}{% endblock %}
{% block body %}
<div class="container">
<h3></h3>
{{ form_start(reportForm) }}
{{ form_widget(reportForm) }}
<button type="submit" class="btn btn-primary">Search</button>
{{ form_end(reportForm) }}
The problem was not in the template/billing but code needed to point to the built-in templates that come with the component twig-bridge. In the example, the folder Resource/views/Forms is a real directory that has to be used.
What I found out is that I need to read more closely and investigate every line of code that is presented. So, that is a self-evaluation. This is what solved the riddle.
I ended up with this:
use Symfony\Bridge\Twig\Extension\FormExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
use Symfony\Component\Form\FormRenderer;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage;
use Symfony\Component\Security\Csrf\CsrfTokenManager;
use Symfony\Component\Security\Csrf\TokenGenerator\UriSafeTokenGenerator;
use Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage;
use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Component\Translation\Translator;
use Twig\Environment;
use Twig\Extension\DebugExtension;
use Twig\HeaderExtension;
use Twig\Loader\FilesystemLoader;
use Twig\RuntimeLoader\FactoryRuntimeLoader;
class RequeueChargesController extends Controller
{
public function requeueCharge()
{
$defaultFormTheme = 'form_div_layout.html.twig';
$vendorDirectory = dirname(__DIR__, 2).'\vendor';
$translator = new Translator('en');
$translator->addLoader('xlf', new XliffFileLoader());
//$form->handleRequest();
$session = new Session(new PhpBridgeSessionStorage());
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new SessionTokenStorage($session);
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$appVariableReflection = new \ReflectionClass('\Symfony\Bridge\Twig\AppVariable');
$vendorTwigBridgeDirectory = dirname($appVariableReflection->getFileName());
$loader = new FilesystemLoader(['../../templates/billing/',
$vendorTwigBridgeDirectory.'/Resources/views/Form']);
$twig = new Environment($loader, [
'debug' => true,
]);
$twig->addExtension(new HeaderExtension());
$twig->addExtension(new DebugExtension());
$twig->addExtension(new TranslationExtension($translator));
$formEngine = new TwigRendererEngine([$defaultFormTheme], $twig);
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
FormRenderer::class => function () use ($formEngine, $csrfManager) {
return new FormRenderer($formEngine, $csrfManager);
}
]));
$twig->addExtension(new FormExtension());
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new HttpFoundationExtension())
->addExtension(new CsrfExtension($csrfManager))
->getFormFactory();
$form = $formFactory->createBuilder(TaskType::class)
->getForm();
return $twig->render('requeueCharge.html.twig', [
'payments' => 'Charge',
'reportForm' => $form->createView()
]);
}
}
The example code that was given in https://symfony.com/doc/3.4/components/form.html#rendering-the-form needed little alteration to work.
You can compare the example with what I had to do to get it working in the OpenEMR codebase. If you have any questions, try me.
I'm having a hard time trying to make this little modification...
I want to render a file (login.twig) which is inside my views file but in another folder: /views/ajax_files/login.twig
do I have to do this everytime ?
require 'vendor/autoload.php';
$loader = new Twig_Loader_Filesystem('views/ajax_files');
$twig = new Twig_Environment($loader, array(
'cache' => 'cache',
'auto_reload' => true,
));
echo $twig->render('login.twig');
Because on my index.php, that is already being declared
which I'm trying to write DRY code
require 'vendor/autoload.php';
$loader = new Twig_Loader_Filesystem('views');
$twig = new Twig_Environment($loader, array(
'cache' => 'cache',
'auto_reload' => true,
));
echo $twig->render('index.twig');
You can also define multiple template directories directly in your index.php with
$loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2));
Please also have a look at http://twig.sensiolabs.org/doc/api.html#loaders, you could also use a loader chain or simply add the additional path to your existent filesystem loader, with some code like
$loader = $twig->getLoader();
$loader->addPath('another/path/to/templates'); //or $loader->prependPath('...')
$twig->setLoader($loader);
I am working with the TWIG framework for php, and would like to know how i would be able to include these php files inside my php code like i normally do.
<?php
session_start();
include("includes/db.php");
include("functions/searchfunctions.php");
include("functions/userSearchSession.php");
?>
The db file establishes the connection through mysqli to the database.
In your comments you mentioned you are using the Slim framework, which has an extension to support Twig templates.
Using the extension however, requires some additional setup though, you must install the extention, called Slim Views, and also the Twig core from within composer. Slim Views does not list Twig as a dependancy.
To get this working:
Use composer to get add both Slim Views And Twig
$ php composer require slim/views
$ php composer require twig/twig:~1.0
Configure your Slim Framework $app to use the new tempting engine.
$view = $app->view();
$view->parserOptions = array(
'debug' => true,
'cache' => dirname(__FILE__) . '/cache'
);
$view->parserExtensions = array(
new \Slim\Views\TwigExtension(),
);
At this point, Slim Framework is now using Twig when rendering pages. You can now do all of your includes and pass the variables to Twig:
<?php
// ./Slim_app.php
require 'vendor/autoload.php';
/*
* foo.php contains the following:
* <?php
* $foo = bar;
*
*/
require 'foo.php';
$app = new \Slim\Slim(array(
'view' => new \Slim\Views\Twig()
));
$view = $app->view();
$view->parserOptions = array(
'debug' => true,
'cache' => dirname(__FILE__) . '/cache'
);
$view->parserExtensions = array(
new \Slim\Views\TwigExtension(),
);
$app->get('/hello', function () use ($app, $foo) {
//twig_template.html.twig exists in the templates directory.
//(./templates/twig_template.html.twig)
$app->render('twig_template.html.twig', array('foo' => $foo));
});
$app->run();
?>
{# ./templates/twig_template.html.twig #}
{{ foo }}
Navigating to Slim_app.php/hello now displays the following:
More info on using Twig.
My question: How do I permit use of debug in Twig templates within Silex?
I'm playing around with the Silex micro-framework (a PHP framework that leverages Symfony).
When using the Twig template system with it I wanted to output a particular object. Normally I would do this with var_dump($app); and in Twig with {% debug app %}.
My problem is getting debug (and setting Silex's own debug to true does not help with Twig) to work with Silex. Out of the box a call to debug will result in an error message:
Twig_Error_Syntax: Unknown tag name "debug" in...
The call to debug looks like this:
{% debug app %}
I have found references to how to configure Twig's config.yml file to correctly use debug but Silex does not use a config file for Twig.
Silex does say you can set options via passing an associative array to twig.options and while Twig docs say you can pass an environment option like:
$twig = new Twig_Environment($loader, array('debug' => true));
Trying to pass it in Silex like:
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.options' => array('debug' => true),
));
Does not work. Is this the wrong sort of option? Simply incorrect formatting? I've no idea and nothing I have tried works.
I sense myself getting into "wheel spinning" mode so I am asking here on SO in hopes that I can move on to more productive work this morning. :)
(ugh... how's that for a hyper-specific StackOverflow question?)
Solution: (all this just to get var_dump like functionality... oh my): This was a bit of a pain in the butt, to be honest, and the Silex docs were of no help whatsoever in discovering this but here is what I had to do to get this to work.
First load the Twig autoloader:
$app['autoloader']->registerPrefixes(array(
'Twig_Extensions_' => array(__DIR__.'/vendor/Twig-extensions/lib')));
Why do you have to register it this way? No idea. How does it actually find the autoloader? No idea. But it works.
Register the provider and set the debug option:
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__.'/views',
'twig.class_path' => __DIR__.'/vendor/Twig/lib',
'twig.options' => array('debug' => true), //<-- this is the key line to getting debug added to the options
));
And finally (the best part):
$oldTwigConfiguration = isset($app['twig.configure']) ? $app['twig.configure']: function(){};
$app['twig.configure'] = $app->protect(function($twig) use ($oldTwigConfiguration) {
$oldTwigConfiguration($twig);
$twig->addExtension(new Twig_Extensions_Extension_Debug());
});
To be honest, I think that's enough Silex for me.
Credit for this solution goes to Nerdpress.
*ninja edit: a year and a half later I have to say that Silex was a dud for me. I have been using Slim for all micro-framework needs and it is fantastic. Gets the job done quickly, cleanly, simply and easily.
I completely removed the old answer to show the output from a little example-app I built:
composer.json:
{
"require": {
"silex/silex": "1.*",
"twig/twig": "1.*",
"twig/extensions": "*"
}
}
app.php:
require_once __DIR__ . '/../vendor/.composer/autoload.php';
$app = new Silex\Application();
$app['debug'] = true;
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__ . '/views',
'twig.options' => array('debug' => true)
));
$app['twig']->addExtension(new Twig_Extensions_Extension_Debug());
$app->get('/', function () use ($app) {
return $app['twig']->render('debug_test.twig', array('app' => $app));
});
$app->run();
for silex ^2.2 using pimple 3 the share() has been removed so use:
$app->extend('twig', function($twig, $app) {
$twig->addExtension(new Twig_Extension_Debug());
return $twig;
});
It has been a while now so I did a small update to the accepted answer, you can use the new extend method of Pimple:
composer.json:
"silex/silex": "~1.3",
"twig/twig": "^1.23",
"symfony/twig-bridge": "^2.7",
"twig/extensions": "^1.3"
index.php (front controller)
/*
* config
*/
//...
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__.'/../templets',
'twig.options' => array('debug' => true),
)
);
$app['twig'] = $app->share($app->extend('twig', function($twig, $app) {
$twig->addExtension(new Twig_Extension_Debug());
return $twig;
}));
//...
/*
* some static page
*/
$app->get('/', function () use($app) {
return $app['twig']->render('index.twig');
});
$app->run();