title: Memcache Slowing Down Drupal

text:
# Question
Title: Memcache Slowing Down Drupal
Running seige (load tester) without memcache enabled I see stats similar to this:

```
Transactions:                    560 hits
Availability:                 100.00 %
Elapsed time:                  59.42 secs
Data transferred:               6.25 MB
Response time:                  1.56 secs
Transaction rate:               9.42 trans/sec
Throughput:                     0.11 MB/sec
Concurrency:                   14.71
Successful transactions:         543
Failed transactions:               0
Longest transaction:           10.57
Shortest transaction:           0.00

```

Notice that I'm getting about 560 transactions in 60 seconds, 9.42 trans/sec.

When I enable memcache (using the PECL memcache module) and re-run siege I see much worse performance:

```
Transactions:                    133 hits
Availability:                 100.00 %
Elapsed time:                  59.94 secs
Data transferred:               1.34 MB
Response time:                  6.43 secs
Transaction rate:               2.22 trans/sec
Throughput:                     0.02 MB/sec
Concurrency:                   14.27
Successful transactions:         129
Failed transactions:               0
Longest transaction:           12.22
Shortest transaction:           0.00

```

Notice that I've decreased my performance significantly. I was only able to process 133 hits in 60 seconds and the throughput is 2.22 transactions per second.

I have memcache setup on its own dedicated system with 4GB of RAM and here are the parameters: memcached -d -p 11211 -u memcached -m 2560 -c 2048 -P /var/run/memcached/memcached.pid

I noticed that if I go to /admin/reports/memcache I get the following PHP errors:

```
Notice: Undefined variable: stats in dmemcache_stats() (line 244 of /www/sites/all/modules/memcache/dmemcache.inc).
Warning: Invalid argument supplied for foreach() in dmemcache_stats() (line 244 of /www/sites/all/modules/memcache/dmemcache.inc).
Notice: Undefined variable: stats in dmemcache_stats() (line 263 of /www/sites/all/modules/memcache/dmemcache.inc).
There are no statistics being reported for this bin.

```

I'm not sure if that's related to the issue or not?

This is what I have in settings.php:

```
/**************************************************
 * MEMCACHE
 **************************************************/
// the path to the core cache file
include_once('./includes/cache.inc');
// the path to the memcache cache file
include_once('./sites/all/modules/memcache/memcache.inc');

$conf['cache_default_class'] = 'MemCacheDrupal';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
$conf['memcache_servers'] = array(
        'memcache.domain.local:11211' => 'cluster'
);

$conf['memcache_bins'] = array(
        'bin1' => 'cluster'
);

$conf['memcache_key_prefix'] = 's-drupal';

```

Why is memcache slowing down my site instead of speeding it up? Would switching to PECL memcached help?

# Answer
> 2 votes
The errors on the stats page are due to an unrelated issue with memcache reporting. I think the problem you have is with the conf setup. I believe it should be like this for a default set up where all tables are mapped to the same bin:

```
$conf['cache_default_class'] = 'MemCacheDrupal';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
$conf['memcache_servers'] = array(
    'memcache.domain.local:11211' => 'default'
);

$conf['memcache_key_prefix'] = 's-drupal';

```

If that doesn't do the trick you can explicitly code the mappings for each table:

```
$conf['memcache_bins'] = array(
  'cache' => 'default',
  'cache_filter' => 'default',
  'cache_menu' => 'default'
);

```

etc.

# Answer
> 1 votes
```
// Memcache settings
$settings['cache']['default'] = 'cache.backend.memcache';

$settings['memcache']['key_prefix'] = 'nfb_drupal_';
$settings['memcache']['memcached_servers'] =  [
        '127.0.0.1:11211' => 'default',
];
$settings['memcache']['bins'] = [
        'default' => 'default', // You can omit this config, because the "default" cluster will be used automatically for all cache bins which have no memcached cluster specified.
];

```

are the only settings I added to settings.local.php related to cache and our site is blazin'. We have sub-second full page render and download times on 100% drupal site. There are no static pages here. Clearing your browser cache doesn't seem to slow things down noticably.

**IMPORTANT:**

1. Always enable module first, then add configuration. Otherwise site will crash.
2. Always remove configuration first, then disable module Otherwise site will crash.

Use firefox and go to www.nfb.org to see memcached in action.

For best results use firefox (best) or internet exploder. Chrome is slow.

An important note is that **once you log in to Drupal, you're not using caching**. Because of the nature of the drupal back end, by design, it doesn't get cached no matter what you do.

This is using the standard memcached module, not memcached\_storage, which requires different configuration parameters.

Make sure you use a key prefix if you use memcached for other things besides drupal. For multiple drupal sites use a different key prefix for each site.

This has the effect of partitioning the cache entries and can improve things if you use memcached for multiple applications and/or drupal sites.

**This should be obvious, but needs to be said because I don't believe in taking things for granted:** *Make sure you install memcached on your web server, enable the drupal module, and make sure you can connect to the port you specify in your configuration.*

Go to memcached.org for documentation on how to do this.

I don't want to get replies like "This didn't work!" or "Now it's even slower!!!" because you didn't install memcached on your web server and configure it, turn the drupal module on, configure your firewall etc...

**If you can't do this(make sure the telnet client is installed):**

```
$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get foo
VALUE foo 0 2
hi
END
stats
STAT pid 8861
(etc)

```

**Your memcached setup is non-existent or somehow FUBAR.**

Once installed, and site is browsed to build up the cache, if you telnet to memcached and type something like:

```
stats cachedump 3 0

```

You'll get something like:

```
stats cachedump 3 0
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-entity [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-config [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-default [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-bootstrap [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-menu [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-data [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-discovery [14 b; 1579275863 s]
ITEM nfb_civicrm_/56477c85410897a96440113a448cc752/ [13 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-page [14 b; 1579275863 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/_562bb77fd2fe36b6298b8fbaf64e96d0 [6 b; 1579284982 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/_874badf76040ef2c6208412eaade4b47 [6 b; 1579284982 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/_aa342d4db4e895a354916ddc04f9f729 [6 b; 1579285468 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-advagg [14 b; 1579275863 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/civicrm_event_2d2_2c3_2c4_2c5_2c6_2c7_2c8 [6 b; 1579285849 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-ultimate_cron_logger [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-signal [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-toolbar [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-discovery_migration [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-migrate [14 b; 1579275863 s]
ITEM nfb_drupal_%3Amemcache_bin_timestamps%3A-file_mdm [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-entity [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-config [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-discovery [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-bootstrap [14 b; 1579275863 s]
ITEM nfb_civicrm_/e3ecf972619e5cbbb8bf1575d46fae1a/ [13 b; 1579275863 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/_711c488064b6de06070ddaddf44ee52b [6 b; 1579285613 s]
ITEM nfb_civicrm_/settings/5e21d65b50b71/defaults_contact [6 b; 1579283816 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/_f1e6cd34c98d835e6603900708b8c94f [6 b; 1579284487 s]
ITEM nfb_civicrm_/default/5e21d65b4e694/_0903da7f623c9a608a28bb3e3b05012e [6 b; 1579284487 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-toolbar [12 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-page [12 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-migrate [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-dynamic_page_cache [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-content [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-render [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-menu [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-discovery_migration [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-data [14 b; 1579275863 s]
ITEM actionfund_drupal_%3Amemcache_bin_timestamps%3A-default [14 b; 1579275863 s]

```

That's how you know it's working.

---
Tags: performance, caching
---


title: How to print the latest facebook posts?

text:
# Question
Title: How to print the latest facebook posts?
I would like to show the two latest facebook-posts on my Drupal page. I found these two modules: https://www.drupal.org/project/facebook\_pull and https://github.com/mysequel/Drupal-8-Facebook-Feed-Module. Unfortunately there is no working Drupal 8 compatibility yet. The first one is in Dev Status and I can't even get it to work. The second generates an error when activating.

What is the Drupal 8 way to import this data from Facebook?

# Answer
> 0 votes
While the migration of existing modules is done you can use the solution proposed at https://www.powr.io/tutorials/how-to-add-facebook-feed-module-to-your-drupal-site. There is a free version https://www.powr.io/plugins/facebook-feed/standalone?id=9305465& that you can configure for the moment.

Here is the description of it (= quote from the linked page):

> Facebook Feed is free, mobile responsive, and easy to edit; no code needed! Simply embed Facebook Feed to any page, post, sidebar, or footer. Next, customize it right on the live site. Facebook Feed is free and easy-to-use in no time.

# Answer
> 0 votes
I suggest Social Wall module that work with Twitter, Facebook and Instagram and provide base functionality to integrate it with other social networks

> This module provides a block that displays feeds from any social network. New social networks and the way they are displayed can be implemented in your module. Available configurations :
>
> Which social networks to display Social networks order Any configuration you set in your custom social network (number of posts to show, ...) New permission Administer social networks

---
Tags: 8, social-network
---


# Question
Title: Should I define all my variables in the module.settings.yml file?
With the new Configuration Management System we can create a module.settings.yml file with all the variables that we will use in our module.

Now just to made a test I delete all the content inside my module.settings.yml file (leaving the file empty), I reinstalled the module and it works, so I deleted my module.settings.yml file and I reinstalled my module one more time and, the module works, I can set the variables (the configuration is created) and I can use the variables, even I can export the configuration.

In this scenario I see that you don't need to define your variables even the file is not needed (or maybe I missing something). So, should I define all my variables in the module.settings.yml file?

# Answer
> 3 votes
Talking of the configuration file in config/install, its purpose is setting the default values for the configuration used from the module.

Deleting its content could probably not make much difference if the default values are `FALSE`, `NULL`, or an empty string. In the other cases, its content would make a difference.

# Answer
> 0 votes
I guess you don't need it if your variables are optional. If you have required variables or if you just want to provide default variables put it in a module.settings.yml file within a config/install folder.

# Answer
> 0 votes
# Drupal Docs update

In Drupal Docs there is an explanation of how to configuration, Structure, get and edit `module_name.settings` file in `config/install` subdirectory of your module directory as here: Defining and using your own configuration in Drupal 8 as follow:

The simplest way to use this is the `Drupal::config()` static method:

```
$config = \Drupal::config('example.settings');
// Will print 'Hello'.
print $config->get('message');
// Will print 'en'.
print $config->get('langcode');

```

If you want to edit a configuration and update it with a new value you can use the `\Drupal::service('config.factory')->getEditable()` method:

```
$config = \Drupal::service('config.factory')->getEditable('example.settings');

// Set and save new message value.
$config->set('message', 'Hi')->save();

// Now will print 'Hi'.
print $config->get('message');

```

To know more please read it. The best part it explains how to make your settings translatable using `langcode` key and including two more files `example.schema.yml` and `example.config_translation.yml`.

---
Tags: 8, configuration
---


# Question
Title: Need to add a JS file into <head> using a custom module with custom twig template
I have created a custom module and created a config page which we need to input the url on that page.

Created a twig template within my custom module:

```
<script src={{ js_file_url }}>test</script>

```

In my .module file

```
<?php

/**
 * @file
 * Add the url to the header section.
 */

/**
 * Implments hook_page_attachments_alter().
 */
function custom_module_page_attachments_alter(array &$attachments) {

  $js_file_url = \Drupal::config(' custom_module.settings')->get('url');

  $renderable = [
    '#theme' => 'my_template',
    '#test_var' => 'test variable',
  ];

$attachments['#attached']['html_head'][] = [
    [
      '#theme'  => 'my_template',
      '#js_file_url'   => $js_file_url,
    ],
  ];

}

function  custom_module_theme($existing, $type, $theme, $path) {
  return [
    'my_template' => [
      'variables' => ['js_file_url' => NULL],
    ],
  ];
}

```

My output:

```
<><script src=http://google.com>test</script></>

```

Expected Output is

```
<script src=http://google.com>test</script>

```

How to get rid of empty tags =\> \<\>,

By default $attachments\['#attached'\]\['html\_head'\]\[\] is adding the '#tag' even if i dont declare it.

Can someone help me, please.

# Answer
You can attach custom tags to any render array from where it bubbles up into the HTML head. In the following sample I'm adding structured data when a certain block is viewed. `$value` then contains what's being printed between the opening and closing script tag.

```
/**
 * Implements hook_block_view_BASE_BLOCK_ID_alter().
 */
function MYMODULE_block_view_system_breadcrumb_block_alter(array &$build, BlockPluginInterface $block) {

  // Get JSON-LD.
  if ($json_ld = \Drupal::service('easy_breadcrumb.structured_data_json_ld')
    ->value()) {

    // Prepare script tag.
    $structured_data = [
      '#tag' => 'script',
      '#attributes' => ['type' => 'application/ld+json'],
      '#value' => $json_ld,
    ];

    // Add script tag.
    $build['#attached']['html_head'][] = [
      $structured_data,
      'easy_breadcrumb_structured_data_json_ld',
    ];
  }
}

```

I hope you get the idea how this can easily be adjusted to get your custom snippet into the head. You can keep your logic in `hook_page_attachments_alter` but then let it look more like in the following snippet. Maybe you don't even need any `#value` at all.

```
/**
 * Implements hook_page_attachments_alter().
 */
function MYMODULE_page_attachments_alter(array &$attachments) {

  if ($js_file_url = \Drupal::config('MYMODULE.settings')->get('url')) {

    // Prepare script tag.
    $my_script = [
      '#tag' => 'script',
      '#attributes' => ['src' => $js_file_url],
      '#value' => 'test',
    ];

    // Add script tag.
    $attachments['#attached']['html_head'][] = [
      $my_script,
      'MYMODULE_my_script',
    ];
  }
}

```
> 1 votes

---
Tags: theming, hooks
---


title: Override image template for field

text:
# Question
Title: Override image template for field
Can I modify core/image twig template only for specified entity.field?

I want to modify img tag output only for commerce\_product.images custom field but there is only 1 suggestion `themes/bootstrap/templates/system/image.html.twig` which override all image uses.

```
<div class="field--item">
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'image_formatter' -->
<!-- BEGIN OUTPUT from 'core/modules/image/templates/image-formatter.html.twig' -->

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'image' -->

<!-- BEGIN OUTPUT from 'themes/bootstrap/templates/system/image.html.twig' -->

<img src="zz.jpg" alt="alttext" typeof="foaf:Image" class="img-responsive" height="150" width="150">

<!-- END OUTPUT from 'themes/bootstrap/templates/system/image.html.twig' -->
<!-- END OUTPUT from 'core/modules/image/templates/image-formatter.html.twig' -->

</div>

```

EDIT1: if i'm implement hook\_theme\_suggestions\_HOOK\_alterm there is no entity or field info:

```
function mytheme_theme_suggestions_image_alter(array &$suggestions, array $variables) {
  $entity = $variables['item']->getEntity(); //ERROR
}

```

# Answer
> 0 votes
It's possible but very difficult to do.

You would have to alter to output of the image formatter to inject a theme suggestion on the `image_formatter` template (or create your own image formatter).

Then you would need to inject the suggestion from the formatter to the image theme function (could be done in a preprocess).

The issue is that altering the output would probably be something you would handle in each unique case, so you would basically need to create your own image formatter.

It's not a lot of work, but a bit tricky.

TL:DR; Yes it's possible but you don't want to do that.

# Answer
> 0 votes
As Berdir says, you can do this easily if you use an image style specific to your field/need.

```
function THEMENAME_theme_suggestions_image_alter(array &$suggestions, array $variables) {
  $suggestions[] = 'image__' . $variables['style_name'];
}

```

---
Tags: theming, commerce, 8
---


# Question
Title: How do I troubleshoot PrivateTempStore for session data?
I am updated one of my Drupal 7 modules for Drupal 8 and I discovered that I need to use PrivateTempStore rather than $\_SESSION variables. I followed some great examples online, but it does not seem to be storing the data correctly. I am even checking the database directly afterwards, but it does not have the correct data. I've done some debugging at the point where I am storing the data to see what is set, and it says it is set with the value I expect. However, the database does not show this value and reloading the page and outputting the value retrieved does not show what I expect. What are the method people use to debug these issues.

Currently running Drupal 8.8.1 on PHP 7.3.

# Answer
> I am updated one of my Drupal 7 modules for Drupal 8 and I discovered that I need to use PrivateTempStore rather than $\_SESSION variables.

The Drupal 8 replacement for `$_SESSION` is not PrivateTempStore, it is the session object in the request:

**Drupal 7:**

```
function mymodule_session_counter_increment() {
  if (!isset($_SESSION['mymodule_count'])) {
    $_SESSION['mymodule_count'] = 0;
  }

  return $_SESSION['mymodule_count']++;
}

```

**Drupal 8:**

```
class MymoduleSessionCounter {
  function increment(Request $request) {
    $session = $request->getSession();
    $value = $session->get('mymodule_count', 0);
    $session->set('mymodule_count', $value + 1);

    return $value;
  }
}

```

See the change record: https://www.drupal.org/node/2380327

For more info see this topic: How do I store the values submitted in a form in the session?
> 2 votes

---
Tags: sessions
---


# Question
Title: Is there a Grouped Product listing type in Drupal Commerce
I have a Magento site I would really like to migrate to Drupal Commerce. The one must-have feature is Grouped Product. A grouped product will have a base product from which the product listing will use the photos, description, etc. The related products will provide their titles, prices, etc. to the product listing. See the photo for an example.

Can this be done with Drupal Commerce?

Thanks for your time and help!

# Answer
Drupal Commerce does differentiate between products and product variations same as other systems, but the feature you're looking for hasn't been ported to Drupal 8 yet. It's easy enough to create a table with individual Add to Cart buttons for the variations in Drupal 8, but to have a single Add to Cart button for all variations on a product page, you'd need this module upgraded for Drupal 8:

https://www.drupal.org/project/commerce\_add\_to\_cart\_extras
> 1 votes

# Answer
It sounds like from the question, and looks like from the photo example that you would like to sell multiple products as a "Set" (see photo) with one sku (see photo). If that's not the case, maybe add more detail regarding your use case.

> The "best" option out of the box:

There is not currently a **stable** bundle module for Drupal Commerce 2. Commerce\_product\_bundle for Drupal 8 accomplishes the function you want, but the module is not stable, nor under active development or maintenance. I would only install it for testing on a sandbox site, and would be hesitant using it in production in it's current state. commerce\_product\_set on github was developed because commerce\_product\_bundles was not production ready/ maintained.

So unfortunately, nothing is ready for this out of the box, so whatever choice you make will likely require some development.

Commerce\_bundle for Drupal 7 is actually very dependable as a **dev** module, but I'm guessing you don't want to start with Drupal 7 at this point.

> Another suggestion:

There is also product add on (pado) module for Drupal 8, but the use case is a little different than your example.

Sorry there is not better news.
> 0 votes

---
Tags: commerce
---


title: How to place multi view in one page?

text:
# Question
Title: How to place multi view in one page?
I have two content types and I wanna place two content views in one page with different display modes. How to solve it?

# Answer
> 0 votes
You can add Attachment to a view.

And Page: filter -\> contenttype 1 Attachment: filter -\> contenttype2

---
Tags: views, theming
---


# Question
Title: What is the proper way to show a visitor an error?
I'm using a custom submit handler for a Webform, which POSTs important form data to another API. That part works, but on occasion there may be random network errors that prevent a successful submission, such as if the REST endpoint happened to be down at that particular moment (or whatever).

In those cases, I don't want the user to think their form successfully submitted when it didn't. How can I override the confirmation page with a custom error page? I tried `drupal_set_message()`, but it doesn't show up anywhere on the confirmation page that I could see.

Ideally, I would also be able to get back the event ID generated by `watchdog` logging so that the user, if they contact us by phone or email upon seeing the error, would be able to provide more information that can help us debug it.

So in summary, in a perfect world, a failed submission would result in:

1. The form submission ($form\_state) being logged into watchdog or another log
2. Watchdog returns the associated event ID
3. The user sees a custom error page describing the error, with the event ID as an error code to help in debugging.

I can hack something together with `die()` and a hash of the form data as an error code, but is there a better, proper Drupal way?

Relevant code so far:

```
 try {
    $apiResponse = drupal_http_request($apiEndPoint, [
      'headers' => ['Content-Type' => 'application/json'],
      'method' => 'POST',
      'data' => drupal_json_encode($formData),
      'timeout' => 5 // Timeout in seconds.
    ]);

    // I'm not okay :(
    if ($apiResponse->code != "200") {
      throw new Exception ($apiResponse->data, $apiResponse->code);
    }
  } catch (Throwable $e) {
    watchdog('tfm_custom_form_handlers', "A custom form handler failed: (@code) @message.", [
      '@code' => $e->getCode(),
      '@message' => $e->getMessage(),
    ], WATCHDOG_ERROR);
  }

```

Thanks for the help!

# Answer
> 1 votes
Have your `POST` code inside a validate function, that runs last, after all other validation has passed.

Ex: `$form['submit']['#validate'][] = 'mymodule_post_to_api';`

and use `form_set_error('form', 'Failed to connect to API, try again later');` inside your `catch`.

For POST's errors, don't wait for someone to report. Programmatically make Drupal send yourself or whomever maintains the code, an e-mail with the form fields & error details.

See How to programmatically send an email?

---
Tags: 7, hooks, webforms, redirection
---


# Question
Title: Cache a block by a custom entity rendered within
I struggle with getting a custom block cached correctly:

* we have a custom entity "Politician"
* For that entity we have several routes where we want to render a "politician header" with some basic information about the politician
* the politician header is a custom template which is rendered in a custom block
* the problem is: when caching is activated the block always shows the politician data from the first politician which was rendered.

Here is the code for the block plugin - to keep it simple I do not copy the method getPoliticianFromUrl() here:

```
/**
 * Provides a block with the profile header for a politician. We do not render
 * it on the public edit form path
 *
 * @Block(
 *   id = "aw_frontend_politician_header",
 *   admin_label = @Translation("Politician profile header"),
 *   category = "Abgeordnetenwatch"
 * )
 */
class PoliticianProfileHeader extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {
    $politician = $this->getPoliticianFromUrl();
    if ($politician == NULL) {
      return [];
    }

    return array(
      '#theme' => 'politician_header',
      '#politician' => $politician,
      '#cache' => [
        'keys' => ['politician', $politician->id()]
      ]
    );
  }

  public function getCacheContexts() {
    $politician = $this->getPoliticianFromUrl();
    if ($politician != NULL) {
      return Cache::mergeContexts(parent::getCacheContexts(), $politician->getCacheContexts());
    }
    return parent::getCacheContexts();
  }

  public function getCacheTags() {
    $politician = $this->getPoliticianFromUrl();
    if ($politician != NULL) {
      return Cache::mergeTags(parent::getCacheTags(), $politician->getCacheTags());
    }
    return parent::getCacheTags();
  }
}

```

Then I render the politician header - again I just put in interesting parts:

```
function template_preprocess_politician_header(&$variables) {
  /** @var \Drupal\pw_basic\Entity\Politician $politician */
  $politician = $variables['politician'];
  /** @var \Drupal\Core\Render\Renderer $renderer */
  $renderer = \Drupal::service('renderer');
  $renderer->addCacheableDependency($variables, $politician);
  $variables["#cache"]["contexts"][] = 'user.roles';
  $variables['#cache']['keys'] = ['politician_header', $politician->id()];
}

```

I thought when I define cache keys this ensures that different versions of the render array are cached. This does not happen - not for the custom politician header template (for which I do not find any cached data in cache\_render tanle - is this just cached with Twig caching?) and not for the block.

My idea was to create a custom cache context based on my Politician entity but as far as I understand cache contexts they depend on more global circumstances such as the active theme, the current user and things like that. I hoped the Entity API would generate such a context in a magical way so I tried $politician-\>getCacheContexts() but nothing.

What do I miss?

# Answer
By any reason I do not really get the block rendering to respect my cache keys set wherever. It only respects set cache contexts so I create a custom cache context:

**In pw\_basic.services.yml** (pw\_basic is the name ofthe module)

```
  cache_context.politician:
    class: Drupal\pw_basic\Cache\PoliticianCacheContext
    arguments: ['@current_route_match']
    tags:
      - { name: cache.context }

```

**The politician cache context class:**

```
class PoliticianCacheContext implements CacheContextInterface {

  use GetPoliticianFromUrlTrait;

  /**
   * @var \Drupal\pw_basic\Entity\Politician
   */
  protected $politician;

  public function __construct(CurrentRouteMatch $current_route_match) {
    $this->politician = $this->getPoliticianFromUrl();
  }

  /**
   * {@inheritdoc}
   */
  public static function getLabel() {
    return t('Politician');
  }

  /**
   * {@inheritdoc}
   */
  public function getContext() {
    $cache_context = '';
    if ($this->politician !== NULL) {
      $cache_context = $this->politician->id();
    }
    return $cache_context;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheableMetadata() {
    return new CacheableMetadata();
  }
}

```

Then I cleared the block plugin class from any cache logic and just added the following in template\_preprocess\_politician\_header(), the preprocess function of the template rendered within the block:

```
$variables["#cache"]["contexts"][] = 'politician';

```

What I do not really like is the service character of the cache context classes. Why is it only possible to set the context in such a global way? Do I miss somethin? I need to use this global workaround and check for the politician from URL which makes this context not as flexible as I want it to be. Is there a way to give a variable to a cache context directly when defining it in a render array?
> 1 votes

---
Tags: 8, blocks, caching
---


# Question
Title: adding new validation method using HookEventDispatcherInterface::FORM_ALTER event
I'm trying to add a new validation method for 'user\_login\_form' using HookEventDispatcher module and events:

```
class MyFormEventsSubscriber implements EventSubscriberInterface {

public static function getSubscribedEvents() {
      return [ HookEventDispatcherInterface::FORM_ALTER => 'alterForm'];
  }

public function alterForm(FormAlterEvent $event) {

    if ($event->getFormId() == 'user_login_form') {

      $form = &$event->getForm();
      $form['#validate'][] = 'my_api_authentication';

    }
  }

  function my_api_authentication(&$form, FormStateInterface $form_state) {
    $test = 1;
  }
}

```

But i never reach *my\_api\_authentication* function. How i need to refer it and where should be suposed to be implemented ?

May be i should manage with *hook\_form\_FORM\_ID\_alter* instead *FORM\_ALTER HookEventDispatcherInterface* event ?

# Answer
> 0 votes
You can do it that way too: in Oriented object way don't call the method like `'my_api_authentication'` it should be `[$this, 'myApiAuthentication']` and also the method should be Camel Cases, try with the following:

```
class MyFormEventsSubscriber implements EventSubscriberInterface {

  public static function getSubscribedEvents() {
    return [HookEventDispatcherInterface::FORM_ALTER => 'alterForm'];
  }

  public function alterForm(FormAlterEvent $event) {
    if ($event->getFormId() == 'user_login_form') {
      $form = &$event->getForm();
      $form['#validate'][] = [$this, 'myApiAuthentication'];
    }
  }
  function myApiAuthentication(&$form, FormStateInterface $form_state) {
    // Your code validation here.
  }

}

```

---
Tags: 8, hooks, event-subscribers
---


# Question
Title: How do I generate options based on Ajax callback
In Drupal 8, I want to generate options of second select-box based on Ajax call of first select-box. The result generate a third new select box but I don't need to generate a new one. I want to replace the options of the second select-box. Please see my codes below:

```
public function buildForm(array $form, FormStateInterface $form_state) {
$form['example_select'] = [
  '#type' => 'select',
  '#title' => $this->t('Select element'),
  'wrapper' => 'first',
  '#options' => [
    '1' => $this->t('One'),
    '2' => $this->t('Two'),
    '3' => $this->t('Three'),
    '4' => $this->t('From New York to Ger-ma-ny!'),
  ],
  '#ajax' => [
    'callback' => '::myAjaxCallback',
    'disable-refocus' => FALSE,
    'event' => 'change',
    'wrapper' => 'edit-output',
    'progress' => [
      'type' => 'throbber',
      'message' => $this->t('Verifying entry...'),
    ],
  ]
];

$form['example_select2'] = [
  '#type' => 'select',
  '#title' => $this->t('Select element'),
  '#prefix' => '<div id="first">',
  '#suffix' => '</div>',
  '#options' => [
  ],
  '#ajax' => [
    'callback' => '::myAjaxCallback2',
    'disable-refocus' => FALSE,
    'event' => 'change',
    'wrapper' => 'edit-output',
    'progress' => [
      'type' => 'throbber',
      'message' => $this->t('Verifying entry...'),
    ],
  ]
];
return $form;
}

public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
  if ($selectedValue = $form_state->getValue('example_select')) {
    $arr = array('1' => 'Nice way', '2' => 'Good way');
    $form['example_select2']['#options'] = $arr;
  }
  return $form['example_select2'];
}

```

# Answer
> 1 votes
1. Remove the `'wrapper' => 'first'` that exist in the `example_select`.
2. Set `'#ajax'=> 'wrapper'` elements to `'first'`, actually this is the id of element that will be updated, in your case `<div id="first">` that you create using the `prefix` and `suffix` in `$form['example_select2']`
3. This is an extra step, for some reason it will work but you'll get an error if you don't add `'#validated' => 'true'`, to `$form['example_select2']`
4. in the ajax callback function `myAjaxCallback` you need to apply some logic that enables you to create form select options dynamically based on the choice you made in the first slect box (see the code bellow )

full code that has been tested in my machine and it works 100% :

```
 public function buildForm(array $form, FormStateInterface $form_state) {
    $form['example_select'] = [
      '#type' => 'select',
      '#title' => $this->t('Select element'),
      '#options' => [
        '1' => $this->t('One'),
        '2' => $this->t('Two'),
        '3' => $this->t('Three'),
        '4' => $this->t('From New York to Ger-ma-ny!'),
      ],
      '#ajax' => [
        'callback' => '::myAjaxCallback',
        'disable-refocus' => FALSE,
        'event' => 'change',
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Verifying entry...'),
        ],
        // The wrapper actually is the id of the element that
        // the ajax response will be injected into
        // it must be isndie the '#ajax" element.
        'wrapper' => 'first',
      ],
    ];

    $form['example_select2'] = [
      '#type' => 'select',
      '#title' => $this->t('Select element'),
      // The "wrapper" id that the ajax response will be injected into
      // must have an id ="wrapper set on select 1 form'.
      '#prefix' => '<div id="first">',
      '#suffix' => '</div>',
      // for some reason you  need to set '#validated' => 'true' other wise tou get :
      // An illegal choice has been detected. Please contact the site administrator.
      '#validated' => 'true',
      '#options' => [],
      '#ajax' => [
        'callback' => '::myAjaxCallback2',
        'disable-refocus' => FALSE,
        'event' => 'change',
        'wrapper' => 'edit-output',
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Verifying entry...'),
        ],
      ],
    ];
    return $form;
  }

  public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
    // 1.construct an array of choices
    // make the key = your select '#options' key
    // and value = options values that you want to use in example_select2.
    $arr = [
      '1' => ['first','uno','first one','Best'],
      '2' => ['Second','2nd place','not first'],
      '3' => ['Third','Three',''],
      '4' => ['Fourth','four','las one'],
    ];

    // 2.Get the selected option value
    // ex : 3
    $selctedOption = $form_state->getValue("example_select");

    // 3.Choose an array based on the selected option value.
    // ex : $arr['3']
    $form['example_select2']['#options'] = $arr[$selctedOption];

    return $form['example_select2'];
  }

```

# Answer
> 0 votes
The below code is working well forme.

```
public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
  if ($selectedValue = $form_state->getValue('example_select')) {
    $arr = array('1' => 'Nice way', '2' => 'Good way');
    $form['example_select2']['#options'] = $arr;
  }
  $form_state->setRebuild(TRUE);
  $response = new AjaxResponse();
  $response->addCommand(new ReplaceCommand("#first", ($form['example_select2'])));
  return $response;
}

```

---
Tags: 8, forms, ajax
---


title: Update Symfony components

text:
# Question
Title: Update Symfony components
There are many posts and articles that make vague references to upgrading Symfony 3 to Symfony 4 in Drupal 8. But nothing specific.

For example this one by Ryan Weaver "Symfony 4 and Drupal"

I've installed a fresh copy of Drupal 8.8.1 and updated with

```
 composer update drupal/core --with-dependencies

```

Then, I ran

```
composer outdated "symfony/*"

```

Clearly, there are symfony components that are outdated.

Is it possible to update these "outdated" components? Or, are we stuck till Drupal 9?

# Answer
> 6 votes
As Ryan Weaver mentions,

> The current version of Drupal - 8.4 - requires Symfony 3.2.8 or higher, but less than 4.0. In practice, this probably means that your Drupal 8.4 project is using the latest Symfony 3.2.\* version. But, you could technically upgrade your Symfony dependencies to version 3.4.
>
> Source: Symfony 4 and Drupal

Thus, you can, but only for minor versions.

---

To quote Dries Buytaert,

> Our biggest dependency in Drupal 8 is Symfony 3, and according to Symfony's roadmap, Symfony 3 has an end-of-life date in November 2021. This means that after November 2021, security bugs in Symfony 3 will not get fixed. To keep your Drupal sites secure, Drupal must adopt Symfony 4 or Symfony 5 before Symfony 3 goes end-of-life. **A major Symfony upgrade will require us to release Drupal 9** (we don't want to fork Symfony 3 and have to backport Symfony 4 or Symfony 5 bug fixes). This means we have to end-of-life Drupal 8 no later than November 2021.
>
> Source: Drupal 7, 8 and 9

He says here that Drupal 8 will reach end of life of Nov 2021 because that's Symfonys 3's end of life. Thus, from this, one can conclude that you can't just upgrade D8 to Symfony 4 (another major Symfony version).

---
Tags: 8
---


# Question
Title: Do multi-level multi-value relationships work in a view?
In Drupal 8, I have a content type **Story**, with a multi-value entity reference to content type **Project**, which, in turn, has a multi-value reference to **Team-Member**, which has a single-value reference to **Person**. In my story node, I want to show a list of projects, and within each, a list of team members.

I have an embedded view (content type **Story**), to which I'm passing the nid as a contextual filter, with 3 relationships defined: referenced **Projects**, referenced **Team-Members**, and referenced **Persons**. I've added fields from all 3 types, each using the correct relationship, I'm pretty sure.

I'm getting **Project** fields correctly, each **Project** in a row. But I'm not getting anything for **Team-Members** or **Persons**.

Am I asking this view to do something views can't do, by having multi-value references 2 levels deep? Is there a better approach? Am I missing something?

# Answer
> 0 votes
> Am I asking this view to do something views can't do, by having multi-value references 2 levels deep?

Yes, to my knowledge there is no way to go 2 levels deep for this scenario.

One possible solution, to work around this constraint, would be to use Views Field View and...

1) Create a team member view that uses the project nid as a contextual filter.

2) Add the project nid (content id) as field to your original view so you can pass it to the views field view.

3) In original view, add a views field, select the team member view you created in Step 1 and pass it the project nid (content id).

# Answer
> 0 votes
After spending a day trying to make this work as an embedded view, I decided to take another approach. Given that my need here is specific to a particular page template, I just wrote a nested loop in twig, with a couple of tests to replicate filters the view would have applied. Much simpler for this situation.

# Answer
> 0 votes
I had the same challenge, and I was able to set up multi-level relationships - thanks to another article on this platform.

---
Tags: views, 8
---


title: How to create content type "News"

text:
# Question
Title: How to create content type "News"
A site user needs to be able to add news to Drupal 8 site.

Some news might be own contents and some news might be from external sources.

If the site user is adding a news which is from an external source, the site user should be able to add a node by just entering the source URL(i.e. examplesite.com/xyz).

If the site user is adding a news which is their own content, the site user should be able to add a node by entering the contents which may have number of paragraphs with titles and few images for each node.

Site user also should be able to add nodes without any coding.

I already create a role and the user for the role.

I created a content type "News" which currently have title and body fields.

How can I create a content type which meets the above requirements?

# Answer
> 0 votes
It sounds like you're off to a good start. Next, you'll need to add a new field to your content type for links to external news articles.

`Home >> Administration >> Structure >> Content types >> News >> Manage fields`

/admin/structure/types/manage/news/fields/add-field

Add a new field of type **Link** and label it something like *News Link*. Save the field.

Decide if you want to allow only one link to be saved in this field, or multiple values. Save the field settings.

Decide if you want to allow external links only in the field (the default is "Both internal and external links"). Save settings.

After that, you'll still need to make a whole bunch of decisions about how to display News content items ... but the Link field seems to be a missing link in your description.

Good luck!

---
Tags: theming
---


# Question
Title: EntityQuery for taxonomy term of specific bundle
I would like to build a query for all taxonomy terms of a specific bundle.

```
$terms = \Drupal::entityQuery('taxonomy_term')
  ->condition('type','mail_template')
  ->execute();

```

This returns an error `'type' not found`.

How do I query taxonomy terms of a specific bundle (specific vocabulary)?

# Answer
Since you are using Drupal 8 you should use the `entityTypeManager` for this task.

This code will load all terms from the `mail_template` vocabulary.

```
$terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties([
  'vid' => 'mail_template',
]);

```
> 4 votes

# Answer
This works :

```
$terms = \Drupal::entityQuery('taxonomy_term')
  ->condition('vid','mail_template')
  ->execute();

```
> 8 votes

# Answer
```
            $termData = \Drupal::entityTypeManager()
            ->getStorage('taxonomy_term')
            ->loadByProperties(['vid' => 'vocabulary_name']);

```

Always works :D

If you also have the name it is

`->loadByProperties(['name' => $term, 'vid' => 'selected_keyword']);`

If you need the id from what is returned

`// returns an array with the tid as the key so
 foreach ($termData as $key => $value){
 $termId = $key;
 // I need the first and only
 break;
 }`
> 3 votes

---
Tags: 8, taxonomy-terms, database
---


# Question
Title: db_select with groupBy(CAST(column as DATE))
I am looking to achieve `GROUP BY CAST(date_time AS DATE)` in a `db_select` function in Drupal 7 but with no idea how.

The function up until now is:

```
 foreach ($distinct_users as $user){
    $day_record = db_select('mytable', 'p')
      ->condition('p.processed', 0, '=')
      ->condition('p.first_name', $user['first_name'], '=')
      ->condition('p.last_name', $user['last_name'], '=')

```

and I need to group the results by day which is in `Y-m-d H:i:s` in my table column.

Please advise.

# Answer
> 0 votes
The solution that worked for me was to group results via php.

---
Tags: 7, database
---


# Question
Title: What is the correct way to update my cached block when a node of a given type is saved or updated?
I have a custom module with a block plugin:

## SliderBlock.php

```
class SliderBlock extends BlockBase {
  public function build() {
    $build = [];
    $build['#theme'] = 'slider_block';

    return $build;
  }
}

```

I want to render a list of nodes of type 'slides' in the block (it will eventually be a custom slider feature)

## mymodule.module

```
function mymodule_theme() {
  return [
    'slides_block' => [
      'variables' => [
        'slides' => get_slides(),
      ],
    ],
  ];
}

function get_slides() {
  // Load all slides nodes.
  $nids = \Drupal::entityQuery('node')
    ->condition('type','slides')
    ->condition('status','1') // Only published slides nodes.
    ->execute();
  $nodes =  \Drupal\node\Entity\Node::loadMultiple($nids);

  return $nodes;
}

```

and I loop over each in the template to get the markup I need:

## slider-block.html.twig

```
{# markup for slider here #}
{% for slide in slides %}
  <p>{{ slide.label }}</p>
{% endfor %}

```

The above template shows me the title field for each Slides node, which is what I expect. The problem is that if I un-publish a Slides node, the markup is not updated unless I clear caches.

Alright, this sounds like a cache issue, so I dove into a google search mission and discovered a series of ways to disable caching for the block. None of which seem to work, for anonymous users or otherwise:

```
// Unsuccessful:
public function getCacheMaxAge() {
  return 0;
}

// Unsuccessful:
$build['#cache'] = [
  'max-age' => 0,
];

```

I looked at cache contexts, as far as I could tell, there was no 'node' based cache context. If I understood them correctly, cache tags wouldn't help, since I don't know the ids of any given node of type 'Slides'.

I 'only want to' disable caching for this block. This block will be rendered only on a specific page, so I could disable caching on that page using the modules route yml file (am I right?), but it feels wrong to disable that whole page for the sake of one block.

What is the right way to solve this, and what's the methodology in reaching that conclusion?

**Note**: I could use views to collect the nodes, but to customise the view markup is more challenging.

# Answer
> 4 votes
As @Clive commented you need a node list cache tag.

Put the slides and the cache tag when you invoke the template in the build array (not in a hook\_theme(), this hook is only called when you install the module):

```
class SliderBlock extends BlockBase {
  public function build() {
    $build = [
     '#theme' => 'slider_block',
     '#slides' => getSlides(),
     '#cache' => ['tags' => ['node_list']],
    ];
    return $build;
  }
}

```

Put a TODO annotation in your code to change the list tag to a content type specific `node_list:slides`, once you have updated to Drupal 8.9.x. See this change record: Added an ENTITY\_TYPE\_list:BUNDLE cache tag.

# Answer
> 2 votes
As mentioned on the comments by @Clive and @leymannx, you need to use *cache tags* to do the job. The problem is with your current approach will be tricky since your nodes are being loaded by your theme hook. Would be much cleaner and Drupal-way of doing things if you refactor your code and make your nodes loaded by the block, so your theme hook can focus on his work: prepare data and render it. Your code could be as follow (dependency injects ommited on purpose, please read more about this here):

**SliderBlock.php**

```
class SliderBlock extends BlockBase {
  private $slides;

  public function build() {
    $this->slides = $this->getSlides();

    if (empty($this->slides)) {
      // Feel free to change to your use case when
      // no slides available.
      // Keep in mind that any non-empty render array
      // could/would be cached.
      return [];
    }

    $build = [];
    $build['#theme'] = 'slider_block';
    $build['#slides'] = $this->slides;

    return $build;
  }

  function getSlides() {
    // Load all slides nodes.
    $nids = \Drupal::entityQuery('node')
      ->condition('type','slides')
      ->condition('status','1') // Only published slides nodes.
      ->execute();
    return \Drupal\node\Entity\Node::loadMultiple($nids);
  }

  public function getCacheTags() {
    $cache_tags = parent::getCacheTags();
    $cache_tags[] = 'block:' . $this->getDerivativeId();

    if (empty($this->slides)) {
       return $cache_tags;
    }

    $node_cache_tags = [];

    foreach ($this->slides as $node) {
      $node_cache_tags[] = $node->getCacheTags();
    }

    $node_cache_tags = array_merge([], ...$node_cache_tags);
    $cache_tags = \Drupal\Core\Cache\Cache::mergeTags($cache_tags, $node_cache_tags);

    return $cache_tags;
  }
}

```

> If you are concerned about **...** a.k.a spread operator and why I merged the tags like that, check this post.

**mymodule.module**

```
function mymodule_theme() {
  return [
    'slides_block' => [
      'variables' => [
        'slides' => NULL,
      ],
    ],
  ];
}

```

Also check this post about block cache tags.

---
Tags: 8, theming, blocks, caching
---


# Question
Title: Is it possible to hide fields on node edit form?
Is it possible to hide fields on node edit form? I've tried Formatter Field but it doesn't work for me. I know it's possible in content type field display management but I need this functionality on node edit form.

# Answer
> 4 votes
You can use the Field permissions module and disable the edit permission for that field, or you can use hook\_form\_alter and the #access property, here's an example:

```
/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, $form_state, $form_id) {

  if ($form_id == "contenttype_node_form") {
    $form['field_foo']['#access'] = FALSE;
  }
}

```

For a node edit form you must also check if the node exists.

# Answer
> 3 votes
The Field extra widgets allows to do this in a easy way:

> Provides two helper widgets for the Field API:
>
> * Hidden: this widget doesn't show anything on the edit form, and as a consequence prevents the user from modifying the content of the widget. This is useful in some situations where using hook\_field\_access() is not suitable (for example when you want to have different edit forms for different users).
> * Read-only: this widget shows the content of the field on the edit form, but doesn't allow the user to edit it. The content is rendered using one of the formatter of the field.

# Answer
> 0 votes
you can use hook\_form\_alter to unset your specified fileds based on form\_id check. hook\_form\_alter()

```
/**
* Implements hook_form_alter().
*/
function MY_MODULE_NAME_form_alter(&$form, $form_state, $form_id) {

  if ($form_id == "contenttype_node_form") {
    unset($form['field_name']);
 }
}

```

i hope now you can understand better..

# Answer
> 0 votes
Using: Drupal 7.39 If you need to show the field for form submission but do not want the user to be able to modify them maybe this will help

I was hijacking basic\_cart form and trying to make the fields readonly, after much stuffing around.

I needed the fields to be submitted but disallow the user to edit the contents of those fields.

I tried your method but it didn't work, I was able to disable the field using:

```
$form[$fieldName][LANGUAGE_NONE][0]['#disabled'] = TRUE;

```

but that meant it (the field) didn't get submitted, so after looking into includes/form.inc I found this gem

```
 if (!empty($element['#disabled'])) {

if (!empty($element['#allow_focus'])) {
$element['#attributes']['readonly'] = 'readonly';
}
else {
  $element['#attributes']['disabled'] = 'disabled';
}
}

```

So then I found this worked.

```
$form[$fieldName][LANGUAGE_NONE][0]['#disabled'] = TRUE;
$form[$fieldName][LANGUAGE_NONE][0]['#allow_focus'] = TRUE;

```

You may or may not need to apply this patch ( I think it works without) https://www.drupal.org/files/issues/drupal-7.x-add\_readonly\_to\_form\_fields-3.patch

And thats how I disabled my fields :D

# Answer
> 0 votes
Use hook\_form\_alter to set the disabled property TRUE for the form field:

If its required to Disable the field only while editing only then,

```
function module_name_form_alter(&$form, &$form_state, $form_id){
  if($form_id == 'form_id_name'){
    if (arg(2) == 'edit') { #Use the URL parts
        $form['field_name']['#disabled'] = TRUE;
     }
  }
}

```

If its required to Hide the field only while editing only then,

```
function module_name_form_alter(&$form, &$form_state, $form_id){
  if($form_id == 'form_id_name'){
       if (arg(2) == 'edit') { #Use the URL parts
         $form['field_name']['#access'] = FALSE;
     }
   }
}

```

# Answer
> -1 votes
You can use hide() function in `template.php` or `node--CONTENTTYPE--edit.tpl.php` files.

---
Tags: forms
---


# Question
Title: hook_form_alter hiding field only in the form
I have a content type with fields added from the core module and I want to hide some fields in the edit form, but not in the page node.

I've tried with

`$form['my_field']['#access'] = FALSE;` in my custom module, but that hides the field in the node page too. Is there any other way to hide the field only in edit form?

My approach was to wrap some fields into a two columns. Here's what I've tried:

```
  <?php
    /*
     * Implements hook_form_alter().
     */

    function my_module_form_alter (&$form, &$form_state, $form_id) {
         switch ($form_id) {

          case 'custom_node_form':

          $form['column_left'] = array(
          '#prefix' => '<div class="column-left">',
          '#suffix' => '</div>',
            );

           $form['column_left']['custom_field'] = $form['custom_field'];
           $form['custom_field']['#access'] = FALSE;
         break;
       }
    }

```

Unfortunately it's disabling into the page node too. I'm using Display suite for the full content and I'm pretty much sure that the field is not hidden from there.

# Answer
Have you checked

```
admin/structure/types/manage/my_content_type/display

```

Your field is probably hidden here.

Otherwise, hook\_form\_alter is only for form you are right

An other attribute is :

```
$form['my_field']['#disabled'] = TRUE;

```
> 1 votes

# Answer
If you simply want it not to show on your edit form, modify your theme css file

```
.element_class {
  display: none;
}

```
> 0 votes

# Answer
Use hook\_form\_alter to set the disabled property TRUE for the form field:

```
$form['field_name']['#disabled'] = TRUE;

```

Please refer to: Is it possible to hide fields on node edit form?
> 0 votes

---
Tags: forms
---


# Question
Title: How to suppress "page not found" messages in watchdog
The issue `Add an option to suppress page not found watchdog messages` at https://www.drupal.org/node/2836458 indicates that a setting was added to Drupal 8 to suppress page not found errors in watchdog. I can't find the setting in the interface. Am I mistaken in understanding that it was added? If not, where do I find this setting? Running Drupal 8.8.1.

# Answer
> 5 votes
Yes that option is available as described in the linked issue.

Make sure you have the Redirect 404 module enabled, visit `/admin/config/search/redirect/settings`, and select the *Suppress 'page not found' log messages* option.

That will stop 404s being logged.

---
Tags: 8, log-messages
---


# Question
Title: Render media url in node--page.html.twig
I have an Entity reference field `field_video`. It's a core Media field with a Reference type of Remote video.

Because I use this `field_video` in my Hero section I need some additional markup here.

From the admin `node/add/page`, the editor can insert a Youtube remote video (url).

When I debug the page I see the following variables (see screenshot).

How do I render the media url in `node--page.html.twig`? Then I am able to build the correct HTML markup and styling around it.

# Answer
> 0 votes
To get the `uri` of remote video in `node--page.html.twig` try with:

```
node.field_video.entity.field_media_oembed_video.value

```

---
Tags: 8, theming, media, uri
---


# Question
Title: How to use custom class methods in the .theme preprocess functions?
In a try to get code cleaner, I thought I could write a service in a custom module and use its methods within `mytheme.theme`, but obviously the preprocess functions signatures don't accept *extra parameters*.

In `modules/custom/custom_module/src/Service/FooThemeHelpers.php`

```
namespace Drupal\custom_module\Service;

class FooThemeHelpers
{
  // Add a specific custom format
  public function format_profile_adresse($field_profile_adresse){

    // do stuff ...

    return $markup;
  }
}

```

**Then in mytheme.theme**

```
use Drupal\custom_module\Service\FooThemeHelpers;

function mytheme_preprocess_views_view_fields(&$variables, FooThemeHelpers $themeHelpers) {

    if($variables['view']->id() == 'bar') {

      $markup = $themeHelpers->format_profile_adresse($variables['fields']['field_profile_adresse']->content);
      $variables['fields']['field_profile_adresse']->content = $markup;
  }
}

```

> TypeError: Argument 2 passed to mytheme\_preprocess\_views\_view\_fields() must be an instance of Drupal\custom\_module\Service\FooThemeHelpers, string given

I tried also with `template_preprocess_page_title()`, same error.

Should I declare and use **static methods** instead in my service ? Is there any *Drupal coding standard way* to export these helpers functions in a dedicated class, so that .theme remains lighter and readable... ?

# Answer
> 4 votes
The dependency injection coding standards only apply to most * classes.
In functions, use `$service = \Drupal::service('service_name')` to get the service.

To test code written in these functions, mock the services then build a custom container for them and assign it to Drupal using `\Drupal::setContainer($container)`.

See `Drupal\Tests\Core\Annotation\TranslationTest` for an example of building a test container.

* Entity types, classes implementing TypedDataInterface, and certain plugins with custom plugin managers do not support dependency injection.

# Answer
> 2 votes
This is not exact answer to the question but to the code example there, so if you really trying to achieve the task in the example code, then the right way is to use custom FieldFormatter and you can set this one on any views and/or entity view\_mode for field type address. You can easy get a boilerplate with drupal console command

```
drupal generate:plugin:fieldformatter

```

name it CustomAddressFieldFormatter for ex. This should happen in custom module. Pay attention to viewElements() method, address data is in $item, and you should return renderable array such as #markup, or any other valid,

```
  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];

    foreach ($items as $delta => $item) {
      //ksm($item);
      $elements[$delta] = ['#markup' => $item->getLocality()];
    }

    return $elements;
  }

```

or create your theme for an element and pass the data to it here. Above code will print the address City only for ex.

Look here https://www.drupal.org/docs/8/creating-custom-modules/creating-custom-field-types-widgets-and-formatters/create-a-custom-0 but instead in field\_types Random you should use address

Then in views or entity viev\_mode for field address, for Formatter you will have your custom formatter (Custom Address Field Formatter) as option to select - how this field to be rendered in the page.

---
Tags: 8
---


title: Commerce 2 Twig and Retail Price

text:
# Question
Title: Commerce 2 Twig and Retail Price
I have a use case that I need to add the retail price on a receipt twig next to the discounted unit price. Ive tried every possible field syntax I could think to try, looked everywhere and stumped...

{{ order\_items.i\_need\_the\_retail\_price... }}

Is it possible to get that related field with twig syntax? It doesnt appear to be carried into Order Items.

# Answer
After a few more hours learning twig filters I can calculate the retail price in each line item with this:

```
{% for adjustment in totals.adjustments %}
{% set disc_percent_remainder = 1 - adjustment.percentage %}
{% set disc_unit_price_raw_2 = order_item.getUnitPrice|commerce_price_format %}
{% set disc_unit_price_raw_1 = disc_unit_price_raw_2|trim(' USD', 'right') %}
{% set disc_unit_price_raw = disc_unit_price_raw_1|trim('$', 'left') %}
{% set disc_unit_price = (disc_unit_price_raw * 100) / disc_percent_remainder %}
${{ (disc_unit_price / 100)|round(2, 'ceil') }}
{% endfor %}

```

This is a horrible work-around I'm sure, ruins any chance of multiple currencies and Im sure can be cleaned up a lot with nesting some of this. But, it comes up with the correct retail pice.
> 0 votes

---
Tags: commerce
---


title: How do I send a HTML email?

text:
# Question
Title: How do I send a HTML email?
Does anyone know how to send HTML email using the Rules module? This was a pretty common task in Drupal 7, and I think the rule was included with the Mime Mail module.

The Drupal 8 version of Mime Mail doesn't seems to integrate with the Rules module.

# Answer
> 1 votes
> The Drupal 8 version of Mime Mail doesn't seems to integrate with the Rules module.

This question and the follow-up comment seem to imply that Rules integration with Mime Mail is NEEDED in order to send HTML email with Rules. That's not true. Drupal core doesn't support HTML email, so you need an add-on module like Mime Mail if you want to send HTML email. But if you have Mime Mail installed, then you can send HTML email from ANY source, INCLUDING Rules. If you follow the Mime Mail Quick Start documentation you will get this working in just minutes.

There is also a complete example at https://www.drupal.org/docs/8/modules/d8-rules-essentials/examples/email-examples/sending-html-email showing how to send HTML email from Rules using Mime Mail.

Mime Mail integration with Rules allows Rules to use the ADDITIONAL features provided by Mime Mail which are not part of Drupal core or part of other email modules. But this additional integration is not needed unless you want to use those Mime Mail features. For example, the ability to add attachments, or to specify a plaintext email body that is different from the HTML body. Those are Mime Mail specific features.

Mime Mail is not completely ported to D8 yet but there is a patch that ports the Rules support at https://www.drupal.org/project/mimemail/issues/2928965 If you need these additional features I suggest you contribute to that issue.

---
Tags: 8, rules, mimemail
---


title: What good is the create() method?

text:
# Question
Title: What good is the create() method?
Most classes are instantiated using `create($container)` and `__construct(...$services)` in conjunction, it seems that the more efficient workflow would be to simply pass the container to the constructor `__construct($container)` and not have the create method at all. Is this inherited from Symfony? What purpose does it serve?

# Answer
> 1 votes
The create() \__construct() pattern does make testing easier, but not by much. A new container can be very easily generated and populated with the required services for unit testing.

# Answer
> 1 votes
Just my two cents: If you use such a system it is not needed to set the required services in a service.yml but you can easily set, overlook and check the services in the class itself - in the create() method, where you define all the services. I find this more comfortable than writing everything in a YAML file

---
Tags: 8, dependency-injection, symfony-services
---


# Question
Title: How to extend a specific node type form?
I am searching a way to overwrite the `NodeForm` to get a class per bundle.

Actually `EntityForm` manages the form for all entities. `NodeForm` extends it and manages the forms for all nodes.

I wrote a `CustomNodeForm` replacing `NodeForm` behaviour for all nodes.

```
/**
 * Implements hook_entity_type_build().
 */
function ftvisi_main_entity_type_build(array &$entity_types) {
  $entity_types['node']->setFormClass('default', CustomNodeForm::class);
}

```

Now I'd like to get a class per bundle extending that `CustomNodeForm` but I feel like I am not able to do it.

`CustomNodeForm` might instantiate a form for each bundle - but I don't like that approach and we still just have one constructor which can leads to problems such as:

*"OK my first bundle form needs this service, and my second bundle form needs another one, should I inject the full container itself and then use services on the fly ?"* =\> Pretty bad idea, I know.

Anyway, if `CustomNodeForm` instantiates other classes itself, it will be hard to mock and test. So I definitively don't like that approach.

I then thought about using the form modes, but same problem: a form mode can be used on any node type, so we still don't have a class per bundle and we still have only one constructor for all forms using that form mode.

Any idea to help?

# Answer
AFAIK forms are tied to operations at entity-type level, so you don't have any hook to only alter the form for a particular bundle. Since what you want is to inject certain services for a given bundle what you can do is to implement a chain of responsability pattern through service collectors. This allows you to inject only the service collector to your form and delegate to the collection to evaluate which service should apply for your given bundle. And finally the resolved service is the one that would concentrate the responsability. I could provide you with a deep example but could take some time, let me know if a code sample still needed.

**UPDATE**

This will be the solution in a near future, since sub-classing is the feature you are referring.
> 0 votes

---
Tags: 8, nodes, forms
---


# Question
Title: Get field value and label for a content type using REST API
I need to create a REST API endpoint with GET operation in Drupal 8. The API should return all fields of a given content type. Right now I am only able to fetch the title.

Also, I am not supposed to use the REST Export option in views module but the expected output is same as what we get using the Views REST Export option.

This is the code I have written for the get() method and right now only title is being displayed. I want to output the remaining fields as well.

```
public function get() {
    if (!$this->currentUser->hasPermission('access content')) {
        throw new AccessDeniedHttpException();
    }

    $query = \Drupal::entityQuery('node')
      ->condition('status', 1)
      ->condition('type', 'schemes_funds_nav')->execute();

    $nodes = \Drupal\node\Entity\Node::loadMultiple($query);

    foreach ($nodes as $entity) {
        $result[$entity->id()] = $entity->title->value;
    }

    $response = new ResourceResponse($result);
    $response->addCacheableDependency($result);

    return $response;
}

```

Any help is highly appreciated. Thanks in advance.

# Answer
In the foreach you add just title so it's normal to have only title displayed: you should populate your array result with the values from your entity, something like:

```
  foreach ($nodes as $entity) {
    $result[] = [
      'nid' => $entity->id(),
      'title' => $entity->title->value,
      'FIELD_NAME_1' => $entity->FIELD_NAME_1->getValue(),
      'FIELD_NAME_2' => $entity->FIELD_NAME_2->getValue(),
       // And so on with other fields.
    ];
  }

```
> 1 votes

---
Tags: 8
---


# Question
Title: Third-party modules installed with Composer don't have their version in the .info.yml file
I have a project installed by composer, everything working perfectly, except when i run `composer install` contrib module installed successfully in `web/modules/contrib` but none of the modules `.info.yml` contain something like:

```
# Information added by Drupal.org packaging script on 2016-06-09
version: '8.x-3.0-alpha2'
core: '8.x'
project: 'MODULENAME'
datestamp: 1465505348

```

Issue is i don't see module needs update in *admin/reports/updates*
and when i run `drush ups` i get

Or even `composer show` i get

Even on *admin/modules* i can't see the module version  Like the following picture from another project

And i can't run `drush updb` throw an error

> The Pathauto module is not compatible with the current version of Drupal core. Update the Pathauto module to 8.x-1.6 or later.

Because it check on pathauto version in system\_requirements and get the version as null:

```
$info = \Drupal::service('extension.list.module')->getExtensionInfo('pathauto');
// This is null
$info['version']

```

Composer version **1.9.1** .
My `composer.json`:

```
{
  "authors": [
    {
      "name": "Author",
      "email": "email@gmail.com"
    },
    {
      "name": "Author 2",
      "email": "contact@somedomaine.fr"
    }
  ],
  "autoload": {
    "psr-4": {
      "Osinet\\Deploy\\": "scripts/Osinet/"
    },
    "classmap": [
      "scripts/composer/ScriptHandler.php"
    ]
  },

  "config": {
    "discard-changes": true,
    "preferred-install": "source",
    "process-timeout": 3600,
    "secure-http": false,
    "sort-packages": true
  },
  "conflict": {
    "drupal/drupal": "*"
  },
  "description": "Project",
  "extra": {
    "installer-paths": {
      "drush/contrib/{$name}": ["type:drupal-drush"],
      "import": ["type:zend-extra"],
      "web/core": ["type:drupal-core"],
      "web/libraries/{$name}": ["type:drupal-library"],
      "web/modules/contrib/{$name}": ["type:drupal-module"],
      "web/profiles/contrib/{$name}": ["type:drupal-profile"],
      "web/themes/contrib/{$name}": ["type:drupal-theme"]
    },
    "osinet-builder": {
      "params": "settings/params.local.yml",
      "tmp-dir": "tmp"
    },
    "patches": {
      "drupal/media_entity": {
        "Fix broken route remote": "https://www.drupal.org/files/issues/dynamically_define_menu-2831071-17.patch"
      }
    },
    "bin-dir": "bin"
  },
  "license": "GPL-2.0+",
  "minimum-stability": "dev",
  "prefer-stable": false,
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/dawehner/drush_language.git"
    },
    {
      "type": "vcs",
      "url": "https://github.com/kgaut/drupal-potx.git"
    },
    {
      "type": "composer",
      "url": "https://packages.drupal.org/8"
    }
  ],
  "require": {
    "php": "^7.0.0",
    "ext-SPL": "*",
    "ext-SimpleXML": "*",
    "ext-Zend-OPcache": "*",
    "ext-ctype": "*",
    "ext-curl": "*",
    "ext-date": "*",
    "ext-dom": "*",
    "ext-filter": "*",
    "ext-gd": "*",
    "ext-hash": "*",
    "ext-json": "*",
    "ext-openssl": "*",
    "ext-pcre": "*",
    "ext-pdo": "*",
    "ext-pdo_mysql": "*",
    "ext-session": "*",
    "ext-tokenizer": "*",
    "ext-xml": "*",
    "lib-curl": "^7.36.0",
    "lib-iconv": "*",
    "lib-libxml": "*",
    "lib-openssl": "*",
    "lib-pcre": "*",
    "composer/installers": "^1.3",
    "cweagans/composer-patches": "~1.6.2",
    "drupal-composer/drupal-scaffold": "^2.3",
    "drupal/admin_toolbar": "^1.19",
    "drupal/advagg": "^4.0",
    "drupal/allowed_formats": "^1.1",
    "drupal/autologout": "^1.0",
    "drupal/cdn": "3.x-dev",
    "drupal/ckeditor_iframe": "^2.0",
    "drupal/ckeditor_media_embed": "1.x-dev",
    "drupal/color_field": "2.x-dev",
    "drupal/console": "^1.8.0",
    "drupal/core": "8.8.1",
    "drupal/crop": "1.x-dev",
    "drupal/date_popup": "1.x-dev",
    "drupal/draggableviews": "1.x-dev",
    "drupal/drush_language": "dev-8.x-1.x",
    "drupal/eck": "^1.0",
    "drupal/entity": "^1.0-rc1",
    "drupal/entityqueue": "1.x-dev",
    "drupal/fakeobjects": "1.x-dev",
    "drupal/field_group": "^3.0-beta1",
    "drupal/field_hidden": "^1.0",
    "drupal/file_version": "^1.0",
    "drupal/form_mode_manager": "2.x-dev",
    "drupal/image_widget_crop": "^2.1",
    "drupal/inline_entity_form": "1.x-dev",
    "drupal/jwt": "^1.0@alpha",
    "drupal/maxlength": "1.0-beta4",
    "drupal/media_entity": "1.x-dev",
    "drupal/media_entity_image": "1.x-dev",
    "drupal/memcache": "2.x-dev",
    "drupal/migrate_plus": "^4.0",
    "drupal/migrate_source_csv": "2.2",
    "drupal/migrate_tools": "^4.0",
    "drupal/pathauto": "1.6",
    "drupal/restui": "^1.17",
    "drupal/toolbar_menu": "^2.1",
    "drupal/ultimate_cron": "^2.0",
    "drush/drush": "8.x-dev"
  },
  "require-dev": {
    "behat/behat": "^3.4",
    "behat/mink-extension": "^2.2",
    "behat/mink-goutte-driver": "^1.2",
    "composer/composer": "^1.5@dev",
    "doctrine/cache": "~1.6.2",
    "doctrine/collections": "~1.4.0",
    "doctrine/common": "~2.7.0",
    "doctrine/inflector": "~1.2.0",
    "doctrine/instantiator": "~1.0.5",
    "drupal/coder": "^8.2",
    "drupal/config_inspector": "1.x-dev",
    "drupal/devel": "1.x-dev",
    "kgaut/potx": "8.x-1.x-dev",
    "phpunit/phpunit": "^6.1",
    "squizlabs/php_codesniffer": "^2.7.0",
    "symfony/phpunit-bridge": "^3.4.3"
  },
  "scripts": {
  },
  "type": "project"
}

```

Any ideas, will be appreciated!

# Answer
Remove `"preferred-install": "source"` from config or set it to `"dist"`.
Putting `"source"` means Composer will get a package from a version control repository. And it seems to be downloading directly from https://git.drupalcode.org where all projects have no fixed version in their info files no matter which Git tag you check out.

You also can set more advanced patterns, check https://getcomposer.org/doc/06-config.md#preferred-install. In your case it probably can be boiled down to the following.

```
{
    "config": {
        "preferred-install": {
            "drupal/*": "dist",
            "*": "source"
        }
    }
}

```

Then remove vendor/, remove the lock file and reinstall. `rm -rf vendor/ && rm composer.lock && composer install`.
> 3 votes

# Answer
As pointed out in the other answer, you are getting Git checkouts due to the `"preferred-install": "source"` in the *composer.json* file. You could remove that (or replace the "source" value with "dist", although presumably you have that there for a reason).

To solve this problem, there is the Composer Deploy module, which augments Drupal's internal version information with information from composer's metadata. If you want to install from source *and* you want version information, this is the way to do it.
> 0 votes

---
Tags: 8, composer
---


# Question
Title: How to filter views results based on entity reference field
I use Drupal 7 and entityreference module. I have a content type with a entity refenrece field to users called field\_users\_referenced.

So I created a view with views module and list nodes of thats content type. I want to order this views result based on field\_users\_referenced.

when I add field\_users\_referenced field on filter fields, and set it for exposed filter , after type a field\_users\_referenced value on thats field, have no any result.

I **do not want** to filter field\_users\_referenced with select box, I want to type value on exposed filter field and order results.

please help me.

# Answer
> 6 votes
Advance View Settings -\> Add Relationship -\> Select Entity Reference Field

Then in filters -\> add Filter-\> Select field from the respective entity.

Thanks

# Answer
> 2 votes
In Drupal 8, you can do one of the following. These are in order from more recommended to less recommended:

1. Apply the latest core patch from Generalize TaxonomyIndexTid filter to be available for all entity reference fields (unless it's been committed by the time you're reading this),
2. Use the Entity Reference Exposed Filters module, or
3. Follow the instructions in Entity reference filter with Drupal 8, which require custom code.

# Answer
> 1 votes
You have to add your entity reference field as a relation to the view, and then you can use the fields from the User entity type in you filter section and configure it/them as you please.

# Answer
> 1 votes
Based on of the @Colan solution. Add the following Patch to your `composer.json` file

```
"extra": {
    "patches": {
        "drupal/core": {
            "View Entity Reference Field" : "https://www.drupal.org/files/issues/2019-12-24/drupal-generalize-taxonomyindextid-filter-2429699-277.patch"
        }
    }
}

```

then run `composer install` and **Rebuild the cache**.

# Answer
> 1 votes
There is another way for Drupal8. Try using the verf module

---
Tags: 7, entities, views
---


# Question
Title: How do I prevent the automatic removal of a database table when a module is uninstalled?
In Drupal 7, a database table created through `hook_schema()` gets created on module installation, and gets deleted on uninstallation.

I would like to prevent the removal of a database table when the module defining it is uninstalled, because the data which I am storing is very important so I want to make sure that even if someone even uninstalls the module for certain purpose than also data retains. Backing up the table before is certainly one solution but I am looking for some better alternative.

# Answer
> 2 votes
Uninstall is there just to delete changes made to database. If you do not want that deletion to happen, do not uninstall. If you need only one table, back it up before uninstallation and restore it after. If you want to remove module from uninstall list, simply delete it's files.

If you need selected module to be always on, you can use `hook_modules_disabled()` in a helper module, to display message like *"Disabling of this module is not permitted"* and instantly re-enable it. If module is never disabled, there will be no option to uninstall it. Of course if someone with admin privileges will want to destroy your data, he will, so don't give those privileges to those who can't be trusted with them, but at least it should prevent accidental module removal by developer who is not bright enough to stop and think.

Last but not least, if module's data is of significant importance, you have daily or maybe even hourly backups anyway, so accidental deletion is not a problem at all. Backup and Migrate and Elysia Cron are great help with setting up backups like this, but you should also ask your sysadmin to provide automatic copy to another physical machine, if possible.

# Answer
> 0 votes
I would implement `hook_install` and `hook_uninstall` and not use `hook_schema`.

In hook\_install you can use the database api to create the table. Then leave your hook\_uninstall blank, thus preserving the table and data.

# Answer
> 0 votes
I had the same problem, i solved implementing the `hook_schema` and `hook_uninstall` in this way

```
/**
 * Implements hook_uninstall().
 */
function my_module_uninstall() {
    drupal_static( 'my_module_uninstall', true );
}

/**
 * Implements hook_schema().
 */
function my_module_schema() {
    if( drupal_static( 'my_module_uninstall', false ) ){
        return null;
    }

    return array(
        'my_table' => array(
            // table definition
        ),
    );
}

```

When the module will be uninstall the `hook_schema` will be executed again (after the hook\_uninstall), the schema will not be returned hence it will not be deleted by the `drupal_uninstall_schema` function.

However this is a sort of workaround: the response of @Mołot is more useful if you have to redistribute your custom module. But for my needs I prefered my approach as my module will not be used outside my project, and I wanted to be sure that the table will be there even after an accidental uninstall.

---
Tags: 7, hooks, database
---


# Question
Title: Execute a custom shell script before the aegir verify
Every actions in aegir trigger a verify.

I would like to automatically execute a shell script before that verify (rsync of plateforms).

How could I proceed ?

# Answer
> 2 votes
You could implement a drush\_hook\_pre\_COMMAND() hook in drush to run any code you'd like.

See the docs page for more details: https://docs.aegirproject.org/extend/altering-behaviours/#running-extra-code-after-a-task

---
Tags: aegir
---


title: Connection issues

text:
# Question
Title: Connection issues
New to Drupal 8 and tripped up on this one. It seems something wrong with database but if anyone has tips please let me know! Here is my code:

and here is error:

And my drupal site isn't working at all:

Not really even sure where to start looking. Also, using Acquia DevDesktop if that helps at all. Thanks!

# Answer
**Acquia DevDesktop** create it's configuration inside *USER\_DIR/.acquia/DevDesktop/DrupalSettings/* folder in file called `loc_drupal8theming_dd.inc` in your case.
So no need to add another Database configuration. Just remove the last part `$databases['default']['default'] = [ ] ...`
> 0 votes

# Answer
Ultimately, updating Drupal ended up solving my issue: https://www.drupal.org/docs/8/update/update-core-via-drush. Even though there were no updates to be made, I guess something in that process (I think dropping then updating my database) resolved my site issues. Thanks to everyone though because they helped solve my first command line error.
> 0 votes

---
Tags: 8, database, acquia-dev-desktop
---


title: Send view field in URL - Drupal

text:
# Question
Title: Send view field in URL - Drupal
I have a search page created with embedded filters in Drupal 8 View. In the list of fields I have a fields - \[Field\_program\_id\]. I also have a button 'Learn more' when clicking this button I want to pass the \[field\_program\_id\] and show the details of the Programs in that page. Not sure where to start. Any guidance?!

My view looks as below:

The '968' is the Program ID. Upon clicking the learn more, I want my url to be https://myproj/search?nodeid=\[field\_program\_id\]

and in this page I want to show the details again. Any help?!

# Answer
In replacement to your "Learn more" add "Custom text" field after "Field\_program\_id" in your views. In "Text" add "a" tag like

```
<a href="/search?nodeid={{field_program_id}}" class="button">Learn more</a>

```

Take a look in "Replacement patterns" for available fields. Read description there too for a guidance.

(this is in Drupal 8)

It is the almost the same in Drupal 7, just with \[\] instead {{}}. Class for "button" depends of the theme.
> 1 votes

---
Tags: views, nodes, forms, redirection
---


# Question
Title: Alter Existing Route - Bypass/override entity permission
I added a custom access check to a JSON API endpoint so that only users who provide a token can POST/PATCH updates on a media endpoint. I followed this documentation in order to alter an existing route using `RouteSubscriber:alterRoutes()` and a custom access check.

Everything is working properly with my custom access check. I have a custom condition which will either forbid or allow access based on a condition:

```
public function access() {
   $valid = $this->validateToken($token);

   if ($valid) {
     $access = AccessResult::allowed()
   } else {
     $access = AccessResult::forbidden('The access token is invalid');
   }

   return $access;
}

```

If the user does not fulfill the appropriate condition, then access is denied through my custom access check.

However, if the custom access check allows access, the default entity permissions are still being applied. I get a 403 Forbidden error saying:

```
The current user is not permitted to upload a file for this field. The following permissions are required: 'administer media' OR 'create media' OR 'create [machine_name] media'

```

When I allow access, I want whichever user who provided the correct token to be able to create a particular entity (including anonymous users). How do I override the entity permission system so that whoever fulfills the condition has access to create the entity?

Can I dynamically add the permission to this user to create this particular entity for just this request?

Right now in my alterRoutes() function I am setting a requirement for my `_custom_access`. Do I also need to set an additional requirement for `_entity_access` or `_entity_create_access`?

# Answer
Drupal uses both route access and entity access. You need to add your access check in hook\_entity\_access() because the media entity module is denying create access. Use route access for non entity pages.
> 2 votes

---
Tags: 8, routes
---


title: Get currently logged in user

text:
# Question
Title: Get currently logged in user
I am facing an almost similar problem whereby if I do:

```
$userCurrent = \Drupal::currentUser();
$name = $userCurrent->getUsername();

```

I get the site account name instead of the logged in user. Which is the right way to get the logged in username or roles for that matter. I even tried:

```
$user = Drupal\user\Entity\User::load($userCurrent->id());

```

But all this does not seem to work.

Any suggestions?

# Answer
Try this

```
<?php
// Load the current user.
$user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());

// get field data from that user
$website = $user->get('field_website')->value;
$body = $user->get('body')->value;

$email = $user->get('mail')->value;
$name = $user->get('name')->value;
$uid= $user->get('uid')->value;
?>

```

Or

```
$uid = \Drupal::currentUser()->id();
$user = \Drupal\user\Entity\User::load($uid);
$name = $user->getUsername();

```

You will get more details about User::getUsername.
> 8 votes

# Answer
If you get the site account name instead of the logged in user, then there is no user logged in at the point the code is run.

`\Drupal::currentUser()` gets an account. This can be an user or an anonymous session. Both share the same interface and methods.

Your code is OK. Why you get the wrong account is difficult to say, because there is not enough details in the question. It could be a caching issue. Then you would have to add a cache context for the user.
> 3 votes

# Answer
Could it be that before trying to obtain the user name for the current user you should first check if the user is an authenticated user e.g.:

```
    $userCurrent = \Drupal::currentUser();
    if ($userCurrent->isAuthenticated()) {
        $name = $userCurrent->getAccountName();
    }
    else{
        $name = "Anonymous/Unauthenticated User";
    }

```
> 1 votes

# Answer
You can get the username & email of the current logged in user like so:

```
function tropical_preprocess_page(&$variables){
   # gets current username
   $user_logged_in_name = $variables['user']->getDisplayName();

   # Capitalize first letter
   $variables['user_logged_in_name'] = ucfirst($user_logged_in_name);

  # gets User Email
  $user_email = $variables['user']->getEmail();
  $variables['user_email'] = $user_email;
}

```

You can output the results in the HTML like so:

```
<h2>Welcome back, {{ user_logged_in }}!</h2>
<p>The email for this user is: <strong>{{ user_email }}<strong></p>

```

I am not sure if this is what you want. I hope it helps...
> 0 votes

# Answer
This question depends on where you are trying to access this information.

Dependency injection is the ideal way to call drupal services.

Often what you can do is go to core (\[webroot\]/core/lib/core), and look at core.services.yml. Tons of services are used in this file, making it a great reference point.

For instance you want the current user, so search for say 'user' and look for '@\[service-name\] definitions. In this case you will find a '@current\_user'.

This means a service exists with that name. That service also happens to be defined in this file. Further down you will find the 'current\_user:' service definition.

```
current_user:
  class: Drupal\Core\Session\AccountProxy
  arguments: ['@event_dispatcher']

```

Within that you can see what class it calls, so when you inject this service, or call for the current user via `\Drupal::currentUser()`, this is the class it is calling.

You can then open up that class to see what is available for use.

If you are writing a custom module, you add a \[module\_name\].services.yml file and define your modules service name, then inject the @current\_user service.

Which means adding your @ service values to the arguments array of comma separated values.

For instance:

```
services:
  commerce_custom_shipping_carts:
    class: '\Drupal\commerce_custom_shipping_carts\EventSubscriber\CommerceCustomShippingCartsEventSubscriber'
    arguments: ['@messenger', '@string_translation', '@current_user']
    tags:
      - { name: 'event_subscriber' }

```

Then within your class constructor, pass in the service:

```
   * Messenger Interface.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * String Translation Interface.
   *
   * @var \Drupal\Core\StringTranslation\TranslationInterface
   */
  protected $stringTranslation;

  /**
   * Current user session.
   *
   * @var \Drupal\Core\Session\AccountProxy
   */
  protected $currentUserSession;

  /**
   * Constructs a new CartEventSubscriber object.
   *
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation.
   * @param \Drupal\Core\Session\AccountProxy $currentUserSession
   *   The current user session.
   */
  public function __construct(MessengerInterface $messenger, TranslationInterface $string_translation, AccountProxy $currentUserSession) {
    $this->messenger = $messenger;
    $this->stringTranslation = $stringTranslation;
    $this->currentUserSession = $currentUserSession;
  }

```

Then you can use anything in the class with: `$this->currentUserSession->[method_name]([method_parameters]);`
> 0 votes

---
Tags: users, 8
---


# Question
Title: Update title field in hook_ENTITY_TYPE_insert()
I use `hook_ENTITY_TYPE_presave()` and `hook_ENTITY_TYPE_insert()` in order to update the node with a title using its ID.

```
function <module_name>_node_presave($node) {
  // ...
  if ($node->isNew() && $node->getType() == '<custom_content_type>') {
    $node->title = 'New entity ' . $node->id()->value;
  }
}

function <module_name>_node_insert($node) {
  if ($node->getType() == '<custom_content_type>') {
    $node->title = 'Submission #' . $node->id();
    // more code...
    $node->save();

  }
}

```

The first setting of title in `hook_ENTITY_TYPE_presave()` is only done because no entity can be saved without title. However, it seems like the setting of the title in `hook_ENTITY_TYPE_insert()` does not change anything.

I have already tried calling `node->save();` in `hook_ENTITY_TYPE_insert()` but it gives me an exception stating that I try to store an entity using an already existing primary key. The exception message is

> The website encountered an unexpected error. Please try again later.
>
> Drupal\Core\Entity\EntityStorageException: SQLSTATE\[23000\]: Integrity constraint violation: 1062 Duplicate entry '48' for key 'PRIMARY': INSERT INTO {node\_revision} (nid, vid, langcode, revision\_timestamp, revision\_uid, revision\_log) VALUES (:db\_insert\_placeholder\_0, :db\_insert\_placeholder\_1, :db\_insert\_placeholder\_2, :db\_insert\_placeholder\_3, :db\_insert\_placeholder\_4, :db\_insert\_placeholder\_5); Array ( \[:db\_insert\_placeholder\_0\] =\> 45 \[:db\_insert\_placeholder\_1\] =\> 48 \[:db\_insert\_placeholder\_2\] =\> en \[:db\_insert\_placeholder\_3\] =\> 1485011236 \[:db\_insert\_placeholder\_4\] =\> 11 \[:db\_insert\_placeholder\_5\] =\> ) in Drupal\Core\Entity\Sql\SqlContentEntityStorage-\>save() (line 770 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

Can I change the title of the new entity (using the id)? Should I use another hook?

# Answer
Since nodes have no id on insert, you should just save the node twice.

node\_save() initiates a database transaction, in which the changes are not yet written, but the id is already reserved (explaining your issues with not being able to save). You will have to await the database transaction before attempting to save the node again. Unfortunately there is no hook for this.

However, there is a workaround: drupal\_register\_shutdown\_function(). This can be used to call an additional function at the end of the request.

You'll end up with a code like this:

```
function your_module_node_insert($node){
  if($node->type == 'your_node'){
    drupal_register_shutdown_function('_your_module_post_insert',$node);
  }
}

function _your_module_post_insert($node) {
  if ($node) {
      $node->save();
  }
}

```

Code comes originally from here: https://drupal.stackexchange.com/a/102185/9921
> 6 votes

# Answer
The presave hook is called *before* the entity is saved, due to that, it does not yet have an ID. That makes you can not use it, it will be empty (your code there is also wrong, id(), returns an ID, not an object, either -\>nid-\>value, or -\>id(), as you have in insert().

The insert hook does have an ID, but it it's *after* saving. You're updating the object in memory but it is not persisted (again) automatically. You can persist it if you want to, simply by explicitly calling $node-\>save() again.

However, that obviously has some performance drawbacks (but it is possible, despite what the other answers said) as you have to save everything twice.

My recommendation would simply be to rely on a value that you do know, which is basically everyting except the ID and revision ID. For example the creation date:

$node-\>title = 'Submission from ' . \Drupal::service('date.formatter')-\>format($node-\>getCreatedTime());

in hook\_presave() should work fine and give you a title that contains a user readable timestamp.
> 2 votes

# Answer
During hook\_ENTITY\_TYPE\_insert the entity does not have an ID. It gets an ID only after it is saved into the database.

You can, of course, save the entity after it has already been saved and use the ID in the entity title.

```
mymodule_node_insert(Node $node) {
  $node->setTitle('New entity ' . $node->id())->save();
}

```

However, If you what you really want is to add a unique title to all nodes that are missing one, I would suggest the following:

```
mymodule_node_create(Node $node) {
  if (empty($node->label()) {
    $node->setTitle('New node ' . $node->uuid());
  }
}

```

The code above will work because the `uuid` field always has a value.
> 1 votes

# Answer
I needed to do something similar - this worked for me:

```
I needed to do something similar - this worked for me:

function your_module_node_insert($node) {
  if ($node->getType() == 'your_node') { //$node->type did not seem to work
        $node->setTitle('New entity ' . $node->id()); // to update title with node id
        $node->field_test = 'Id' . $node->id();  //to update a text field with node id
        $node->save();
  }
}

```
> 0 votes

---
Tags: 8, hooks
---


# Question
Title: How do I get the entity ID when inserting a new node?
How do I get the ID of the inserted entity?

I am trying to use `hook_ENTITY_TYPE_presave()` and `hook_ENTITY_TYPE_insert()`, but in neither of those I can get the entity ID.

In `hook_ENTITY_TYPE_presave()`, I used the following code.

```
 if ($entity->isNew()) {
    print $entity->id();
 }

```

# Answer
> 6 votes
The ID isn't available in `hook_ENTITY_TYPE_presave()` (*pre* meaning *before*, as in not saved so the database hasn't assigned it an ID yet), but is definitely available in `hook_ENTITY_TYPE_insert()`.

This will work, for example:

```
function MODULE_node_insert(NodeInterface $node) {
  // No need to check `isNew()`; if it's in an insert hook, it's new.
  $nid = $node->id();
}

```

# Answer
> 0 votes
I needed to do something similar - this worked for me:

```
function your_module_node_insert($node) {
  if ($node->getType() == 'your_node') {
        $node->setTitle('New entity ' . $node->id()); // to update title with node id
        $node->field_test = 'Id' . $node->id();  // or, to update a text field with node id
        $node->save();
  }
}

```

---
Tags: 8, entities, hooks
---