Contents

Laravel Package Development

Required Knowledge

Composer

Composer
Composer is a tool for dependency management in PHP.

Packagist

Packagist
Packagist is the default Composer package repository.

Laravel

Laravel
Laravel is a web application framework in PHP.

GitHub

GitHub
GitHub is a code hosting platform for version control and collaboration.

Install Laravel

Note
I don’t explain how to set environment up for PHP and Composer in this post.
1
composer create-project laravel/laravel my-project

Settings for Package Development

Directory Structure

Directory Structure
<Laravel Project>/<Packages Direcotry>/<Vendor Name>/<Package Name>/src

Create a Packages Directory

1
2
cd my-project
mkdir packages

Create a Vendor Directory

1
2
cd packages
mkdir cozyfex

Create a Package Directory

1
2
cd cozyfex
mkdir my-package

Create a Source Directory

1
2
cd my-package
mkdir src

Initialize git

GitHub Initialization

  • Go to GitHub and register
  • Create a repository laravel-my-package

git Local Initialization

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# my-project/packages/cozyfex/my-package

# Init
git init

# Setting ignore
vi .gitignore

# Add remote repository, below is example for this post.
git remote add origin git@github.com:cozyfex/laravel-my-package.git

Check Sync Local and GitHub

Push to Repository
1
2
3
git add -A
git commit -m "First commit"
git push -u origin master
Check GitHub Repository
  • Go to your GitHub repository and check!

Initialize composer

Using composer

1
2
# my-project/packages/cozyfex/my-package
composer init

Using Template

1
2
# my-project/packages/cozyfex/my-package
vi composer.json

composer.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
  "name": "cozyfex/my-package",
  "description": "Laravel Package Development",
  "keywords": [
    "laravel",
    "package",
    "development"
  ],
  "license": "MIT",
  "support": {
    "issues": "https://github.com/cozyfex/laravel-my-package/issues",
    "source": "https://github.com/cozyfex/laravel-my-package"
  },
  "authors": [
    {
      "name": "Felix D.H. Kang",
      "email": "cozyfex@gmail.com"
    }
  ],
  "require": {
    "php": "^7.3|^8.0",
    "laravel/framework": "^8.0.0"
  },
  "autoload": {
    "psr-4": {
      "CozyFex\\MyPackage\\": "src/"
    }
  },
  "extra": {
    "laravel": {
      "providers": [
        "CozyFex\\MyPackage\\PackageServiceProvider"
      ]
    }
  },
  "minimum-stability": "dev"
}

Core Attributes

Note
If you want to more detail about attributes of composer.json, go to official Composer Document.
name
name
<vendor_name>/<package_name>
support
support
This is for supporting urls.
authors
authors
This is information of authors.
require
require
This is main attribute of composer.
The information is to solve dependency of a project or a library.
This package is depended laravel/framework.
autoload
autoload
This is setting for autoload the package sources.
extra
extra
This is for providing package provider to laravel.
We will create a PackageServiceProvider file in this post later.

Create a Package Sources

Create a Provider

1
2
3
# my-project
php artisan make:provider PackageServiceProvider
mv app/Providers/PackageServiceProvider.php packages/cozyfex/my-package/src/

Create Views

Create a Directory

1
2
3
4
5
6
# my-project/packages/cozyfex/my-package/src
mkdir views

cd views
# my-project/packages/cozyfex/my-package/src/views
mkdir MyPackage

Create View Files

exist_session.blade.php

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
    <title>Exist Session</title>
</head>
<body>
<p>Exist Session</p>
</body>
</html>

none_session.blade.php

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
    <title>None Session</title>
</head>
<body>
<p>None Session</p>
</body>
</html>

View Settings in Provider

my-project/packages/cozyfex/my-package/src/PackageServiceProvider.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

namespace CozyFex\MyPackage;

use Illuminate\Support\ServiceProvider;

class PackageServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        # Here!
        # The 'my-package' is a namespace.
        $this->loadViewsFrom(__DIR__.'/views', 'my-package');
    }
}

Create Controllers

Create a Directory

1
2
# my-project/packages/cozyfex/my-package/src
mkdir Controllers

Exist Session Controller

1
2
3
# my-project
php artisan make:controller -r ExistSessionController
mv app/Http/Controllers/ExistSessionController.php packages/cozyfex/my-package/src/Controllers/

ExistSessionController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php

namespace CozyFex\MyPackage\Controllers;

use Illuminate\Http\Request;

use App\Http\Controllers\Controller;

class ExistSessionController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return response()->view('my-package::MyPackage.exist_session');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     *
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

None Session Controller

1
2
3
# my-project
php artisan make:controller -r NoneSessionController
mv app/Http/Controllers/NoneSessionController.php packages/cozyfex/my-package/src/Controllers/

NoneSessionController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php

namespace CozyFex\MyPackage\Controllers;

use Illuminate\Http\Request;

use App\Http\Controllers\Controller;

class NoneSessionController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return response()->view('my-package::MyPackage.none_session');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     *
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     *
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

Create Routes

Create a routes.php

1
2
# my-project/packages/cozyfex/my-package/src
vi routes.php

routes.php

1
2
3
4
5
6
7
8
9
<?php

use Illuminate\Support\Facades\Route;

use CozyFex\MyPackage\Controllers\ExistSessionController;
use CozyFex\MyPackage\Controllers\NoneSessionController;

Route::middleware(['web', 'auth'])->resource('exist', ExistSessionController::class);
Route::middleware(['web'])->resource('none', NoneSessionController::class);
Middleware

At this time, I want to tell you about middleware.
Above the source, there are two middleware.
The names are web and auth.
The web is to access web session.(The session is starting in web middleware.)
If you don’t use web, you cannot access the session in your package.
That means, if you use only the auth middleware without the web, the auth middleware is not going to work.

If you want to know more details about Laravel middleware, go to the Official Document

Routes Settings in Provider

my-project/packages/cozyfex/my-package/src/PackageServiceProvider.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

namespace CozyFex\MyPackage;

use Illuminate\Support\ServiceProvider;

class PackageServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        $this->loadViewsFrom(__DIR__.'/views', 'my-package');
        # Here!
        $this->loadRoutesFrom(__DIR__.'/routes.php');
    }
}

Connection Laravel and Package

Register Autoload to Laravel composer.json

my-project/composer.json

Check!
"CozyFex\\MyPackage\\": "packages/cozyfex/my-package/src"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{
  "name": "laravel/laravel",
  "type": "project",
  "description": "The Laravel Framework.",
  "keywords": [
    "framework",
    "laravel"
  ],
  "license": "MIT",
  "require": {
    "php": "^7.3|^8.0",
    "fideloper/proxy": "^4.4",
    "fruitcake/laravel-cors": "^2.0",
    "guzzlehttp/guzzle": "^7.0.1",
    "laravel/framework": "^8.40",
    "laravel/tinker": "^2.5"
  },
  "require-dev": {
    "facade/ignition": "^2.5",
    "fakerphp/faker": "^1.9.1",
    "laravel/sail": "^1.0.1",
    "mockery/mockery": "^1.4.2",
    "nunomaduro/collision": "^5.0",
    "phpunit/phpunit": "^9.3.3"
  },
  "autoload": {
    "psr-4": {
      "App\\": "app/",
      "Database\\Factories\\": "database/factories/",
      "Database\\Seeders\\": "database/seeders/",
      "CozyFex\\MyPackage\\": "packages/cozyfex/my-package/src"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Tests\\": "tests/"
    }
  },
  "scripts": {
    "post-autoload-dump": [
      "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
      "@php artisan package:discover --ansi"
    ],
    "post-root-package-install": [
      "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
    ],
    "post-create-project-cmd": [
      "@php artisan key:generate --ansi"
    ]
  },
  "extra": {
    "laravel": {
      "dont-discover": []
    }
  },
  "config": {
    "optimize-autoloader": true,
    "preferred-install": "dist",
    "sort-packages": true
  },
  "minimum-stability": "dev",
  "prefer-stable": true
}

Generate Vendor Autoload

IMPORTANT!
This is very IMPORTANT!!
DON’T MISS IT!!
1
2
# my-project
composer dump-autoload

Add Provider to Laravel Providers

Provider
CozyFex\MyPackage\PackageServiceProvider::class

my-project/config/app.php

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Application Name
    |--------------------------------------------------------------------------
    |
    | This value is the name of your application. This value is used when the
    | framework needs to place the application's name in a notification or
    | any other location as required by the application or its packages.
    |
    */

    'name' => env('APP_NAME', 'Laravel'),

    /*
    |--------------------------------------------------------------------------
    | Application Environment
    |--------------------------------------------------------------------------
    |
    | This value determines the "environment" your application is currently
    | running in. This may determine how you prefer to configure various
    | services the application utilizes. Set this in your ".env" file.
    |
    */

    'env' => env('APP_ENV', 'production'),

    /*
    |--------------------------------------------------------------------------
    | Application Debug Mode
    |--------------------------------------------------------------------------
    |
    | When your application is in debug mode, detailed error messages with
    | stack traces will be shown on every error that occurs within your
    | application. If disabled, a simple generic error page is shown.
    |
    */

    'debug' => (bool) env('APP_DEBUG', false),

    /*
    |--------------------------------------------------------------------------
    | Application URL
    |--------------------------------------------------------------------------
    |
    | This URL is used by the console to properly generate URLs when using
    | the Artisan command line tool. You should set this to the root of
    | your application so that it is used when running Artisan tasks.
    |
    */

    'url' => env('APP_URL', 'http://localhost'),

    'asset_url' => env('ASSET_URL', null),

    /*
    |--------------------------------------------------------------------------
    | Application Timezone
    |--------------------------------------------------------------------------
    |
    | Here you may specify the default timezone for your application, which
    | will be used by the PHP date and date-time functions. We have gone
    | ahead and set this to a sensible default for you out of the box.
    |
    */

    'timezone' => 'UTC',

    /*
    |--------------------------------------------------------------------------
    | Application Locale Configuration
    |--------------------------------------------------------------------------
    |
    | The application locale determines the default locale that will be used
    | by the translation service provider. You are free to set this value
    | to any of the locales which will be supported by the application.
    |
    */

    'locale' => 'en',

    /*
    |--------------------------------------------------------------------------
    | Application Fallback Locale
    |--------------------------------------------------------------------------
    |
    | The fallback locale determines the locale to use when the current one
    | is not available. You may change the value to correspond to any of
    | the language folders that are provided through your application.
    |
    */

    'fallback_locale' => 'en',

    /*
    |--------------------------------------------------------------------------
    | Faker Locale
    |--------------------------------------------------------------------------
    |
    | This locale will be used by the Faker PHP library when generating fake
    | data for your database seeds. For example, this will be used to get
    | localized telephone numbers, street address information and more.
    |
    */

    'faker_locale' => 'en_US',

    /*
    |--------------------------------------------------------------------------
    | Encryption Key
    |--------------------------------------------------------------------------
    |
    | This key is used by the Illuminate encrypter service and should be set
    | to a random, 32 character string, otherwise these encrypted strings
    | will not be safe. Please do this before deploying an application!
    |
    */

    'key' => env('APP_KEY'),

    'cipher' => 'AES-256-CBC',

    /*
    |--------------------------------------------------------------------------
    | Autoloaded Service Providers
    |--------------------------------------------------------------------------
    |
    | The service providers listed here will be automatically loaded on the
    | request to your application. Feel free to add your own services to
    | this array to grant expanded functionality to your applications.
    |
    */

    'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,

        /*
         * Package Service Providers...
         */
        
        # Here!
        CozyFex\MyPackage\PackageServiceProvider::class,

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

    ],

    /*
    |--------------------------------------------------------------------------
    | Class Aliases
    |--------------------------------------------------------------------------
    |
    | This array of class aliases will be registered when this application
    | is started. However, feel free to register as many as you wish as
    | the aliases are "lazy" loaded so they don't hinder performance.
    |
    */

    'aliases' => [

        'App'          => Illuminate\Support\Facades\App::class,
        'Arr'          => Illuminate\Support\Arr::class,
        'Artisan'      => Illuminate\Support\Facades\Artisan::class,
        'Auth'         => Illuminate\Support\Facades\Auth::class,
        'Blade'        => Illuminate\Support\Facades\Blade::class,
        'Broadcast'    => Illuminate\Support\Facades\Broadcast::class,
        'Bus'          => Illuminate\Support\Facades\Bus::class,
        'Cache'        => Illuminate\Support\Facades\Cache::class,
        'Config'       => Illuminate\Support\Facades\Config::class,
        'Cookie'       => Illuminate\Support\Facades\Cookie::class,
        'Crypt'        => Illuminate\Support\Facades\Crypt::class,
        'Date'         => Illuminate\Support\Facades\Date::class,
        'DB'           => Illuminate\Support\Facades\DB::class,
        'Eloquent'     => Illuminate\Database\Eloquent\Model::class,
        'Event'        => Illuminate\Support\Facades\Event::class,
        'File'         => Illuminate\Support\Facades\File::class,
        'Gate'         => Illuminate\Support\Facades\Gate::class,
        'Hash'         => Illuminate\Support\Facades\Hash::class,
        'Http'         => Illuminate\Support\Facades\Http::class,
        'Lang'         => Illuminate\Support\Facades\Lang::class,
        'Log'          => Illuminate\Support\Facades\Log::class,
        'Mail'         => Illuminate\Support\Facades\Mail::class,
        'Notification' => Illuminate\Support\Facades\Notification::class,
        'Password'     => Illuminate\Support\Facades\Password::class,
        'Queue'        => Illuminate\Support\Facades\Queue::class,
        'Redirect'     => Illuminate\Support\Facades\Redirect::class,
        // 'Redis' => Illuminate\Support\Facades\Redis::class,
        'Request'      => Illuminate\Support\Facades\Request::class,
        'Response'     => Illuminate\Support\Facades\Response::class,
        'Route'        => Illuminate\Support\Facades\Route::class,
        'Schema'       => Illuminate\Support\Facades\Schema::class,
        'Session'      => Illuminate\Support\Facades\Session::class,
        'Storage'      => Illuminate\Support\Facades\Storage::class,
        'Str'          => Illuminate\Support\Str::class,
        'URL'          => Illuminate\Support\Facades\URL::class,
        'Validator'    => Illuminate\Support\Facades\Validator::class,
        'View'         => Illuminate\Support\Facades\View::class,

    ],

];

Interim Check

Links

Run php artisan serve

You can check below links now.

http://localhost:8000/none
This link works good.

http://localhost:8000/exist
This link is not going to work as well.
Don’t worry, it was predictable.
Because we don’t install any login process.
If you want to check all, run below commands in the project directory.
composer require laravel/breeze
php artisan breeze:install
npm install && npm run dev

Additional Features

Migration

Migration
Before into this section, make sure database connection in Laravel.

Create a migrations Directory

1
2
# my-project/packages/cozyfex/my-package/src
mkdir migrations

Generate Migration File

1
2
3
4
5
6
# my-project
php artisan make:migration --create=boards create_board
mv database/migrations/2021_05_22_080925_create_board.php packages/cozyfex/my-package/src/migrations/

# If you want to change table scheme, '--create' to '--table'
php artisan make:migration --table=boards add_feild_to_board

my-project/packages/cozyfex/my-package/src/migrations/2021_05_22_080925_create_board.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBoard extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('boards', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained();
            $table->string('author');
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('boards');
    }
}

Migrations Settings in Provider

my-project/packages/cozyfex/my-package/src/PackageServiceProvider.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

namespace CozyFex\MyPackage;

use Illuminate\Support\ServiceProvider;

class PackageServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        $this->loadViewsFrom(__DIR__.'/views', 'my-package');
        $this->loadRoutesFrom(__DIR__.'/routes.php');
        # Here!
        $this->loadMigrationsFrom(__DIR__.'/migrations');
    }
}

Model

Create a Models Directory

1
2
# my-project/packages/cozyfex/my-package/src
mkdir Models

Generate a Model

1
2
3
# my-project
php artisan make:model Board
mv app/Models/Board.php packages/cozyfex/my-package/src/Models/

my-project/packages/cozyfex/my-package/src/Models/Board.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace CozyFex\MyPackage\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

use App\Models\User as AppUser;

class Board extends Model
{
    use HasFactory;

    /**
     * @return BelongsTo
     */
    public function users(): BelongsTo
    {
        return $this->belongsTo(AppUser::class);
    }
}

Command

Create a Commands Directory

1
2
# my-project/packages/cozyfex/my-package/src
mkdir Commands

Generate a Command

1
2
3
# my-project
php artisan make:command InstallCommand
mv app/Console/Commands/InstallCommand.php packages/cozyfex/my-package/src/Commands

my-project/packages/cozyfex/my-package/src/Commands/InstallCommand.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php

namespace CozyFex\MyPackage\Commands;

use Illuminate\Console\Command;

class InstallCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'cozyfex:my-package:install';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->call('migrate');

        $this->info('[CozyFex MyPackage] was installed successfully!');

        return 0;
    }
}

Command Settings in Provider

my-project/packages/cozyfex/my-package/src/PackageServiceProvider.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php

namespace CozyFex\MyPackage;

use Illuminate\Support\ServiceProvider;

use CozyFex\MyPackage\Commands\InstallCommand;

class PackageServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        $this->loadViewsFrom(__DIR__.'/views', 'my-package');
        $this->loadRoutesFrom(__DIR__.'/routes.php');
        $this->loadMigrationsFrom(__DIR__.'/migrations');

        # Here!
        if ($this->app->runningInConsole()) {
            $this->commands([
                InstallCommand::class,
            ]);
        }
    }
}

Check Command

1
2
3
4
5
# my-project
php artisan

# Only cozyfex
php artisan | grep cozyfex

Publish PackageServiceProvider

Publish in Laravel
I don’t guarantee this package is perfect fit to your project.
Some of them want to use this package, but they also want to change a part of the package.
Reason why the Laravel provides a function for that in Provider.

my-project/packages/cozyfex/my-package/src/PackageServiceProvider.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php

namespace CozyFex\MyPackage;

use Illuminate\Support\ServiceProvider;

use CozyFex\MyPackage\Commands\InstallCommand;

class PackageServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        # Load View
        $this->loadViewsFrom(__DIR__.'/views', 'my-package');

        # Load Route
        $this->loadRoutesFrom(__DIR__.'/routes.php');

        # Load Migration
        $this->loadMigrationsFrom(__DIR__.'/migrations');

        # Here!
        # Publish View
        $this->publishes([
            __DIR__.'/views' => resource_path('views/CozyFex'),
        ]);

        # Commands
        if ($this->app->runningInConsole()) {
            $this->commands([
                InstallCommand::class,
            ]);
        }
    }
}

Laravel Publish Path Functions

resource_path
resource_path
my-project/resources
config_path
config_path
my-project/config
public_path
public_path
my-project/public
database_path
database_path
my-project/database

Publish Command

1
php artisan vendor:publish
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
Which provider or tag's files would you like to publish?:
  [0 ] Publish files from all providers and tags listed below
  [1 ] Provider: CozyFex\MyPackage\PackageServiceProvider
  [2 ] Provider: Facade\Ignition\IgnitionServiceProvider
  [3 ] Provider: Fideloper\Proxy\TrustedProxyServiceProvider
  [4 ] Provider: Fruitcake\Cors\CorsServiceProvider
  [5 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider
  [6 ] Provider: Illuminate\Mail\MailServiceProvider
  [7 ] Provider: Illuminate\Notifications\NotificationServiceProvider
  [8 ] Provider: Illuminate\Pagination\PaginationServiceProvider
  [9 ] Provider: Laravel\Sail\SailServiceProvider
  [10] Provider: Laravel\Tinker\TinkerServiceProvider
  [11] Tag: cors
  [12] Tag: flare-config
  [13] Tag: ignition-config
  [14] Tag: laravel-errors
  [15] Tag: laravel-mail
  [16] Tag: laravel-notifications
  [17] Tag: laravel-pagination
  [18] Tag: sail
> 1

Check Published Directory

1
cd my-project/resources/views

Push Package to GitHub

Commit

1
2
3
4
git status
git add -A
git commit -m "My package"
git push origin master

Tagging

For Packagist Versioning
This tag is used for versioning of Packagist.
1
git tag v1.0.0

Push Tag

1
git push origin v1.0.0

Register Package to packagist.org

Recommendation
I recommend to sign up with your GitHub account.
This is for register a web hook in GitHub by packagist.org.
Of course, you need to agree with it.

Check Package on New Laravel Project!

Generate New Laravel Project

1
composer create-project laravel/laravel new-project

Composer Require MyPackage

1
2
3
# new-project
cd new-project
composer require cozyfex/my-package
1
php artisan serve