How to create Magnto 2 module 

#Purpose of a module
The purpose of a module is to provide specific product features by implementing new functionality or extending the functionality of other modules. Each module is designed to function independently, so the inclusion or exclusion of a particular module does not typically affect the functionality of other modules.

#Create a module folder for Magento 2 modules
Module name has two parts:  
1. vendor name it could be a Company name[Karabiner] or person name[Moaaz].
2. module name it usually describes module purpose like [Shipping].
  **vendor name and module name should be upper camel case.**
        
Our `VENDOR_NAME` will be `Karabiner` and `MODULE_NAME` will be `HelloMagneto2`

The codebase of your custom module will be in `[MAGENTO_DIRECTORY]/app/code/[VENDOR_NAME]/[MODULE_NAME]`
folder name will be [MAGENTO_FOLDER]/app/code/Karabiner/HelloMagneto2`
*MAGENTO_DIRECTORY the location of magento2 on your environment.

#Declare the module by module.xml
We need to create a configuration in module etc directory. Magento 2 will use it to recognize the module’s name and module’s version
`app/code/[VENDOR_NAME]/[MODULE_NAME]/etc/module.xml`
Add this content to declare module name is `HelloMangento2` and version `0.0.1`

```xml:app/code/Karabiner/HelloMagento2/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Karabiner_HelloMagento2" setup_version="0.0.1" />
</config>
```

In case your module depends on another module 
you can specify a load order in your component’s module.xml file using the `<sequence>` tag to ensure that needed files from other Modules are already loaded when your Module loads.

```xml:app/code/Karabiner/HelloMagento2/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Karabiner_HelloMagento2" setup_version="0.0.1" >
       <sequence>
            <!-- Karabiner_HelloMagento2 is dependent on Vendor_ModuleA: -->
            <module name="Vendor_ModuleA" />
            <!-- you can add more than one module-->
        </sequence>
    </module>
</config>
```
#Register the module by `registration.php`

Each Module must have a file called `registration.php` in its root directory. `registration.php` is the entry point of a module 

```php:app/code/Karabiner/HelloMagento2/registration.php
<?php
use Magento\Framework\Component\ComponentRegistrar;
$registrar = new ComponentRegistrar();

if ($registrar->getPath(ComponentRegistrar::MODULE, "Karabiner_HelloMagento2") === null) {
    ComponentRegistrar::register(ComponentRegistrar::MODULE, "Karabiner_HelloMagento2", __DIR__);
}

```

Structure of the Module folder should be like this :

```bash:app/code/Karabiner/
└── HelloMagento2
    ├── etc
    │   └── module.xml
    └── registration.php
```

#Enable, Install the module
We can install the module through the command line. 
Please open your terminal and use these commands

###View disabled modules:
```bash:MAGENTO_DIRECTORY
cd [MAGENTO_DIRECTORY]
php bin/magento module:status
==========output==========
List of enabled modules:
....
List of disabled modules:
Karabiner_HelloMagento2 <- not enable yet
```

###Enable module:
```bash:MAGENTO_DIRECTORY
cd [MAGENTO_DIRECTORY]
php bin/magento module:enable Karabiner_HelloMagento2
==========output==========
The following modules have been enabled:
- Karabiner_HelloMagento2
```

###Setup module:
after enabling module we have to set up it.

```bash:MAGENTO_DIRECTORY
cd [MAGENTO_DIRECTORY]
php bin/magento setup:upgrade
```

###Disable module:

```bash:MAGENTO_DIRECTORY
cd [MAGENTO_DIRECTORY]
php bin/magento module:disable Karabiner_HelloMagento2
==========output==========
The following modules have been disabled:
- Karabiner_HelloMagento2
Cache cleared successfully.
```

#Create a route for Module

Magento 2 use this format url:
http://[magento_url]/[frontName]/[controller_name]/[action_name]

Create a `routers.xml` file:
`app/code/Karabiner/HelloMagento2/etc/frontend/routes.xml`
Add this content:

```xml:app/code/Karabiner/HelloMagento2/etc/frontend/routes.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard"> <!-- standard or admin -->
    <route id="HelloMagento2" frontName="custom_router_name">
        <module name="Karabiner_HelloMagento2" />
    </route>
</router>
</config>
```
lets explain `routes.xml`config
1. `router` tag
    **id** `standard` means this router will add into frontend router
        `admin` mean this router will add into admin router 
2. `route` tag
    - **frontName** the name will be after URL.
     if you add new route could `topic` your forntName will be `custom_router_name` and URL will be `http://<magento_url>/custom_router_name/`
    - **id** specifies the unique node id for this route in Magento, which is also the first segment of its associated **layout** handle XML filename (routeId_controller_action.xml).
    
Example: http://<magento_url>/custom_router_name/index/index
So we need init router name for the module before creating any controllers and actions in the future.


#Create a controller and action
we will create a URL for displaying in your browser: “Hello Form karabiner Magento 2 module something action”.

Create an action file:
`app/code/Karabiner/HelloMagento2/Controller/Something/Index.php`
Add the content:

the namespace should be like this 
`/VENDOR_NAME/MODULE_NAME\Controller\[Controller_Class]`
`/Karabiner/HelloMagento2\Controller\Something`

```php:app/code/Karabiner/HelloMagento2/Controller/Something/Index.php
<?php
namespace /Karabiner/HelloMagento2\Controller\Something;

class Index extends \Magento\Framework\App\Action\Action
{
  public function __construct(
\Magento\Framework\App\Action\Context $context)
  {
    return parent::__construct($context);
  }

  public function execute()
  {
    echo 'Hello Form karabiner magento 2 module something action'; 
    exit;
  }
}
```

```bash:app/code/Karabiner/
app/code/Karabiner/
└── HelloMagento2
    ├── Controller
    │   ├── Index #http://<magento_url>/custom_router_name/index
    │   │   ├── Index.php #http://<magento_url>/custom_router_name/index/index
    │   │   └── View.php #http://<magento_url>/custom_router_name/index/view
    │   └── Something 
    │       └── Index.php #http://<magento_url>/custom_router_name/somethhing/index
    ├── etc
    │   ├── frontend
    │   │   └── routes.xml
    │   └── module.xml
    └── registration.php
```

After adding new route we should clear cache

```bash:MAGENTO_DIRECTORY
bin/magento cache:clean
==========output==========
Cleaned cache types:
config
layout
block_html
collections
reflection
db_ddl
compiled_config
eav
customer_notification
config_integration
config_integration_api
google_product
full_page
config_webservice
translate
vertex
```

![route-output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275433/ab2ecf18-0500-5d29-c0a0-4bc518313026.png)