DRUPAL 8 conditional hook_theme, hook_theme multiple templates, using multiple custom pages in drupal 8 module

If you need to use multiple custom templates in your drupal 8 module, you can return array with multiple keys in your hook_theme(), like this:

function cr_theme()
{  
  return [
    'product-page' => [
      'variables' => [
        'product' => null
      ],
      'template' => 'product-page'
    ],
    'size-selector-page' => [
      'variables' => [
        'form' => null,
        'base_url' => null,
        'products' => null
      ],
      'template' => 'size-selector-page'
    ]
  ];
}

Drupal 8 REDIRECT FROM CONTROLLER

Here is example of how you can redirect from your controller:

use Symfony\Component\HttpFoundation\RedirectResponse;

// ...

return new RedirectResponse(\Drupal::url('cr.sizeselector', $routeParams));

where ‘cr.sizeselector’ is your route name from yourmodulename.routing.yml config
and $routeParams is optional param where you can pass required params

if you want to redirect to internal node (like basic page), here is an example of how to redirect to ‘node/123?foo=bar#baz’:

$routeName = 'entity.node.canonical';
$routeParameters = ['node' => 1]; // id of your node
$options = [
	'query' => ['foo' => 'bar'],
	'fragment' => 'baz',
];
$url = \Drupal::url($routeName, $routeParameters, $options);
return new RedirectResponse($url);

DRUPAL 8 GET THUMBNAIL, IMAGE STYLE, DRUPAL 8 TWIG THUMBNAIL, DRUPAL 8 TWIG IMAGE STYLE

Want to become a great PHP 7 developer? Consider our 21 hour PHP 7 course for beginners and skilled developers. This is the most advanced, in-depth PHP course you can find! More details here: Learn PHP 5 & 7 This Way to Rise Above & Beyond Competition!

The problem is that you have created image field programmatically for your custom entity. Now you can upload your image, but it’s size is full. You want to get thumbnail where needed, or any other style (go to Administration -> Configuration -> Media to see all styles and their machine names). Here is how to do it programmatically:

$imageUrl = null;
if (isset($product->image->referencedEntities()[0])) { // if you have added image
	$uri = $product->image->referencedEntities()[0]->getFileUri(); // get it's uri
	$imageUrl = ImageStyle::load('thumbnail')->buildUrl($uri); // now get url to image style you want
}

Drupal 8 ATTACH CUSTOM CSS AND/OR JS TO CUSTOM/SPECIFIC PAGE ONLY

Let’s say
– your module name is `cr`
– and your theme name is `crtheme`
– and your assets library name is `custom-select`
then in your `cr.module` file:

function cr_preprocess_page(&$variables) {
	// we check current route. If it is our custom page's route, then we attach our custom library assets
    $routeName = \Drupal::request()->get(Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_NAME);
    if ($routeName == 'cr.sizeselector') {
        $variables['#attached']['library'][] = 'crtheme/custom-select';
    }
}

and in your theme’s libraries `crtheme.libraries.yml` file:

custom-select:
  version: 1.x
  css:
    theme:
      custom-select/css/styles.css: {}
  js:
    custom-select/js/jquery.customSelect.js: {}      
    custom-select/js/script.js: {}      
  dependencies:
    - core/jquery

* in the example above it will expect styles.css file to be in /themes/custom/crtheme/custom-select/css/styles.css file

Drupal 8 REDIRECT WHEN FORM SUBMIT, DRUPAL 8 REDIRECT FROM FORM, DRUPAL 8 form redirect, drupal 8 form redirect to external url

In Drupal 7 you could redirect from form submit function like this:

$addon = '20.3mm/17.8mm';
drupal_goto($base_url . '/size-selector/' . $addon);

In Drupal 8 drupal_goto() is deprecated + as far as my investigation shows you can’t return instance of RedirectResponse class like this:

return new RedirectResponse(\Drupal::url('cr.sizeselector', $routeParams)); (which is common sense to use as replacement for drupal_goto()). Instead you must use $form_state to set redirect.

This is what you can do to redirect:
In Drupal 8 drupal_goto() is deprecated + as far as my investigation shows you can’t return instance of RedirectResponse class like this:

$form_state->setRedirect('cr.sizeselector', $routeParams);

And here is a route example:

cr.sizeselector:
  path: '/size-selector/{outSize}/{inSize}'
  defaults:
    _controller: '\Drupal\cr\Controller\CRController::sizeSelector'
    _title: 'Size Selector'
    outSize: '0.0mm'
    inSize: '0.0mm'
  requirements:
    _permission: 'access content'

If you want to redirect to external url, then use this:

$form_state->setRedirectUrl(Url::fromUri('https://google.com'));

If you want to redirect to internal node (like basic page), here is an example of how to redirect to ‘node/123?foo=bar#baz’:

$form_state->setRedirect(
  'entity.node.canonical',
  ['node' => 123],
  [
    'query' => [
      'foo' => 'bar',
    ],
    'fragment' => 'baz',
  ]
);

Drupal 8 USE CUSTOM TWIG TEMPLATE IN CONTROLLER

– Controller example (\modules\custom\cr\src\Controller\CRController.php):
* full example (+ how to attach css & set variable) here: https://gist.github.com/jmolivas/d29065493a91f16f35b2

<?php

/**
 * @file
 * Contains \Drupal\demo\Controller\DemoController.
 */

namespace Drupal\cr\Controller;

use Drupal\Core\Controller\ControllerBase;

class CRController extends ControllerBase
{
    public function sizeSelector()
    {
        return [
            '#theme' => 'size-selector-page' // make sure it is exacly like array key `$theme['size-selector-page']`
        ];
    }
}

– In your theme, for example \themes\custom\crtheme\crtheme.theme:
* (or you can put your hook_theme function to module, for example if module name is cr, then put it to modules\custom\cr\cr.module and name your function `cr_theme`)

<?php

function crtheme_theme()
{    
    $theme['size-selector-page'] = [
        'template' => 'size-selector-page' // it will look for size-selector-page.html.twig
    ];

    return $theme;
}

– actual twig file example \themes\custom\crtheme\templates\size-selector-page.html.twig:
* (you can also put template to modules\custom\cr\templates\size-selector-page.html.twig if you used cr_theme in previous step,
but keep in mind that if you have same template-file name in both theme and module `template` folders,
then template which is located in `crtheme\templates\size-selector-page.html.twig` will have more priority and IT will be loaded, not `cr\templates\size-selector-page.html.twig`)

<div>
    <h1>Test</h1>
</div>

Drupal 8 CREATING MODULE

Let’s create a demo module:

– create modules\demo folder
– create demo.info.yml inside that folder
– put minimally required content:

name: Drupal 8 Demo module
description: 'Demo module for Drupal 8 alpha11'
type: module
core: 8.x

– And that’s it, one file. You can now navigate to the Extend page, find the Demo module and enable it.
– create a routing file for our module called demo.routing.yml
– Inside this file, we can have the following (simple) route definition:

demo.demo:
  path: '/demo'
  defaults:
    _controller: '\Drupal\demo\Controller\DemoController::demo'
    _title: 'Demo'
  requirements:
    _permission: 'access content'

*

– The first line marks the beginning of a new route called demo for the module demo (the first is the module name and the second the route name).
– Under path, we specify the path we want this route to register.
– Under defaults, we have two things: the default page title (_title) and the _content which references a method on the DemoController class.
– Under requirements, we specify the permission the accessing user needs to have to be able to view the page.

– Now, let’s create our first controller called DemoController that will have a method named demo() getting called when a user requests this page.
– Inside the module directory, create a folder called src/ and one called Controller/ inside of it.
* This will be the place to store the controller classes.
– Go ahead and create the first one: DemoController.php

<?php
/**
 * @file
 * Contains \Drupal\demo\Controller\DemoController.
 */
 
namespace Drupal\demo\Controller;
 
/**
 * DemoController.
 */
class DemoController {
  /**
   * Generates an example page.
   */
  public function demo() {
    return array(
      '#markup' => t('Hello World!'),
    );
  }     
}

* This is the simplest and minimum we need to do in order to get something to display on the page.
– All we have to do now is clear the caches and navigate to http://example.com/demo and we should see a Drupal page with Hello World printed on it.
* How to create a menu link that shows up under the Structure menu of the administration?
– create a file called demo.links.menu in the root of our module

demo.demo:
  title: Demo Link
  description: 'This is a demo link'
  parent: system.admin_structure
  route_name: demo.demo

Drupal 8 MENU CREATION (EN, RU etc.)

* (you need menu per language, so for EN & RU you will need English menu and Russian menu)

– EN:

– go to Manage -> Structure -> Menus
– press “+ Add menu”
– enter title, select menu language: English
– press “Save”
– now click “+ Add link”
– give menu item a title in english & select link
– fill other needed options
– click “Save”
– add other links you’d like to add
– click “Save” again to save menu

– RU:

– use EN as analogy to add RU menu

– to add EN menu to block:

– Manage -> Structure -> Block layout
– add EN menu to (for example) Sidebar first (check out “Place blocks” section)
– in “Configure block” window check “English” in “Language selection” section
– set region
– set other needed options
– click “Save block”