Drupal 8 list taxonomy terms - drupal

What is best way to retrieve Drupal 8 taxonomy terms and pass array to twig template?
Now I have:
In template.theme
function template_preprocess_page(&$variables) {
$variables['some_term'] = \Drupal::service('entity_type.manager')->getStorage("taxonomy_term")->loadTree('some_term', $parent = 0, $max_depth = NULL, $load_entities = FALSE);
}
Now in page.html.twig I can access {{ some_term }} array.
I feel that something is wrong about this. What is the best way to achieve this? I just need an array of selected taxonomy terms in page.html.twig. I want to use it to build custom HTML code.
Equivalent function in Wordpress is simple get_terms().

Your code seems to be OK.
Please check next:
Are you getting taxonomy tree array values in template_preprocess_page?
If not ($variables['some_term'] should not be empty array)
check if you are loading correct vocabulary with "...->loadTree('machine_name_of_vocabulary'..."
If yes check what twig is getting in page.html.twig You can check with: {{ dump(some_term) }}. Probably you will need to process array to get only for example list of term names.
Did you cleared Drupal cache?

Related

Testing for WordPress custom post type variables

Within the array for a custom post type named rg_story that I am defining, I have the following statement:
'chronological' => true,
Later, I have this:
if ( 'rg_story' == get_post_type()) {
As far as I know, everything is working OK. I'll know for sure once I create my templates. This is my first time with this stuff.
The problem is that I would like to test for the value of 'chronological', rather than the specific post type. I'm just not sure which function would do that.

Drupal 8 - Add machine name to block as class programmatically

I am looking for a way to add a class to a block, but not a custom class, a class from either the region name or the block machine name.
For example, with regions, this is possible:
{%
set classes = [ 'region-' ~ region|clean_class]
%}
And every divs would have the name of the region (defined in the info.yml file) as a class. I want to do the same thing with blocks. Either add the name of the region or the machine name as a class. The reason that I want a class is for CSS. It's better practice to target elements usings classes than IDs.
Does anyone know how to achieve that programmatically?
1) Twig on Drupal 8.x understands only variables and basic operations with variables. So in order to use custom variables (such as the block region) you need to pass the variables usually on a preprocess function and then use them inside Twig. Here is an example:
function MYTHEME_preprocess_block(&$variables, $hook) {
$block_id = $variables['elements']['#id'];
$block = \Drupal\block\Entity\Block::load($block_id);
// Add region as variable
$variables['region'] = $block->getRegion();
}
and then on block.html.twig file:
{%
set classes = ['region-'~region|clean_class]
%}
See the docs: https://www.drupal.org/docs/8/theming/twig/twig-best-practices-preprocess-functions-and-templates.
2) If you want to have custom block template suggestions (eg for a region) you can alter default theme suggestions using hook_theme_suggestions_alter().
function MYTHEME_theme_suggestions_block_alter(array &$suggestions, array $variables) {
if ($variables['elements']['#configuration']['region']) {
$suggestions[] = 'block__' . $variables['elements']['#configuration']['region'];
}
}
3) Notice that you are not able to use region specific Drupal block twig templates by default because this functionality removed on 8.x. See related post: https://www.drupal.org/node/2011434.
The easiest way would be to use a contributed module such as block_class
I wanted this too and came across this SO post and OPs Drupal forum post of the same question while looking for an answer. Seeing as I think this answers what we were asking I thought I'd link it here for posterity.
From the Drupal forum comments use this snippet by Jeff Burnz in your block twig template:
{%
set classes = [
'block',
'block-' ~ attributes.id,
'block-' ~ plugin_id|clean_class,
label ? 'block-label-' ~ label|clean_class,
]
%}
<div{{ attributes.addClass(classes) }}>
This gives you a few options for classes, attributes.id is the one I wanted, and if you use just that it outputs
<div id="blockID" class="block-blockId"...
I hate styling by ids so will add this to all subthemes I work on from now on. Hope this helps.

get_categories returning an empty array when it shouldn't

I'm writing a file management plugin that uses the category system to create a mock filesystem hierarchy and I'm running into some issues with some code that is responsible for recursively deleting the 'folders' (actually categories). Instead of the code returning all of the child categories of the category to be deleted, it returns an empty array. Any ideas why?
//get all child categories
$wk_child_categories = get_categories(array('child_of' => $_POST['wk_ID'], 'orderby' => 'term_group'));
echo " Got the child categories. They are:";
print_r($wk_child_categories);
One thing that I can see that might be causing the issue is the lack of the post parameter. By default if you don't have a post parameter it will fallback to the standard Wordpress "post" type. If you are using a custom post type it would return an empty array because the query is looking in the wrong spot.
There is also the possibility that the categories are empty. In the arguments for get_categories() there is a hide_empty argument that will default to not return empty categories, try setting that to 0

Pass field content as variable from block preprocessor to block tpl

I have a preprocess function:
[MYTHEMENAME]_theme_preprocess_views_view_fields__random_quote__block(&$vars)
and then a template file to render the variables:
views-view--random_quote--block.tpl.php
I can easily set a variable like so:
$vars['bam'] = 'whatever';
and display that in my template file. Now my question is, how do I pass the contents of a field to my template? Something like:
$vars['customer_name'] = 'field_customer_name';
Where 'field_customer_name' is a field in the content type. I have tried using the field api and I am getting nowhere. My view is getting that field and I can see the data in the preview of the view content
I still haven't figure out how to do this, but I ended up using a fields tpl (in this case: views-view-fields--random_quote.tpl.php) so I could format each field like so
<cite><b><?php print strip_tags($fields['field_customer_name']->content); ?></b>
Ok, I figured out how to do it!
$entity = $vars['view']->result[0]->_field_data['nid']['entity'];
$vars['customer_name'] = '$entity->field_customer_name[$entity->language][0]['value'];
Hope this helps someone

Drupal Taxonomy Block, Vocabulary Listing

I looking for the best way to implement a block that lists all terms of a certain vocabulary. Each term should link to page that lists all nodes associated with that term. Any help would be greatly appreciated. Thanks!
See here for a great tutorial to achieve exactly what you want
http://chrisshattuck.com/blog/how-add-block-menu-tags-or-other-taxonomy-terms-drupal-site
The easiest way to approach this would probably be to use Views, and simply create a new view of the type "term". Here's a quick example which assumes that you have some basic familiarity with the Views UI:
Visit Views > Add (build/views/add), give your new view a name, and select Term from the "View type" radio buttons.
On the next page, start by adding a Taxonomy: Vocabulary filter and selecting your vocabulary in the filter settings.
Add a Taxonomy: Term field and enable the Link this field to its taxonomy term page option in the field settings. You might also want to remove the field's label, since this is just a simple listing.
You probably want your display to display all terms in your vocabulary, so change the "Items to display" 0 (unlimited). By default, new views only display 10 items at a time.
Check out the Live preview below to see if it's outputting what you need.
Add a new Block display using the dropdown on the left side of the Views UI.
Give your new block a name in the "Block settings" area. This is the description that will appear on Drupal's block admin page.
Save your view and visit admin/build/block to place and configure your block.
It's worth noting that Views does indeed have some overhead, but in my experience, its flexibility and ease-of-use far outweigh the relatively minor performance hit.
If you'd like to avoid using Views, you could write a pretty simple custom module using hook_block() and adapting http://drupal.org/node/247472. If you'd like, I can edit this answer with an example module based on that.
(Posting this as another answer, since this is a different approach than my first answer.)
As I mentioned above, here's another approach involving a custom module based on the code at http://drupal.org/node/247472. You could also just drop that code into a custom block with the "PHP" input format selected, but that's generally considered to be bad practice.
Add a new folder in sites/all/modules called vocabulary_block. Customize and add the following two files:
vocabulary_block.module
<?php
/**
* #file
* Exposes a block with a simple list of terms from [vocabulary].
* Each term is linked to its respective term page.
*/
/**
* Lists terms for a specific vocabulary without descriptions.
* Each term links to the corresponding /taxonomy/term/tid listing page.
*/
function vocabulary_block_get_terms($vid) {
$items = array();
$terms = taxonomy_get_tree($vid, 0, -1, 1);
foreach($terms as $term) {
$items[]= l($term->name, "taxonomy/term/$term->tid");
}
if(count($items)) {
return theme('item_list', $items);
}
}
/**
* Implementation of hook_block().
*/
function vocabulary_block_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks[0]['info'] = t('List of [vocabulary] terms');
return $blocks;
case 'view':
if ($delta == 0) {
$vid = 43;
$block['subject'] = t('[Vocabulary]');
$block['content'] = vocabulary_block_get_terms($vid);
}
return $block;
}
}
vocabulary_block.info
name = Vocabulary Block
description = Exposes a block with a simple list of terms from [vocabulary]. Each term is linked to its respective term page.
; Core version (required)
core = 6.x
; Package name (see http://drupal.org/node/101009 for a list of names)
package = Taxonomy
; Module dependencies
dependencies[] = taxonomy
Notes
Be sure to change $vid = 43; to
reflect the ID of the vocabulary that
you'd like to load. You can find the
VID by visiting
admin/content/taxonomy and looking at
the destination of the edit
vocabulary link for your
vocabulary. The VID will be the last
fragment of that URL:
admin/content/taxonomy/edit/vocabulary/[vid].
I wouldn't normally hard-code the
$vid into the module itself. However,
setting up the necessary Drupal
variable and administration form (to
allow users to select a vocabulary
from the Drupal interface) would be
overkill for this answer.
For your own documentation purposes,
don't forget to search/replace
[vocabulary] in those two files and
use your own vocabulary's name
instead.
This method may not necessarily be more performant
than the Views method I described
earlier, especially once you start considering caching,
optimization, etc.
Since performance is a priority,
I recommend thoroughly testing a
variety of different methods on this page and
choosing whichever one is fastest for you.

Resources