Access content types fields in template - drupal

Trying to retrieve all the data from a content type (the Article content type from the core installation).
I think I have managed to get the records, but I can't access the properties.
This is what I have in the controller
$query = \Drupal::entityQuery('node');
$query->condition('type', 'Article');
$items = $query->execute();
When I try to dump the items I'm getting
array(2) {
[3]=>
string(1) "2"
[4]=>
string(1) "3"
}
There is 2 results and I have 2 articles so I think this is the good way to get theses articles. But then in my twig templates I don't know how to call the properties.
This is empty result
{% for article in items %}
<li>{{article.body}}</li>
{% endfor %}
Tried with .title and .name too.
Actually I think that what I'm getting here are just the articles ids but not the properties, so I guess I miss something again here.
Thanks for the assistance
EDIT: Also tried this, but it makes it crash
$items_ids = $query->execute();
$items = Article::loadMultiple($items_ids);

Ended up by find out what was wrong with that, I needed to use Node for the load in controller and then .field.value in templates to render.
Controller
$query = \Drupal::entityQuery('node');
$query->condition('type', 'Article');
$items_ids = $query->execute();
$items = Node::loadMultiple($items_ids);
Twig
{% for article in items %}
<li>{{article.title.value}}</li>
{% endfor %}

Related

Search all posts by an author in Wordpress/Timber

I'm trying to display all posts by a given author on the search results page using Timber. I've found that this works if I manually type it in:
/s?&author_name={username}
But I need to create these links dynamically in a loop, and unfortunately Timber's User object doesn't have access to a User's username. Going by ID also doesn't work (/s?&author={author_id}).
What's the solution here?
I would suggest you make a function available in Twig which allows you to pass in the author id and return the author archive link via get_author_posts_url() or access the WP user class.
See documentation on how to achieve this:
https://timber.github.io/docs/guides/functions/#make-functions-available-in-twig
php
add_filter( 'timber/twig', 'add_to_twig_author_link' );
function add_to_twig_author_link( $twig ) {
$twig->addFunction( new Timber\Twig_Function( 'get_author_posts_url', 'get_author_posts_url' ) );
return $twig;
};
twig
{{ get_author_posts_url( author_id ) }}
If you need to access author archive via link, you can do it by Timber\Post object
{% for post in posts %}
{{ post.author.name }}
{% endfor %}
But as I understood, your problem is to pass user login into twig templates. This way you can add to a global context all of your users.
search.php
$ctx = Timber::context();
$ctx['users'] = get_users(); // it will return array of WP_User objects
Timber::render( 'search.twig', $ctx );
search.twig
{% for user in users %}
{{ user.user_login }} // this will show user login
{% endfor %}

Get custom post type label instead of name - WordPress + Timber

I created 3 custom post types in WordPress : dissertation, subject-imposed, subject-free
In each custom post type the user is allowed to create only ONE post.
I created a menu composed with those three custom post types which allow to switch from post to another from the same user.
But I got a problem. The menu item display the name of the post type and not the label.
I got : DISSERTATION / SUBJECT-IMPOSED / SUBJECT FREE
And I would like the label (labels are in french) : MEMOIRE / SUJET IMPOSE / SUJET LIBRE
How can I get the label instead ? Thank you in advance.
In single.php :
$post_queried = get_queried_object();
$context['post_type_current'] = get_post_type_object(get_post_type($post_queried));
$get_post_current_user = get_posts( array(
'author' => $current_user->ID,
'post_type' => array('dissertation', 'subject-imposed', 'subject-free'),
));
$context['list_posts_current_user'] = $get_post_current_user;
In single.twig :
<ul class="menu-secondary__list">
{% for item in list_posts_current_user %}
{% set active = (post_type_current.name == item.post_type) ? 'active' : '' %}
<li class="menu-secondary__item">{{ item.post_type }}</li>
{% endfor %}
</ul>
Two steps to fix this one, first ...
Convert into an array of Timber\Posts
$get_post_current_user is an array of WP_Posts we need to convert these to Timber\Posts in order to interact with Timber's methods. Many ways to do this, but the easiest ...
{% for item in Post(list_posts_current_user) %}
Access the type method:
Now you can use the Post::type() method in your Twig template and access the labels:
{{ item.type.labels.name }}
The {{ item.type }} property will give you everything from here:
https://developer.wordpress.org/reference/functions/get_post_type_object/

Translate doctrine query from default Symfony 3 translation file

In my AdRepository i'm getting an list of list conditions of the product. These have names like 'NEW', 'GOOD'... I use the following simple query to get the list:
$query = $this->createQueryBuilder('ad')
->select('ad.condition as name')
->getQuery()
->getResult();
Now I want to translate the name field from the standard Symfony translation files, so not from the database. What is the best way to do this?
I'm not sure if thats the best way to do it, but you could (I assume you're using Twig) use an if and give the translation variable depending on the condition name.
{% if condition.name === "GOOD" %}
{{ 'condition.good'|trans }}
{% else %}
...
{% endif %}
Of course thats a lot of ifs, if you have many conditions.

Using doctrine database object in a template

I am new to Symfony and am finally beginning to understand how to query a database using a Doctrine. However, I am lost as far understanding how to use the database object content in a Twig template.
Lets say my database object contains product Id's, names, prices, for 50 different products. After I am done querying the database in the controller, I do the following, to pass the database object into the Twig template:
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
$dataObject; // contains query results
return $this->render('GreatBundle:Default:search.html.twig', array('word' => $word));
}
This is where I am stuck. Now I have a Twig template, I would like to pass the DB object from the controller and then print out the database data in my Twig template.
I appreciate any suggestions as to how I can accomplish this.
Many thanks in advance!
I'll respond with an example (more easier for me to explain)
You want to search something with a slug (the var $word in your example). Let's say you want to find a article with that.
So your controller :
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
// Search the list of articles with the slug "$word" in your model
$articleRepository = $this->getDoctrine()->getRepositoy('GreatBundle:Article');
$dataObject = $articleRepository->findBySlug($word);
// So the result is in $dataObject and to print the result in your twig, your pass the var in your template
return $this->render('GreatBundle:Default:search.html.twig', array('result' => $dataObject));
}
The twig template 'GreatBundle:Default:search.html.twig'
{% for item in result %}
{{ item.title }} : {{ item.content }}
{% endfor %}
Just look the second example in the Symfony2 Book (Sf2 Book - templating), you have to use the function "for" to parse your object (like an array in php !)
Example in your twig template :
{% for item in word %}
{{ item.id }} - {{ item.name }} - {{ item.description }}{# etc... #}<br>
{% else %}
<h2>Aoutch ! No data !</h2>
{% endfor %}
Ah, and it's not the good var in your render method (but it's was for your example !)
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
$dataObject; // contains query results
return $this->render('GreatBundle:Default:search.html.twig', array('word' => $dataObject));
}

How to get the current page name in Silex

I'm wondering how to get the current page name, basically 'just' the last parameter in the route (i.e. /news or /about). I'm doing this because I want to be able to have the current page in the navigation highlighted.
Ideally, I'd like to store the current page name in a global variable so that in Twig I can just compare the current page name against the link and add a class accordingly.
I can't figure out how to add the current page name to a global variable though. I've tried using something like this:
$app['twig']->addGlobal('current_page_name', $app['request']->getRequestUri());
at the top of my app.php file, but an 'outside of request scope' error. But I wouldn't like to have to include this in every route.
What's the best way to do this?
If you put it into an app-level before middleware like this, that'll work:
$app->before(function (Request $request) use ($app) {
$app['twig']->addGlobal('current_page_name', $request->getRequestUri());
});
The "page name" part of your question is unclear, are you looking for the current route's name? You can access that via $request->get("_route") even in the before middleware, as it gets called when routing is already done.
You could also generate navigation list directly in stand alone nav twig template. And then import it in to the main template. Then you would only have to get silex to pass to the view the current page identifier. Simplest way... for example from Silex you would have to pass in the "path" variable to your view. Probably it would more convenient to to fetch nav_list from database and pass it in to twig template as global array variable instead. However this example is the simplest you could get to do what you intend.
nav.twig
{% set nav_list = [
["./", "home"],
["./contact", "contact"],
["./about", "about us"]
{# ... #}
] %}
{% set link_active = path|default("") %}
{% for link in nav_list %}
<li><a href="{{ link[0] }}" class="{% if link[0] == link_active %} activeClass {% endif %}" >{{ link[1] }}</a></li>
{% endfor %}
app.php
//...
$app->match('/about', function (Request $request) use ($app) {
return $app['twig']->render('about.twig', array(
'path' => './'.end(explode('/', $request->getRequestUri()))
));
});
//...

Resources