Query a fixed number of random questions in Symfony/Doctrine - php

I'm working on website for multiple choice questions where I use symfony. The thought is to have a very big question database that categorized by topic. And then a test 1 - n chapterSelections. Each chapterSelections should contain a chapterID and a number. The number decides how many random questions it should pick from that chapter.
In the chapter entity it has a getQuestions function, and in the quetions entity, it has an getAlternatives functions.
BUT, I need a function in the chapterSelections entity that says, getRandomQuestions(int n)???
In my view, I was thinking of something like:
{% block body %}
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>Welcome</h1>
<h1>{{ test.name }}</h1>
{% for c in test.chapterSelections %}
<h1>Chapter: {{ c.getChapterID() }} - {{ c.numberOfQuestions }}</h1>
{% for q in c.randomQuestions %}
<h3>{{ q.questionText}} </h3>
{% for a in q.alternatives %}
<p> {{a.alternativeText }} </p>
{% endfor %}
{% endfor %}
{% endfor %}
</div>
{% endblock %}
I know I'm still missing the formcontrols like radiobuttons and formgroups, but this is the hardest part. I need a way to access a number of random questions from the chapterSelection entity. Any thoughts? Some info that is helpful that I have left out?
EDIT
This is how i use getQuestions in my chapter entity:
Entity/chapter.php
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\OneToMany(targetEntity="question", mappedBy="chapterID", cascade={"persist", "remove"}, orphanRemoval=true)
*/
protected $questions;
public function __construct()
{
$this->questions= new ArrayCollection();
}
public function getQuestions()
{
return $this->questions;
}
But I want this functionality in my chapterSelection, with random selection and a specified (in each chapterSelection record) number of questions.

Related

Next article section not working in craftcms anyone know what went wrong here?

one of my craft cms projects, I have articles and once click articles I can read those articles, and in that right side content I have a tab call Next article, but when clicking that nothing response
here the live site - http://ambitmagazine.co.uk/poems/ambit-poetry-competition-2018
screenshot - https://prntscr.com/o9gkph
_entry.html
{% extends "_layout" %}
{% block content %}
{% set issue = entry.issue.first() %}
{% set nextArticle = craft.entries.section('articles').after(entry.postDate).order('postDate asc').limit(1).find() %}
<div class="article section{% if entry.largeText %} article--larger-text{% endif %}">
<div class="article__inner section__inner">
{% include 'articles/_partials/article-header' with { article: entry, issue: issue } only %}
{% include "articles/_types/" ~ entry.type %}
{% if entry.relatedAuthor|length > 0 %}
{% include 'articles/_partials/article-footer' with { article: entry } only %}
{% endif %}
{% if nextArticle|length > 0 %}
<div class="next-item">
<a href="{{nextArticle[0].url}}" class="next-item__inner">
<span><strong>Next Artcile</strong></span>
<span>\</span>
<span>{{nextArticle[0].title}}</span>
</a>
</div>
{% endif %}
<div class="article__sidebar-inner"></div>
</div>
<div class="article__sidebar-outer"></div>
</div>
.after is doing a >= operation so the current article is included in the results, and is almost certainly going to be the first option.
Doing something like .after(entry.postDate|date_modify('+1 second')) will exclude the current article and should give you what you are looking for.
It may be more clear for your query to keep the time as is, but explicitly exclude the current entry by id:
{% set nextArticle = craft.entries()
.section('articles')
.after(entry.postDate)
.id(['not', entry.id])
.order('postDate asc')
.one() %}

Symfony Form Collection Theming but feed some data

Symfony 3.3
I have a form of my Voyage entity
Voyage entity has a Collection in it, named cities, collection of entity City.
And so do the form with the Collection named cities.
The user first use the form and create an instance of Voyage and add some cities to it, I managed to customise the prototype and render it via javascript when the user click "add city" button.
The form is rendered this way for the interesting part (cleaned version without html):
{% extends "#User/layout.html.twig" %}
{% form_theme form.cities '#Prototype/city.html.twig' %}
{% block content %}
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.cities) }}
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock content %}
The theme for the 'form.cities' :
{% block collection_widget %}
{% import '#Prototype/prototype.city.twig' as proto %}
{% spaceless %}
<div class="collection">
{% if prototype is defined %}
{% set attr = attr|merge({'data-prototype': proto.city(prototype)|escape }) %}
{% endif %}
<div {{ block('widget_container_attributes') }}></div>
<div id="container-cities">
{# Here I will add the cities via javascript when user add one #}
</div>
</div>
{% endspaceless %}
{% endblock collection_widget %}
The macro file used in this theme and imported as proto :
{% macro city(widget, id, name, zip) %}
{% spaceless %}
<div
class="added-city border-gray"
data-id="{{id|default('__id__')}}"
id="{{name|default('__name__')}}">
{{name|default('__city_name__')}} ({{zip|default('__zip__')}})
{{ form_errors(widget) }}
{{ form_widget(widget) }}
</div>
{% endspaceless %}
{% endmacro %}
My general problem : When the user wants to edit its instance of Voyage, it already has some cities in it. How can I render them ? How can I access the cities variable from within the theme.
My partial solution : I wanted to extract the 'container-cities' block from the theme file to the rendered html where the form is initialy rendered and where I can access the variables and do this :
{% import '#Prototype/prototype.city.twig' as proto %}
{% for city in form.cities %}
{{ proto.city(city, city.name) }}
{% endfor %}
But it give me this error :
Neither the property "name" nor one of the methods "name()", "getname()"/"isname()"/"hasname()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView".
(It doesn't fail on city.id probably because of some other field named id)
My question :
How can I access the cities within the theme and render them with my macro ?
Or
How to access to the cities items where I render the form, because the form.cities doesn't seem to be the actual City entity Collection, and get rid of that error ?
Thanks
I finally solved it, it was that simple :
I just used this in the form theme :
{% for city in form %}
{{ proto.city(city, city.vars.value.id, city.vars.value.name, city.vars.value.zip) }}
{% endfor %}

Twig loop. control class names

Im trying in Twig to set different classes depending on how may items that gets rendered. Eg, if only one, if only two, if only three etc I want to set a different class on the item. How would I do that?
<ul>
{% for item in items %}
<li>
{% include 'components/list/person.twig' with item %}
</li>
{% endfor %}
</ul>
If you want to know in advice the length of the loop, you can use the predefined loop variable that is named length:
loop.length: The number of items in the sequence
as example:
{% for user in users %}
{{ loop.index }}/{{ loop.length }} - {{ user.username }}
{% endfor %}
hope this help
I am not sure that i understood your question or not...
But if you want to use different classes on base of index of loop then you can use loop.index in loop.
Hope this will help you
<ul>
{% for item in items %}
{℅ if loop.index == 1 ℅}
// Set class here
{℅ endif %}
<li>
{% include 'components/list/person.twig' with item %}
</li>
{% endfor %}
</ul>

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

Howto get attribute from related entity in template

I want to get the id attribute from an entity using "lazy loading".
This is my controller:
public function indexAction() {
$em = $this->getDoctrine()->getManager();
$topics = $em->getRepository('BackendBundle:Topic')->findAll();
$posts = $em->getRepository('BackendBundle:Post')->findAll();
return $this->render('BackendBundle:Home:home.html.twig',
['topics' => $topics, 'posts' => $posts]
);
}
And here is my template block:
{% block article %}
{% for post in posts %}
<h3>
<a href="{{ path('backend_posts_post',
{ 'topic_id': post.topic.id, 'post_id': post.id }) }}">
{{ post.title }}
</a>
</h3>
<br>
<p>{{ post.text }}</p>
<hr>
{% endfor %}
{% endblock %}
I'm trying to get the topic id. Every post depends on a topic and should be possible to get his identifier.
Solved. I was trying to access a post whitout topic.

Categories