Laravel Myanmar Docs

Package Development

Introduction

Laravelတြင္ တျခား functions ေတြ အသစ္ထည့္တဲ့အခါမွာ Packages ေတြခြဲျပီးအသစ္ထပ္ထည့္တဲ့နည္းက သမရုိးက် နည္းလမ္းေကာင္းတခုျဖစ္ပါတယ္။ လူအမ်ားစုေဆာင္းျပီး project ေတြကုိ ဖန္တီးရာတဲ့အခါမွာ အရမ္းအသံုးတည့္တဲ့နည္းလမ္းျဖစ္ပါတယ္။ ဥပမာ Carbon, or Behat.

ေသခ်ာတာေပါ့ဗ်ာ ၊ Packages ေတြကုိ အသံုးျပဳရာမွာ ပံုစံမ်ိဳးစံုရွိပါတယ္။ တခ်ိဳဟာေတြက Laravel တစ္ခုတည္းမဟုတ္ပဲ အျခားျခားေသာ Framework ေတြမွာပါ အလုပ္လုပ္တဲ့ stand-alone packages ေတြျဖစ္တယ္။ အေပၚက CarBon နဲ့ Behat လုိ packages ေတြကေတာ့ Stand-alon ေတြျဖစ္ပါတယ္ ။ အဲဒီလိုဖန္တီးထားတဲ့ packages ေတြကုိ Laravel မွာသံုးမယ္ဆုိရင္ေတာ့ ထံုးစံတုိင္း "composer.json" ဖုိင္မွာ သြားထည့့္ေပးလုိက္တာနဲ့ သံုးျပဳႏုိင္မွာပါ။

တျခားတခ်က္ကေတာ့ တျခား packages ေတြက Laravel အတြက္ပဲလို့ အေသသတ္မွတ္ပီး ထုတ္လုပ္ထားတဲ့ packages ေတြလဲ ရွိပါတယ္ ။ ဥပမာ အရင္ laravel version ေတြမွာ တုန္းက "bundles" လို packages ေတြမ်ိဳးပါ။ အဲဒီ packages ေတြမွာ routes, controllers, views, configuration, နဲ့ migrations ဖြဲ့စည္းထားျပီး laravel ရဲ့ လုပ္ေဆာင္ႏုိင္မူေတြကုိ တိုးခ်ဲ့ အသံုးျပဳႏုိင္ပါတယ္။ Stan-alone packages တစ္ခု ဖန္တီးဖို့ဆိုတာ အရမ္းခက္တဲ့ ကိစၥေတာ့မဟုတ္ပါဘူး ၊ အခုေအာက္မွာ ထပ္ေဖာ္ျပမယ့္ နည္းလမ္းေတြအတုိင္း ဖန္တီးၾကည့္ႏုိင္ပါတယ္။

Laravel အတြက္ Packages ေတြကုိ Packagistမွာတင္ျပီး ျဖန့္ခ်ီႏုိင္ျပီး Composer လို အရမ္းမိုက္တဲ့ Package destributuin tool ေတြသံုးျပဳ ျပီး ဖန္တီးရမွာပါ။

Creating A Package

Laravel မွာသံုးျပဳဖုိ့အတြက္ packages တစ္ခုတည္ေဆာက္ဖုိ့အတြက္ကေတာ့ 'workbench' Artisan command ကုိ အသံုးျပဳျပီးလြယ္လြယ္ကူကူကုိဖန္တီးႏုိင္ပါတယ္။ အဲလိုလုပ္ဖုိ့အတြက္ ပထမဆံုး 'app/config/workbench.php' မွာ name နဲ့ email ေလးအရင္သြားျဖည့္ေပးရပါတယ္။ အဲဒီ name နဲ့ email ကုိ အသစ္ေဆာက္မယ့္ packages ေတြ က 'composer.json' မွာ ျပန္အသံုးျပဳဖုိ့အတြက္ျဖစ္ပါတယ္။ကဲ့ ဒီေလာက္ျပင္ဆင္ျပီးရင္ package တစ္ခု တည္ေဆာက္ဖုိ့ အဆင္သင့္ျဖစ္ေနပါျပီ။ေအာက္က ကြန္မန္းကုိ Terminal(cmd) မွာ ထည့္ run လုိက္ပါ။

Issuing The Workbench Artisan Command

php artisan workbench vendor/package --resources

အေပၚက command ထဲမွာ vendor ဆိုတာက package တစ္ခုကုိ authors ေတြခြဲေရးတဲ့အခါမွာ package name ကုိ ခြဲခြဲျခားျခားသိႏုိင္ေအာင္ေပးထားတဲ့နာမည္ျဖစ္ပါတယ္။ Vendor ဆုိတာက အဲဒီ package ကုိ ဖန္တီးတဲ့လူျဖစ္ျပီး package ဆိုတာကေတာ့ ကုိယ္လုပ္တဲ့ package name ျဖစ္ပါတယ္။ ဥပမာ ကြ်န္ေတာ္ Taylar Otwell က "Zapper" ဆိုတဲ့ package တစ္ခုတည္ေဆာက္လုိက္ရင္ Package name က 'Zapper' ျဖစ္ျပး Vendor name က Taylar ျဖစ္ပါတယ္။ပံုမွန္အားျဖင့္ေတာ့ workbench က framework package တခုတည္ေဆာက္ပါတယ္။ "--resources" command က workbench ကုိ migrations, views, config, စသျဖင့္လိုအပ္တဲ့ ဖုိင္ေတြကုိ ဖန္တီးေပးဖို ့ေျပာပါတယ္။

အေပၚက 'Workbench' ကုိ run ျပီးျပီဆိုရင္ေတာ့ ၊ ကိုယ္ေပးထားတဲ့ နာမည္အတုိင္းပဲ 'workbench' ဆိုတဲ့ဖိုဒါထဲမွာ vendor name နဲ့ ဖိုဒါေတြေရာက္လာျပီး အထဲမွာ package နာမည္နဲ့ လိုအပ္တဲ့ဖုိင္ေတြအကုန္ အလုိေလ်ာက္ရွိေနပါလိမ့္မယ္။ ျပီးရင္ေတာ့ တည္ေဆာက္လုိက္တဲ့ package ကုိ laravel ကေန သံုးျပဳႏုိင္ရန္အတြက္ 'ServiceProvider' ေၾကာ္ျငာေပးရပါတယ္။ Service Provider ကုိ 'app/config/app.php' မွာ သြားထည့္ေပးရပါတယ္။အဲဒီမွာ သြားထည့္ေပးလုိက္ရင္ workbench ထဲက package ေတြကုိ laravel ကေန အသံုးျပဳႏုိင္ပါျပီ။ Service Provider က '[Package]ServiceProvider' ကိုအသံုးျပဳပါတယ္။ဥပမာအရဆုိရင္ 'app/config/app.php' က Provider မွာ 'Taylor\Zapper\ZapperServiceProvider' ဆိုျပီး array ထဲမွာ သြားထည့္ေပးရမွာပါ။

အခုလို Provider မွာ သြားထည့္ေပးျပီးရင္ေတာ့ packages ကုိ လုိအပ္သလိုမ်ိဳး စတင္ အသံုးျပဳႏုိပ္ပါျပီ။ ပထမဆံုး package structure နဲ ့ development workflow ကို အရင္ေလ့လာသင့္ပါတယ္။

Note: Service Provider cannot be found ဆိုျပီး error ျပေနရင္ php artisan dump-autoload ကုိ root directory မွာ terminal(cmd) မွ တစ္ဆင့္ run ျပီး ျပန္စမ္းၾကည့္ပါ။

Package Structure

'workbench' command ကုိ အသံုးျပဳျပီးတဲ့အခါမွာ အဲဒီ command က ကိုယ္ဖန္တီးလိုက္တဲ့ packages ကုိ laravel ႏွင့္ တြဲဖက္အသံုးျပဳႏုိင္ေအာင္ အကုန္အလိုေလ်ာက္ျပဳလုပ္ေပးပါတယ္။

Basic Package Directory Structure

/src
    /Vendor
        /Package
            PackageServiceProvider.php
    /config
    /lang
    /migrations
    /views
/tests
/public

အေပၚက file structure ကုိအရင္ေလ့လာၾကည့္ရေအာင္။ 'src/Vendor/Package' က ေတာ့ 'ServiceProvider' ပါဝင္တဲ့အတြက္ package's classes ေတြရဲ့ အဓိကေနရာလုိ့ေျပာရမွာပါ။ config, lang, migrations, နဲ့ `views' ေတြကေတာ့ packages အတြက္ လိုအပ္တဲ့ resources ေတြပါဝင္မယ့္ဖုိင္ေတြျဖစ္ပါတယ္။ Packages တစ္ခုမွာလဲ Laravel မွာရွိတဲ့ resources ေတြ အတုိင္း တည္ရွိေနမွာပါ။

Service Providers

Service providers ဖိုင္ေတြကေတာ့ packages ေတြရဲ့ အသက္ဖုိင္လုိ့ေျပာရမွာပါ။ပံုမွန္အားျဖင့္ Service Provider မွာ 'boot' နဲ့ 'register' ဆိုတဲ့ methodsႏွစ္ခုပါဝင္ပါတယ္။ ဒီ methods ႏွစ္ခုမွာပဲ အကုန္လံုးျပဳလုပ္ႏုိင္ပါတယ္။ ဥပမာ routes ဖိုင္ခ်ိတ္ဖုိ့ ၊IoC Container ေတြ register bindings လုပ္ဖုိ့ ၊ events ေတြထည့္ဖုိ့ ၊ အကုန္လံုးနည္းပါးကုိ ဒီ method ႏွစ္ခုတစ္ဆင့္ အလုပ္လုပ္သြားမွာပါ။

"register" method က Service Provider ကုိ register ျပဳလုပ္ျပီးတာနဲ့ အလုပ္လုပ္မယ့္ method ျဖစ္ပါတယ္။ 'boot' method ကေတာ့ request အသက္မဝင္ခင္အခ်ိန္ထိပဲ အလုပ္လုပ္မွာျဖစ္ပါတယ္။ ဒါဆိုရင္ေတာ့ service provider ထဲက actions ေတြ registe လုပ္ျပီးတဲ့အခ်ိန္ (သို ့) တျခား provider တစ္ခုရဲ့ service ကုိ ေက်ာ္လြန္(override)အသံုးျပဳလိုပါက 'boot' method ကုိ အသံုးျပဳသင့္ပါတယ္။

'workbench' command ႏွင့္ package တစ္ခုတည္ေဆာက္လုိက္တာနဲ့ 'boot' method မွာ ေအာက္ေဖာ္ျပပါအတုိင္း action တစ္ခု ပါဝင္ေနပါတယ္။

$this->package('vendor/package');

ဒီ method က laravel ကုိ packages ထဲက views,config, other resource ေတြကုိ အသံုးျပဳႏုိင္ေအာင္လုပ္ေပးပါတယ္။ ပံုမွန္အားျဖင့္ေတာ့ အဲဒီ ကုတ္ကုိ ျပဳျပင္ဖုိ့မလိုအပ္ပါဘူး။

ပံုမွန္အားျဖင့္ package တစ္ခုတည္ေဆာက္ျပီးတဲ့အခါ အဲဒီ packages ရဲ့ resource ေတြက 'vendor/package' ေအာက္မွာရွိပါတယ္။ဘယ္လုိျဖစ္ျဖစ္ package method ကုိ argument ေနာက္တစ္ခု ထပ္ထည့္ျပီး package resource ေနရာေတြကုိ လုိအပ္သလို ေအာက္ကပံုစံအတုိင္း ေျပာင္းလဲႏုိင္ပါေသးတယ္။

// Passing custom namespace to package method
$this->package('vendor/package', 'custom-namespace');

// Package resources now accessed via custom-namespace
$view = View::make('custom-namespace::foo');

Service provider classes ေတြအတြက္ app directory ထဲမွာ ေနရာအတည္တစ္က် သတ္မွတ္ထားတာမ်ိဳးလဲမရွိပါဘူး။ 'app' ထဲမွ 'Providers' namespace ေပးျပီး ထားခ်င္တဲ့ေနရာမွာ ထားႏုိင္ပါတယ္။ ဒဲဒီ class ဖိုင္ေတြကုိ Composer's auto-loading facilities က သိမွတ္ျပဳေနသ၍ အဲဒီ class ဖုိင္ထဲက class ေတြကုိ app က ယူသံုးႏုိင္မွာပါ။

'Package ထဲက resources ( ဥပမာ Configuration ၊ Views ) ေနရာေတြကုိ ေျပာင္းလုိက္ျပီဆိုရင္ ေျပာင္းလိုက္တဲ့ေနရာကုိ 'package' methord မွာ တတိယေျမာက္ argument တစ္ခုအျဖစ္ ေအာက္ပါအတုိင္းထည့္သင့္ေပးသင့္ပါတယ္။

$this->package('vendor/package', null, '/path/to/resources');

Deferred Providers

If you are writing a service provider that does not register any resources such as configuration or views, you may choose to make your provider "deferred". A deferred service provider is only loaded and registered when one of the services it provides is actually needed by the application IoC container. If none of the provider's services are needed for a given request cycle, the provider is never loaded.

To defer the execution of your service provider, set the defer property on the provider to true:

protected $defer = true;

Next you should override the provides method from the base Illuminate\Support\ServiceProvider class and return an array of all of the bindings that your provider adds to the IoC container. For example, if your provider registers package.service and package.another-service in the IoC container, your provides method should look like this:

public function provides()
{
    return array('package.service', 'package.another-service');
}

Package Conventions

When utilizing resources from a package, such as configuration items or views, a double-colon syntax will generally be used:

Loading A View From A Package

return View::make('package::view.name');

Retrieving A Package Configuration Item

return Config::get('package::group.option');

Note: If your package contains migrations, consider prefixing the migration name with your package name to avoid potential class name conflicts with other packages.

Development Workflow

When developing a package, it is useful to be able to develop within the context of an application, allowing you to easily view and experiment with your templates, etc. So, to get started, install a fresh copy of the Laravel framework, then use the workbench command to create your package structure.

After the workbench command has created your package. You may git init from the workbench/[vendor]/[package] directory and git push your package straight from the workbench! This will allow you to conveniently develop the package in an application context without being bogged down by constant composer update commands.

Since your packages are in the workbench directory, you may be wondering how Composer knows to autoload your package's files. When the workbench directory exists, Laravel will intelligently scan it for packages, loading their Composer autoload files when the application starts!

If you need to regenerate your package's autoload files, you may use the php artisan dump-autoload command. This command will regenerate the autoload files for your root project, as well as any workbenches you have created.

Running The Artisan Autoload Command

php artisan dump-autoload

Package Routing

In prior versions of Laravel, a handles clause was used to specify which URIs a package could respond to. However, in Laravel 4, a package may respond to any URI. To load a routes file for your package, simply include it from within your service provider's boot method.

Including A Routes File From A Service Provider

public function boot()
{
    $this->package('vendor/package');

    include __DIR__.'/../../routes.php';
}

Note: If your package is using controllers, you will need to make sure they are properly configured in your composer.json file's auto-load section.

Package Configuration

Accessing Package Configuration Files

Some packages may require configuration files. These files should be defined in the same way as typical application configuration files. And, when using the default $this->package method of registering resources in your service provider, may be accessed using the usual "double-colon" syntax:

Config::get('package::file.option');

Accessing Single File Package Configuration

However, if your package contains a single configuration file, you may simply name the file config.php. When this is done, you may access the options directly, without specifying the file name:

Config::get('package::option');

Registering A Resource Namespace Manually

Sometimes, you may wish to register package resources such as views outside of the typical $this->package method. Typically, this would only be done if the resources were not in a conventional location. To register the resources manually, you may use the addNamespace method of the View, Lang, and Config classes:

View::addNamespace('package', __DIR__.'/path/to/views');

Once the namespace has been registered, you may use the namespace name and the "double colon" syntax to access the resources:

return View::make('package::view.name');

The method signature for addNamespace is identical on the View, Lang, and Config classes.

Cascading Configuration Files

When other developers install your package, they may wish to override some of the configuration options. However, if they change the values in your package source code, they will be overwritten the next time Composer updates the package. Instead, the config:publish artisan command should be used:

php artisan config:publish vendor/package

When this command is executed, the configuration files for your application will be copied to app/config/packages/vendor/package where they can be safely modified by the developer!

Note: The developer may also create environment specific configuration files for your package by placing them in app/config/packages/vendor/package/environment.

Package Views

If you are using a package in your application, you may occasionally wish to customize the package's views. You can easily export the package views to your own app/views directory using the view:publish Artisan command:

php artisan view:publish vendor/package

This command will move the package's views into the app/views/packages directory. If this directory doesn't already exist, it will be created when you run the command. Once the views have been published, you may tweak them to your liking! The exported views will automatically take precedence over the package's own view files.

Package Migrations

Creating Migrations For Workbench Packages

You may easily create and run migrations for any of your packages. To create a migration for a package in the workbench, use the --bench option:

php artisan migrate:make create_users_table --bench="vendor/package"

Running Migrations For Workbench Packages

php artisan migrate --bench="vendor/package"

Running Migrations For An Installed Package

Packages ထဲမွာ database migrate လုပ္ဖို့အတြက္ workbench ထဲမွာ To run migrations for a finished package that was installed via Composer into the vendor directory, you may use the --package directive:

php artisan migrate --package="vendor/package"

Package Assets

Moving Package Assets To Public

'packages' ေတြမွာ 'Javascript, Css, images လုိ assets ေတြပါေကာင္းပါႏုိင္ပါတယ္။ အဲဒီ assets ေတြကုိ app မွ တဆင့္တန္းဆြဲေခၚသံုးဖုိ့မျဖစ္ႏုိင္ပါဘူး ။ အဲဒီအတြက္ 'package' ထဲက assets ေတြကုိ public ေအာက္ကုိ ေျပာင္းထည့္ေပးဖုိ့လိုအပ္ပါတယ္။ အဲဒီအတြက္ asset:publish ကြန္မန္း ကုိ ေအာက္ကအတုိင္း အသံုးျပဳျပီး ေျပာင္းထည့္ေပးႏုိင္ပါတယ္။

php artisan asset:publish

php artisan asset:publish vendor/package

တကယ္လုိ တည္ေဆာက္ထားတဲ့ 'package' က 'workbench' ေအာက္မွာပဲရွိေသးရင္ေတာ့ ' --bench ' ကုိေအာက္ပါအတုိင္းထပ္ထည့္ျပီးေရးေပးရပါတယ္။

php artisan asset:publish --bench="vendor/package"

ဒီကြန္မန္းက package ထဲမွ assets ေတြကုိ 'public/packages' ထဲကုိ သက္ဆိုင္ရင္ package နဲ့ vendor နာမည္ေတြအလုိက္ဖိုဒါေတြ အလိုေလ်ာက္ေဆာက္ျပီး သိမ္းဆည္းေပးသြားမွာပါ။ ဥပမာ 'workbench' ေအာက္မွာ 'usersape/kusod' ဆိုျပီး packages ေဆာက္ထားရင္ 'public/packages/userscape/kudos' ဆိုျပီး ေရာက္သြားမွာပါ။ ဒီလိုလုပ္ျခင္းအားျဖင့္ asset ေတြနဲ့ပက္သက္ျပီး လံုျခံဳေရးဆုိင္ရာ အားသာခ်က္မ်ား ရရွိႏုိင္ပါတယ္။

Publishing Packages

ကုိယ္တည္ေဆာက္ထားတဲ့'Package' က အသံုးျပဳဖို ့အားလံုးျပင္ဆင္ျပီးသြားရင္ေတာ့ Packagist ကုိ တျခားသူေတြပါသံုးျပဳႏုိင္ေအာင္ တင္ထားေပးသင့္ပါတယ္။ တကယ္လုိ့ ကုိယ္ တည္ေဆာက္လုိက္တဲ့ 'package' က laravel အတြက္ပဲ သီးသန့္တည္ေဆာက္ထားရင္ေတာ့ 'composer.json' မွာ 'laravel' ဆိုျပီး tag ထည့္ေပးဖုိ့လိုအပ္ပါတယ္။

Also, it is courteous and helpful to tag your releases so that developers can depend on stable versions when requesting your package in their composer.json files. If a stable version is not ready, consider using the branch-alias Composer directive.

Once your package has been published, feel free to continue developing it within the application context created by workbench. This is a great way to continue to conveniently develop the package even after it has been published.

Some organizations choose to host their own private repository of packages for their own developers. If you are interested in doing this, review the documentation for the Satis project provided by the Composer team.