Drupal 9 module squeleton

Info file

In /modules/k4.info.yml

name: k4
description: k4 module.
package: AAA
type: module
core_version_requirement: ^8 || ^9

Routing file

In /modules/k4.routing.yml

k4.listprojects:
  path: '/k4/list_projects'
  defaults:
    _controller: '\Drupal\k4\Controller\k4ListProjectController::app'
    _title: ''
  requirements:
    _permission: 'access content'

libraries file

In /modules/k4.libraries.yml

k4:
  version: 1.x
  css:
    theme:
      k4-app-theme.css: {}
      #css/ezka-extend.css: {}
      css/bootstrap-multiselect.css: {}
      css/font-awesome.min.css: {}
      css/k3_bootstrap_theme.css: {}
      css/ezka-extend.css: {}
  js:
    js/bootstrap-multiselect.js: {}
    js/hummingbird-treeview.js: {}
    js/bootstrap-toggle.min.js: {}
    k4.js: {}
  dependencies:
    - core/jquery # required dependencies.
    #- core/jquery.ui.tabs
    - core/drupalSettings

module file

In /modules/k4.module

 [
      'variables' => ['test_var' => NULL,
                      'variable1'=> NULL,
                      'variable2'=> NUL],
    ],
    'k4_app2_template' => [
      'variables' => array('fox' => array()),
    ],
  ];
}

template file

In /modules/templates/k4-app-template.html.twig

{# k4/templates/k4-app-template.html.twig #}
{{ attach_library('k4/k4') }}

pillars
{{ pillars_select|raw }}

services declaration file

In /modules/k4.services.yml

services:
  k4.k4service:
    class: Drupal\k4\Services\DbAccessService
    arguments: ['@database']

service file

In /modules/k4/src/Services/DbAccessService.php

database = $connection;
  }

  public function test() {
    $table = TABLE_DATAS;
    $sql_query = 'SELECT *** FROM `'.$table.'` t';
    return $this->database->query($sql_query)->fetchAll();
  }

  /*
  * k4_first
  */
  public function k4_first($myParam1, $myParam2) {
    $xx = $this->drupalise();
    return $xx;
  }

  /**
   * Returns list of nids from node table.
   */
  public function drupalise () {
      $query = $this->database->query( "SELECT *** WHERE Year = :Year", array(':Year' => '2020'));
      $k = 0;
      foreach ($query as $record) {
        $k = $k+ $record->***;
      }
      return $k;
  }

  public function k4_get_cached_infos_form($filter = '') {
  	$table = TABLE_DATAS; //'tossddatas_29_11_19'; //variable_get('tossd_table', 'tossddatas_29_11_19');
    $cid = 'k4_some string';

    if ($item = \Drupal::cache()->get($cid)) {
      $datas = $item->data;
      if(in_array($filter,array_keys($datas))) return $datas[$filter];
      return $datas;
    }

  		$my_data = array();

  		/* pillars */
  		$my_data['pillars']["1"] = '***';
  		$my_data['pillars']["2"] = '***';

  		/* recipients */
  		$recipients = array();
	    $sql_recipients = 'SELECT DISTINCT *** FROM `'.$table.'` ORDER BY *** ASC';
        $result_recipients = $this->database->query($sql_recipients);


  		foreach ($result_recipients as $record) {
  		  if($record->*** !== '' && $record->*** !== '') {
  			$recipients[] = array('***' => $record->***,
  			                      'regionnamee' => $record->***,
  								  'region' => $record->***);
  		  }
  		}
  		$my_data['recipients'] = $recipients;

  		
      \Drupal::cache()->set($cid, $my_data, Cache::PERMANENT);

      if(in_array($filter,array_keys($my_data))) return $my_data[$filter];
      return $my_data;
  }
}

the controller file

In /modules/k4/src/Controller/k4ListProjectController.php

 $this->t('ProjectTitle'), 'field' => 'ProjectTitle', 'sort' => 'asc'),
      array('data' => $this->t('sdgcode'), 'field' => 'sdgcode'),
    );

    $db = \Drupal::database();
    $query = $db->select('***','c');
    $query->fields('c', array('columns1', 'columns2'));
    // The actual action of sorting the rows is here.
    $table_sort = $query->extend('Drupal\Core\Database\Query\TableSortExtender')
                        ->orderByHeader($header);
    // Limit the rows to 20 for each page.
    $pager = $table_sort->extend('Drupal\Core\Database\Query\PagerSelectExtender')
                        ->limit(20);
    $result = $pager->execute();

    // Populate the rows.
    $rows = array();
    foreach($result as $row) {
      $rows[] = array('data' => array(
        'ProjectTitle' => $row->columns1,
        'field' => $row->columns1, // This hardcoded [BLOB] is just for display purpose only.
      ));
    }

    // The table description.
    $build = array(
      '#markup' => t('List of All records')
    );

    // Generate the table.
    $build['config_table'] = array(
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    );

    // Finally add the pager.
    $build['pager'] = array(
      '#type' => 'pager'
    );

    return $build;
  }
}

a helper class file

In /modules/k4/src/Helper.php

k4_get_m49menu();
    $out = '';
    $out .= '
    ***';

   return $out;
  }

  public function k4_get_m49menu() {
      $items = \Drupal::service('k4.k4service')->k4_get_m49_array();
      $cache = \Drupal::service('k4.k4service')->k4_get_cached_infos_form();

      $pillars_cached = $cache['pillars'];
      $recipients_cached = $cache['***'];

      foreach ($recipients_cached as $record) {
        $recipients_ids_indb[$record['recipientcode']] = $record['recipientcode'];
      }


      $menu = $this->k4_buildNestedItems($items, $parentId = "-1");
      $m49filter_html = $menu;
      return $m49filter_html;
  }

  public function k4_buildNestedItems($items, $parentId = "-1", $wrapperTag = 'ul', $itemTag = 'li') {
      // Parent items control
      $isParentItem = false;
      $ul_attr = false;
      foreach ($items as $item) {
          if ($item['parent_id'] === $parentId) {
              $isParentItem = true;
              $ul_attr = $item['ul_attr'];
              break;
          }
      }

      $html = "";
      $html .= "";
      }
      return $html;
  }

}

another controller file if needed

In /modules//k4/src/Controller/k4DefaultController.php

test();
    $TossdPillar = array_column($test, 'TossdPillar');
    $sum_disbursements = ***;
    $sum_amountmobilised = ***;
    $testx = array($TossdPillar,$sum_disbursements,$sum_amountmobilised);


          $cache = \Drupal::service('k4.k4service')->k4_get_cached_infos_form();

          $pillars_cached = $cache['pillars'];
          $recipients_cached = $cache['recipients'];
          $sectors_cached = $cache['sectors'];
          $SDGFocuss_cached = $cache['sdg_goals'];
          $years_cached = $cache['years'];

            $pillars_infos = array();
              $pillars = '';
              ...
          $helper = new Helper();
          $modaldiv = '';
          $modaldiv .= $helper->k4_get_modal_div_m49();

             return [
                '#theme' => 'k4_app_template',
                '#pillars_select' => $pillars,
                '#countries_select' => $recip,
                '#sectors_select' => $sector,
                '#year_select' => $year,
                '#test_var' => '',
                '#test' => $testx,
                '#cache' => ['max-age' => 0,],
              ];

  }

  public function test() {
    $resp = \Drupal::service('k4.k4service')->test();
    $test =  new JsonResponse($resp);
    return $test;
  }
  public function usertest(User $user) {
     return [
      '#type' => 'markup',
      '#markup' => 'uid => '.$user->id() . ' / '.$user->get('name')->value,
    ];
  }
}