Phalcon Template "Undefined variable" (variable is set) - php

I want to show a template file (ajax include) with variable from controller.
I want to create a simple shoutbox.
development environment:
PHP Version 5.6.19 (xampp)
Phalcon 2.1.0r (php c-ext)
Windows 10
IDE Netbeans
This is the include part: (it works)
$("#shoutbox_messages").load("{{ static_url("shoutbox/getshouts") }}");
This is my controller function (app/controllers/ShoutboxController.php):
public function getshoutsAction() {
$shouts = $this->di->getModelsManager()
->createBuilder()
->columns(array('Shouts.*', 'Users.name'))
->from('Shouts')
->join('Users')
->orderBy('Shouts.created_at DESC')
->getQuery()
->execute()
->toArray();
$this->view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_LAYOUT);
$this->view->setVar("shouts", $shouts);
}
This is my view file (app/views/shoutbox/getshouts.twig):
{% for shout in shouts %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ shout.name }}</h3>
</div>
<div class="panel-body">
{{ shout.shouts.text }}
</div>
</div>
{% endfor %}
(The twig file extension is set as the volt engine file extension.)
This view is part of a layout file (included from the main layout):
{# Shoutbox #}
<div id="flash_sb"></div>
{% include "shoutbox/shoutform.twig" %}
<hr/>
<div id="shoutbox_messages">
{% include "shoutbox/getshouts.twig" %}
</div>
I don't know why i get an error when include this file:
Notice: Undefined variable: shouts (in app/views/shoutbox/getshouts.twig)
When i use only the controller/action (http://myurl/shoutbox/getshouts) it works. I have access to the variable "shouts".
I don't understand why this works when i use http://myurl/shoutbox/getshouts but in the layout there is no var "shouts".
If u need more information tell me please.
I hope someone can tell me whats wrong.

You may should pass the vars with using with like that:
{% include "shoutbox/getshouts.twig" with ['shouts': shouts] %}

Related

Render twig component in a loop

objective : products database + twig component rendered in a loop.
I have this setup:
A .twig product component with my component markup:
<article class="productCard "><h3 class="productCard__name">{{ product.name }}</h3></article>
A loop in my page which I want to display all the instances of the product but with the twig component template:
{% for product in products %}
<div class="col">
{{ include('components/productCard.html.twig'),{'product.name': product.name}) }}
</div>
{% if loop.index % 4 == 0 %}
</div><div class="row" >
{% endif %}
A Database with the actual list of product.
I'm not sure of the correct syntax of the loop call to achieve what I want (passing the parameters of the database to the loop to the component).
The proper syntax would be:
{% include 'components/productCard.html.twig' %}
No need for using with or passing variables. Then your other snippet should work as-is:
<article class="productCard">
<h3 class="productCard__name">{{ product.name }}</h3>
</article>

Blade - (Sage 9) probem when multiple #yield/#section

We are new to sage9 / Blade framework and we are trying to create a template logic with ACF. Everything was working well with 1 block but when we add more block the first 1 echoes 2-3 times.
Here's how we did it:
We use the default layouts.app from sage9:
web/app/themes/[theme-name]/resources/views/layouts/app.blade.php
...
<div class="vy_main uk-offcanvas-content">
<header>
#yield('dispatch_banner')
</header>
<div class="wrap container" role="document">
<div class="content">
<main class="main">
#yield('dispatch') //The one we currently working on
</main>
...
In the layout we are calling #yield('dispatch'). Inside page.blade.php we are extending the layouts and we add the dispatch section.
web/app/themes/[theme-name]/resources/views/page.blade.php
#extends('layouts.app')
#section('dispatch_banner')
#layouts('banners')
{!! App::banners() !!}
#endlayouts
#endsection
#section('dispatch')
#layouts('sections')
{!! App::sections() !!} //This call a controller where we can select the correct section to display.
#endlayouts
#endsection
Inside the controller,
web/app/themes/[theme-name]/app/Controllers/App.php we return a template to use and passing configurations/variables to use. :
public static function sections(){
...
$return .= \App\template('sections.'.$sections, $config);
}
return $return;
...
}
We create a standard block. This block include by the dispatcher :
web/app/themes/[theme-name]/resources/views/sections/std.blade.php
Inside this template, we created a new layouts "base", because all sections will have the same base structure, we extend this base inside the template and put a section content in it like so:
web/app/themes/[theme-name]/resources/views/sections/std.blade.php
#extends('layouts.base')
#section('section-content')
#if ($image)
<div class="uk-grid uk-flex-middle" data-uk-grid>
<div class="{!! $class_image !!}">
<img src="{!! $image['url'] !!}" alt="{!! $image['alt'] !!}">
</div>
<div class="{!! $class_content !!}">
#endif
<div class="{!! $content_class_content !!}">
#layouts('content')
{!! App::content() !!}
#endlayouts
</div>
#if ($image)
</div>
</div>
#endif
#endsection
And here the layout
web/app/themes/[theme-name]/resources/views/layouts/base.blade.php
<section {{ (( $section_id )?'id='.$section_id:'') }} class="{!! $class_section !!}">
#if($has_container)
<div class="uk-container uk-container-{!! $container !!}" data-uk-scrollspy="cls: uk-animation-fade;">
#yield('section-content')
</div>
#else
#yield('section-content')
#endif
</section>
As I said, everything was working fine with 1 block but as soon as we add a second block the data just keep repeating BUT only the #yield('section-content') from the base, the variables use inside the layout aren't repeating.
Here what we have in the html from :
<section {{ (( $section_id )?'id='.$section_id:'') }} class="{!! $class_section !!}">
We get :
<section class="uk-section vy_std uk-section-primary uk-section-xlarge">
<section class="uk-section vy_accordion uk-section-transparant">
<section class="uk-section vy_std uk-section-transparant">
Where is the problem with our logic and we the content from #yield('section-content') keep repeating instead of using the right data send from the controller?
If this can help I can send all the code from the controller, it's not big but to me it's wasn't where the problem is so I cut this part out.
Thank for your time!
I manage to work this out by using components/slots instead of layouts. Now I get the base from a component like so:
#component('layouts.base', $config)
/*Section code*/
#endcomponent
And everything is working again!

Link to other page in Drupal 8

In Drupal 7, I used following codes to link to other pages. I have "Service" block and inside that block , I write like this.
<?php
global $base_url;
global $base_path;
$link = $base_url . '/sites/all/themes/bootstrap_business/images';
?>
<div><img alt="" src="<?php print $link?>/customer.png" /></div>
<p> Service</p>
and I save text format with PHP.
But for now Drupal 8, we don't have Text format option "PHP" and also I don't know how to write codes to connect with other page.
Anyone help me please? Thanks.
In drupal 8 you can use hook_preprocess_HOOK() to pass variables to twig files and call your variables like
<header class="main-header">
{{ title_prefix }}
{% if page.header and logged_in %}
{{ page.header }}
{% endif %}
{% if not logged_in %}
<a href="{{ front_page }}" title="{{ 'Home'|t }}" rel="home" id="logo" class="logo">
<img src="{{ base_path }}themes/custom/mytheme/logo-login.png" alt="{{ 'Home'|t }}" />
</a>
<h2 class="login-logo">{{ site_name }}</h2>
{% endif %}
{{ title_suffix }}
</header>
Please see https://www.drupal.org/docs/8/theming/twig/functions-in-twig-templates for more details
You can also include other pages using
{# this template is located in templates/layout.html.twig #}
{% extends "layout.html.twig" %}
{# this template is located in templates/user/profile.html.twig #}
{{ include('user/profile.html.twig') }}
See: https://www.drupal.org/docs/8/theming/twig/functions-in-twig-templates
In your example, you need to specify your theme directory. Just use:
<img src="/{{ directory }}/images/xyz.jpg">
Here, {{directory }} will resolve to directory of your current theme.
For preparing links to other fields. see above mentioned drupal page

Octobercms - Getting frontend user avatar

So i'm trying to gererate a frontend user list, but i'm having trouble reaching the avatar url.
i'm able to get all user names but when i try to do the same with the profile picture the fallback is shown.
The {{ user.avatar.url }} is working on the user page when someone is signed in.
I've tried to look for the query used on the backend to get the user avatar on the preview, but i was not able to find it.
I don't know if this is relevant but i'm using https://octobercms.com/plugin/netsti-uploader for frontend users to upload their avatars. It's working since if i upload it on the frontend the backend user preview shows the right avatar
This is what i am using to get all users:
CODE:
use October\Rain\Auth\Models\User;
function onInit() {
$this['activatedUsers'] = User::whereIsActivated(true)->get();
}
MARKUP
<div>
{% for user in activatedUsers %}
<div class="card list">
{% if user.avatar %}
<img class="userimg" src="{{ user.avatar.url }}">
{% else %}
<img class="userimg" src="assets/images/user.png">
{% endif %}
<p class="name"><span class="rank-title">NAME</span><br>{{ user.name }} {{ user.surname }}</p>
{% if user.last_login %}
<p><span class="rank-title">LAST UPDATE</span><br>{{ user.last_login }}</p>
{%endif%}
</div>
{% endfor %}
All help is appreciated, thanks
try to use it like that.
use RainLab\User\Models\User;
function onInit() {
$this['activatedUsers'] = User::whereIsActivated(true)->get();
}
Markup
{% for user in activatedUsers %}
<div class="card list">
{{ user.avatar.path }}
</div>
{% endfor %}
Have a look at October\Rain\Database\Attach\File class to see available methods :
getThumb($w,$h,$options) - Generates and returns a thumbnail path
getPath() - Returns the public address to access the file
getLocalPath() - Returns a local path to this file. If the file is stored remotely,it will be downloaded to a temporary directory.
getDiskPath() - Returns the path to the file, relative to the storage disk
e.g :
{{user.avatar.getThumb(200,200, { mode : 'crop' } )}}
install "Frontend File Uploader for Model" plugin
insert {% component 'imageUploader' %} in your markup
insert
function onInit()
{
$user = Auth::getUser();
if($user){
$component = $this->addComponent(
'NetSTI\Uploader\Components\ImageUploader',
'imageUploader',
['modelClass'=>'RainLab\User\Models\User','modelKeyColumn'=>'avatar', 'deferredBinding' => false]
);
$component->bindModel('avatar', $user);
}
}
on your code section
You can query the backend user model with with 'avatar'.
use Backend\Models\User;
...
$user = User::where('id', $author_id)->with('avatar')->first();
...
<h1>{{ user.avatar.path }}</h1>

Twig loop for nested comment in a Symfony-Doctrine blog

I am trying to implement a comment section on a blog with Symfony and Doctrine, using Twig templates.
I am having some trouble trying to implement a response system for my comments. I would like to have something like this:
<div class="comment">
<p>This is comment number 1</p>
<div class="response">
<p>This is a response to comment number 1</p>
<div class="response">
<p>This is a response to response just above</p>
</div>
</div>
</div>
So I would like to have sort of a nested comment system.
I have a Comment entity with a $response property having a OneToOne Relation with another Comment entity:
/**
* #ORM\OneToOne(targetEntity="Comment")
*/
protected $response;
In my controller, I just get my comments like this:
$comments = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:Comment')
->findByArticle($article);
Now I am trying to create the HTML (Twig) but I don't know how to loop throught all comment and associated response so I can create the HTML as I wrote just above...
Anyone who can help me with that?
Thanks.
All you need is recurrence. You have a few options to choose from, one of them is using a macro.
Create twig file with your macro:
{# src/AppBundle/Resources/views/Default/_macro.html.twig #}
{% macro print_comments_recursively(comment) %}
<div class="response">
<p>{{ comment }}</p> {# implement __toString on your Comment class or print appropriate property #}
{% if comment.response is not null %}
{{ _self.print_comments_recursively(comment.response) }}
{% endif %}
</div>
{% endmacro %}
Import macro in your view and use it:
{% import 'AppBundle:Default:_macro.html.twig' as macros %}
<div class="comment">
<p>{{ comment }}</p>
{% if comment.response %}
{{ macros.print_comments_recursively(comment.response) }}
{% endif %}
</div>
Here you have similar problem, already solved, with other solutions: How to render a tree in Twig

Categories