Let's make a Composer packages - chapter.1
Published: 2020-12-10 00:27:44

## Introduction
I'm sure no one is using PHP and hasn't taken care of Composer, but it's an article for people who want to publish their own packages, not just the ones that are published.

I hope it helps people who want to do OSS activities but are wondering what the specific steps are.: Blush:
(* I haven't released the package so far, so I'd be happy if you could give me some advice.)

[temori/distancexport] (https://packagist.org/packages/temori/distancexport)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/r59mnme6e25gge3zl9pz.png)
The above package edits the migration destination column and migration source column in spreadsheet format when data needs to be migrated between DBs or data with different table names or column names is migrated. I created it because I thought it would be convenient if possible.

## final goals
We will publish it to [packagist] (https://packagist.org/) and aim to install the package with `composer require [package name]`.

## Environment
The development environment is always prepared with `docker`.
I think you can develop it in your favorite environment.

By the way, I am developing in the environment of the following repository.
[temori1919/docker-lamp] (https://github.com/temori1919/docker-lamp)

## Project creation
First, create a directory for packages.
At a minimum, I think the following directory structure is fine.

I have created directories under the `package` directory with` vendor name` and `package name`, but I think it doesn't matter if the root directory is the package name.

```sh
package
└── vendorname
    └── Package name
        ├── LICENSE
        ├── README.md # Since it describes the outline of the package, you can create it after it is completed.
        ├── composer.json # This file is generated by the composer command described later.
        ├── .gitignore # Create any files you want to exclude from git
        ├── src # Directory to store the package source
        └── tests # Directory to store test code (OK without it)
```

After creating the directory, create `composer.json` with the` composer init` command.

It's the usual **that file** that defines an external package.

```sh
$ cd path/to/package/vendorname/packagename

Execute the # command to start creating the file interactively
$ composer init
                                            
  Welcome to the Composer config generator
                                            
This command will guide you through creating your composer.json config.

#Enter the vendorname/package name and enter (what you enter here will be the vendorname/package name when you publish it externally)
Package name (<vendor>/<name>) [some/mypackage]:
# Describes the outline of the package, but it can be blank. (It will be displayed in the outline of packagist described later)
Description []:
#Producer, it's okay to skip with n
Author [some <some@address.com>, n to skip]:
#Minimum stability, Enter as it is is no problem
# This is the place to describe the stability of the package to be created.
# By default, "stable" can only be used with "dev", "alpha", "beta", "RC", and "stable".
Minimum Stability []:
#Package type, just enter OK
#The default is "library" (the type installed under vendor), and there are also "project", "metapackage", and "composer-plugin".
Package Type (e.g. library, project, metapackage, composer-plugin) []:
#License type (Please specify the license that suits your purpose)
License []:
# Find the package you plan to use
# I don't plan to use it for the time being, so just enter
Would you like to define your dependencies (require) interactively [yes]?
Search for a package:
#This is the above dev package
# If you plan to use it, you can search here, but you can add it later, so enter it for the time being.
Would you like to define your dev dependencies (require-dev) interactively [yes]?
Search for a package:

It will be a confirmation of the contents described in the # command
# If there is no problem, Enter (you can also modify the file directly later)
{
    "name": "some/mypackage",
    "license": "MIT",
    "require": {}
}

Do you confirm generation [yes]?
```

I think you have `composer.json` directly under the package directory.

```sh
mypackage/composer.json
```

The directory is now ready.

## Implement package processing
### Creating directories and dummy projects
Create classes and methods under the `src` directory.

When developing a package, `composer require` the package in the local directory and proceed with the development.

First, create a dummy project to install the package to be developed.
It will be in the same level as the `package` directory created earlier.

```sh
├── package
└── dummy-project
```
* There is no problem in creating a project using FW.

Go to the created project, create `composer.json` and add the following.
* If you created a project using FW, add it to the already placed `composer.json`.
```sh
cd dummy-project
```

```composer.json
    "repositories": [
        {
            "type": "path",
            "url": "../package/vendorname/packagename"
        }
    ]
```

Now with the `vendor/packagename` you specified for `composer in it`

```sh
composer require vendorname/packagename
```

Type the command and the local directory will be installed as a package.

You can change the installation destination by changing the `type` of` composer.json`. If `repositories` is not specified, the default will search for packages from [packagist] (https://packagist.org/).
It is possible to change the installation destination such as reading from a local directory with `path` and installing directly from a repository hosting service such as github with `vcs`.

See below for details.

> https://getcomposer.org/doc/05-repositories.md#types

Installing with `type` set to` path` will generate a symbolic link to the local package directory in the `vendor` directory containing the packages in the installed project.

When coding a package, if you change the package under `vendor` in the project, it will be reflected in the source of the package directory created in the same hierarchy as the project, so when using the IDE, code jump etc. will occur. It's convenient.

### Creating classes and methods

By the way, I am creating the main class with the package name.

With this package, the name and structure are as follows.

```sh
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml
├── resources
│ ├── assets
│ │ ├── css
│ │ │ ├── jexcel.css
│ │ │ └── jsuites.css
│ │ └── js
│ │ ├── jexcel.js
│ │ └── jsuites.js
│ └── views
│ └── index.php
├── src
│ ├── DataBases
│ │ ├── BaseDriver.php
│ │ ├── Connect.php
│ │ └── Drivers
│ │ ├── Mysql.php
│ │ └── Pgsql.php
│ ├── Distancexport.php
│ ├── Provider.php
│ └── Renders
│ └── AssetResponse.php
└── tests
    └── DistancexportTest.php
```

`Distancexport.php` is the class file that is the starting point of the package.

Also, the `resources` directory is created because it was necessary to draw a view for this package.

After creating the class, add the autoload setting to the package `composer.json`.

```json
{
    "name": "some / mypackage",
    "license": "MIT",
    "require": {},
    "autoload": {
        "psr-4": {
            "Some\\Mypackage\\":"src/",
            "Some\\Tests\\":"tests/"
        }
    }
}
```

This will autoload the `src` subordinate in the `Some\Mypackage` namespace.

As for `tests`, it is assumed that the test code is stored under the directory, so it will be autoloaded in the namespace of `Some\Tests`.

Also, although it is a namespace that is named when creating a class, the file cannot be read unless it is the namespace set by autoloading.

The namespace described in `composer.json` must be added to the file that describes the namespace to be implemented in the package.
(* In the above example, `Some\Mypackage\ClassName`)

If you need an external package, describe it in `require` and it will be installed when you` composer require` or `install` on the project side.

## Make a README.md
Create a README.

I mainly describe the following items.

- package name
--Badges that display versions, licenses, etc.
It's easy to understand visually, and above all, it's cool: smiley:
- Overview  
Describe the outline of the package
--If the package has a UI, gif animations and images
If you have a UI, it would be easier to understand if you had an image. It may also be the created image.
- table of contents  
Place a table of contents with links for each heading.
- Characteristic
It is a feature of the package.
--Requirements
It will be the place to describe the corresponding version etc.
--How to install
How to install the package.
Describe with a command so that you can copy and paste.
--How to use
--License

The package released this time has the following items.
https://github.com/temori1919/distancexport/blob/master/README.md

I used the following services for badges.
> [shields] (https://shields.io/)

You can easily create badges with packages published on [packegist] (https://packagist.org/).

Of course, some badges can be created even if they are not published.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o364m775ahvupic62ii2.png)

The above is the version of packagist, but if you enter the published vendor name and package name, the URL will be generated with md or html.

As for the version, it can be generated only after it is published to packagist, so I think that it will be created after publishing the package and tagging the version described later.

You can also change the style and wording of the badge.

## Create a repository on GitHub and push
Let's push the source to the repository.
Create a `LICENSE` file after pushing.

Click `Create new file` to create a new file on GitHub.
If you enter `LICENSE` in the file name, you will be able to select the license file template.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5gx1fjanu0egjyg4wi9o.png)

After that, select the license that suits your purpose and generate the file.

Specify the version with ## tag
I think that the following tag creation screen will be displayed by `tags`->`Create a new release`, so I will generate tags.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6garx2dpotojbh4761rh.png)

Specify `Tag version`.

I try to start from `v1.0.0`.
It doesn't matter with or without `v`.

composer recognizes it as a version even with `v`.

The `Target` branch is selected next to the` Tag version`, but the current latest commit of the `master` branch is the this tagged version.

If there is a title, detailed contents, etc., there is no problem even if it is not described.

## Publish to packagist
Finally, publish the GitHub repository to packagist.

If you do not have an account, please create one.
You can also log in with your GitHub account.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hzzhbnmtn3i32jnmeba5.png)

Display the page to submit the package from the `Submit` button in the header.

Enter the URL of the repository in `Repository URL` and press the Check button.

The GitHub repository and packagist are now linked.
Tag information added on GitHub will also be linked as a package version of packagist.

The `README.md` added to the repository is also reflected in the package TOP page of packagist.

## Register the packagist api token on the GitHub webhook
Register the URL of the packagist api on the GitHub webhook.

By utilizing Webhook, when you update the repository of GitHub, you will be able to automatically reflect the change on the packagist side.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ponvywv2ub0sqvoeiif9.png)

Press `Show API Token` to show the token.
Click the `the docs` link below it to see how to register your GitHub webhook.

Register WebHook on GitHub using the token that displays the URL described in the above document.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/34aeciypynnyaxtyb1tc.png)

Enter as described in the documentation.


This completes all the work involved in the release.

## Finally
If you follow the steps, I don't think publishing a package is such a high hurdle.

Next time, I will continue with the procedure to publish the Laravel package.

[Let's make a Composer packages - chapter.2 -- Laravel package] (https://dev.to/temori1919/let-s-make-a-composer-packages-chapter-2-laravel-package-2m4d)