Podcast #128: We chat with Kent C Dodds about why he loves React and discuss what life was like in the dark days before Git. Listen now.
19

There are 3 questions here: How to create a controller? How to create a service? How to use services in a controller? 1. Create a controller 1.1 Add a controller class - you did it. For others see Drupal documentation 1.2 Add a routing file - it looks like this is missing in your code: my_module.routing.yml my_module.my_route_name: path: '/my/path' ...


12

There are some examples on drupal.org of adding a pager to the page, if you want to use the one that core uses: https://api.drupal.org/api/drupal/core%21includes%21pager.inc/function/pager_default_initialize/8.2.x The second example should work for you: $page = pager_find_page(); $num_per_page = \Drupal::config('mymodule.settings')->get('...


8

I think you want to return a render array, instead of markup. Because the from needs to stay as a render array, your best bet it to bring your content content to the same format instead of the other way. In your example: public function processSingle($nid) { $build = []; $build['heading'] = [ '#type' => 'markup', '#markup' => '<div ...


7

To customize your Breadcrumbs you need to take full control of the Breadcrumb for that particular route with your own Breadcrumb Builder service. To do this, you need to create an entry in your module/profile services file: e.g., mymodule/mymodule.services.yml services: mymodule.breadcrumb: class: Drupal\mymodule\MyModuleBreadcrumbBuilder tags: ...


7

Instead of custom one-off checks, you should use the validation API. Before saving, call $user->validate(). That tells you if anything with the values isn't OK, there is also a limit on what characters are allowed for the username/email and so on. See https://www.drupal.org/docs/8/api/entity-validation-api/entity-validation-api-overview.


6

You need to let Drupal know about the theme, and then you can leverage it in the controller code. The template needs to be in the folder my_module/templates. my_module.module function my_module_theme() { $theme['template_name'] = [ 'render element' => 'build', 'template' => 'template_file_name',//This is only needed if you need a different ...


6

Can you give more details ? For example for an aggregator RSS : In your test.routing.yml : test.rss: path: '/rss' defaults: _title: 'rss' _controller: '\Drupal\test\Controller\RssController::content' requirements: _access_test: 'test' And in your controller : <?php namespace Drupal\test\Controller; use Drupal\Core\Controller\...


6

You can't inject Drupal\Core\Database\Database, it's a container of static functions, constants, & variables for core database functions. If you'd like to inject the Connection object, that is be possible, and is more like something you want (unless you have scenario where setting.php is dynamic an all possible values of $schema can't be known). You ...


6

I guess you can use a simple EntityQuery. $ids = \Drupal::entityQuery('user') ->condition('name', 'USERNAME_TO_CHECK') ->range(0, 1) ->execute(); if(!empty($ids)){ //then this name already exists }


5

As commented on another answer, the answer here is probably, you can't. The database API isn't fully converted to use services. I tried to do it for quite some time, in https://www.drupal.org/node/1811730, but didn't succeed and neither did others. So, for now, you need to use the static methods. The best you can do is wrap it in a method or another ...


5

The controller from your question runs without exception: public function demo() { $build = array( '#cache' => array( 'contexts' => ['ip'], ), ); return (new CacheableJsonResponse(['test'], 200))->addCacheableDependency(CacheableMetadata::createFromRenderArray($build)); } Result: ["test"] To produce the exception you need a ...


5

You might want to try return array( '#theme' => 'ctr', '#myvar' => 'myvalue', ); And then define a hook_theme. /** * Implements hook_theme(). */ function ctr_theme($existing, $type, $theme, $path) { $variables = array( 'ctr' => array( 'template' => 'cntr', 'variables' => array( 'myvar' => 'defaultvalue', ...


5

Yes, when rendering email data you have to take care that you don't bubble up metadata to the render context of the main response. There is a third option, and in most cases the best option: The method Renderer::renderPlain, which not only discards bubbleable metadata, but also makes sure your email doesn't contain leftover placeholders: Renders final ...


4

Funny how those tutorials did not mention Drupal behaviors, which will trigger once the page is loaded. This is a good tutorial on them (Drupal 7, but same principles apply). Basically all you should do is call your callback function from a behavior to get the same effect as jQuery's document ready callbacks. Drupal.behaviors.myModule = { attach: ...


4

You have to use the power of render arrays. For your example, I would use something like that : $form_class = 'Drupal\xyz\Forms\XyzActionsForm'; $form = [ 'form' => $this->formBuilder->getForm($form_class, $parameter), 'custom' => [ '#type' => 'container', 'inside' => [ '#markup' => 'custom html', // Or use the power ...


4

Controllers should return a render array (or a custom response), you almost never need to render anything yourself outside a template. Just replace this: $build = $view_builder->view($entity); $render_array = render($build); $output['entity'] = $render_array; with: $output = $view_builder->view($entity); to return a render array and let Twig ...


4

The language is detected and the prefix removed before routing. So you have a static route without parameter and in the controller you can get the prefix from the language manager: $langcode = $this->languageManager()->getCurrentLanguage()->getId();


4

Of course as soon as I posted this I figured an answer. This looks a little ugly, but I guess this is the way to go: public function content() { $nodes = $this->getStudents(); foreach ($nodes as $node) { $student = \Drupal::entityTypeManager() ->getViewBuilder('node') ->view($node); $students[] = render($student); } ...


3

You'll need to alter the entity.node.canonical route to do this. You can do this via a RouteSubscriber::alterRoutes() in a custom module to have the route driven by your custom logic. In src/Routing/RouteSubscriber.php: namespace Drupal\mymodule\Routing; use Drupal\Core\Routing\RouteSubscriberBase; use Symfony\Component\Routing\RouteCollection; /** * ...


3

As Eyal mentioned, you can pass the variables from your module to jQuery like this: mymodule.module function mymodule_page_attachments(array &$attachments) { $attachments['#attached']['library'][] = 'mymodule/auto'; $attachments['#attached']['drupalSettings']['cool'] = 'hello world'; } } mymodule.libraries.yml auto: version: 1.0 js:...


3

OK, I'm going to be that guy. Do yourself a favour and set up Xdebug, hacks like var_dump() or var_export() are very bad practice and sooner or later you will forget to remove some of those statements and it will end up in production. Also it takes one single click to set up a breakpoint, as opposed to writing a var_dump() or var_export() statement. Not to ...


3

In a route callback like a controller you can pull the request with a typed function parameter: use Symfony\Component\HttpFoundation\Request; public function index(Request $request) { $query_parameters = $request->query->all(); }


3

This is a classic case of trying to do something in the non-Drupal way -- conceptually, defining a custom route for your home page route makes sense, and it's possible in other frameworks, but Drupal has a different way of doing things that makes this approach completely unintuitive. Here's how to do it: Define your route as something other than '/' (i.e. '...


3

Swiftmailer only sends mails, it doesn't let you create HTML / plaintext content for emails. I think that you want to use a module like mimemail to do this. I came across this article that describes how to style mails send out using mimemail. Theming HTML Mail sent through Mime Mail This guide is made for Drupal 7, but the module has been made for Drupal ...


2

You can completely take over the printed page if your return value is an extension of Symfony's Response class. Here your return value is a render array so Drupal assumes it is to be rendered in a normal HTML page. This complex looking diagram shows the flow of request to response: You can read more about the diagram here: https://www.drupal.org/...


2

This is exactly the case when you define a Service: In your controller you call the service with Dependency injection In your module you call the static \Drupal::service('..')


2

That is behavior Drupal 8 has for the #markup property, as described in Render API overview. It is different from the behavior Drupal 7 had; if you are converting code from Drupal 7, you need to change that part of the code accordingly. #markup: Specifies that the array provides HTML markup directly. Unless the markup is very simple, such as an ...


2

One thing that you can do is the same as the entity view builder is doing, use a #pre_render callback. If you look at \Drupal\Core\Entity\EntityViewBuilder::viewMultiple(), you can see it doesn't really do anything except prepare the render array and add a #pre_render callback to the whole thing. The reason for that is that the pre_render callback will ...


2

Kevin's answer caused my Twig template's <?xml ...> tag to be commented out. I had to add to make the page render it as XML. $response->headers->set('Content-Type', 'text/xml'); Full example for my module named custom. custom.routing # My XML controller custom.my_xml_feed: path: '/xml-feed' defaults: _controller: '\Drupal\custom\...


2

The hooks/functions you shown for the .module file can be removed, since Drupal 8 doesn't use hook_menu(); therefore, Drupal will not use the littlurl_forward() function defined from the module. The code in the Controller.php file needs to be rewritten for Drupal 8, since: It should not access $_GET['q'] Instead of drupal_goto(), it should use the redirect(...


Only top voted, non community-wiki answers of a minimum length are eligible