A PHP Package Framework (Designed to help you build high quality PHP Packages faster).
The Nextpack (Drivers Mode) is a start package specific for the drivers driven packages! Example: when a package needs to support multiple similar drivers (providers) shuch as Bit.ly and Goo.gl or Twitter and Facebook..
Nextpack strives to facilitates and boosts the development process of PHP Packages. And it highly recommend producing framework agnostic packages.
Nextpack was created to help PHP developers producing more Open Source Composer Packages with the least amount of time and effort.
Where this comes from! I found myself doing the same things (Setup, Structure, Configuration, Basic Functionality) over and over, everytime I start developing a PHP package. And there where the idea of combining all those common things as a Framework came to my mind, and the Nextpack
project was born.
If you have any questions please share it with us on Gitter or email me on (mahmoud@zalt.me).
Nextpack includes:
- Rich package skeleton, (containing common files required by almost every PHP package)
- Clean folder structure
- Code samples, (demonstrating HOW and WHERE the code should be implemented)
- Test samples, (with PHPUnit)
- Basic configurations, (for the most popular required tools)
- Version Control: Git (
.gitattributes
,.gitignore
) - Continuous Integration: Travis and Scrutinizer (
.scrutinizer.yml
,.travis.yml
) - Testing: PHPUnit (
phpunit.xml
) - Package Manager: Composer (
composer.json
)
- Version Control: Git (
- Common functionalities, (provided by the Nextpack Library).
- Read config files, and serve it in the package classes
- Initialize drivers automatically "in case the package supports multiple drivers/providers"
- Git
- Composer
git clone https://github.com/nextpack/nextpack.git
composer update
- make sure everything is OK by running the tests
phpunit
After you install a fresh copy of Nextpack, the only thing you need to do is customizing it to meet your needs, before start codig your package.
But before the customization steps, if this is the first time you use the package it is recommended to read the Tutorial first, It explains the sample code shipped with the package.
The steps include removing the code samples shipped with the Nextpack:
- Change the namespace of the application from
Nextpack\Nextpack
to yourVendor-name\Package-name
. (you can do this using the [Replace All] feature of your IDE). - Update the following values in
composer.json
:name
,description
,keywords
,authors
,autoload
and don't forget to update thenamespaces
. (you might need to runcomposer dump-autoload
after the changes). - Run
composer install
- Delete the files
Say.php
andSing.php
, then add yourCustom.php
API class. - Delete
English.php
,French.php
andSayInterface.php
, then add yourCustom.php
Driver classes (if necessary). - Delete
NameValidator.php
andMissedNameException.php
. - Rename
SayFacadeAccessor.php
and update the returned string inside thegetFacadeAccessor()
function. - Rename
NextpackServiceProvider
and update the content of the following functions:facadeBindings()
,configPublisher()
andimplementationBindings()
. - Update the config file
nextpack.php
, (or remove it if not necessary). - Delete this
README.md
file. And rename theREADME.md.READY
toREADME.md
. - Update
CONTRIBUTING.md
andLICENSE
by replacing::Vendor-Name
and::Package-Name
with your vendor and package names. - Open the new
README.md
and replace the following: - Delete everytihng in the
tests
directory except theTestCase.php
(then add your tests from scratch). - Update the "testsuite" name in the
phpunit.xml
.
The API classes are normal classes, usually exist on the root of the src
directory, and they all extend from Nextpack\Nextpack\Handler
abstract class.
Example:
class Phone extends Handler
{
public function call($number)
{
// business logic..
return 'Alo Alo ' . $number;
}
}
The usage of this class Phone
will be:
$phone = new Phone();
$message = phone->call('96171137427');
print message;
To read the values of your default config file form an API class, you need to inject Nextpack\Library\Config
class in your constructor.
And then call the function get('fileName.key');
public function __construct(Config $config)
{
// read all the configuration file
$this->all = $config->get('nextpack'); // 'nextpack' is the name if the default config file you are using
// read something specific from the configuration file
$this->format = $config->get('nextpack.drivers.english.format');
}
You can access the driver configurations as you access the class properties $this->property
.
However a safer way to access these class properties is by using the get()
function $this->get('property')
(to prevent accessing undefined property, in case it's removed from the config file).
To access values from outside the driver specific configurations scope, you can call the $this->getAll()
and get all the config file as array.
// access configuration value as attribute
$accessToken = $this->accessToken;
// access configuration value using a safe function [best way]
$accessToken = $this->get('accessToken');
// access configuration value exist outside the scope of the driver in the config file
$allConfigurations = $this->getAll(); // (returns all the config file)
The driver classes are normal classes, usually exist in the src/Drivers
directory, and they all extend from Nextpack\Nextpack\Drivers\Driver
abstract class.
Example:
class Vodafone extends Driver
{
public function call($number)
{
// business logic..
return 'Alo, This is the Vodafone Mobile Operator';
}
}
To initialize an instance of the default driver selected in the config file all you have to do is call $this->driver()
function from any of your API classes.
Config file example:
/*
|--------------------------------------------------------------------------
| Default Driver name
|--------------------------------------------------------------------------
|
| The Supported Providers are:
| - vodafone
| - verizon
|
*/
'default' => 'vodafone',
Note: the name of the driver is the same as the name of the class, in lowercase.
Usage example from the API class:
$driver = $this->driver();
$result = $driver->call('96171137427');
Note: The package user must not initialize object of the Drivers. He should only access the API classes.
You can inject any class you want in any API or Driver's class.
In this example I am injecting a Validator
class.
public function __construct(Validator $validator)
{
$this->validator = $validator;
}
The test classes are normal classes, they can only exist in the tests
directory, and they all extend from Nextpack\Nextpack\Tests\TestCase
class.
Example:
class SingTest extends TestCase
{
public function testSingingSong()
{
$input = 'Bang Bang';
$expectedOutput = "Can you hear me singing $input :P";
$output = (new Sing())->song($input);
$this->assertEquals($output, $expectedOutput);
}
}
Nextpack is shipped with a samples code, to help you get an overall idea about where to place your code.
The two Sample Features are:
Feature 1: Sings a song by it's $name
Feature 2: Say Hello
to $name
with any supported language (English
or French
).
In the terminology of Nextpack, everything that can be supported such as (Providers, API's, Third parties...) are called
Drivers
.In this particular case the languages are the drivers. (because you can support many languages).
When you open the src
directory, you will find Say.php
and Sing.php
they are the package API's (Entry points). Those two API's will be called by the user to get the package do what it's expected to do.
Feature 1 demonstrates the simplest scenario, it shows how to write the business logic inside the API class. (no drivers involved).
class Sing extends Handler
{
public function song($songName)
{
return "Can you hear me singing $songName :P";
}
}
The usage of this API class will be as follow:
print $song = (new Sing())->song('Bang Bang');
The user create an instance of Sing
API then call the function song()
of the class passing a string and getting a string back.
Feature 2 demonstrates the drivers scenario, it shows how to write the business logic inside a driver. (this gives the users the ability to select their drivers).
class Say extends Handler
{
public function hello($name)
{
return $this->driver()->hello($name);
}
}
An instance of a driver is initialized using $this->driver()
, then a driver function ->hello($name)
is called on the instance.
The driver initialized is the default driver selected in the config
file ('default' => 'english',
)
return [
'default' => 'english',
'namespace' => 'Nextpack\\Nextpack\\Drivers\\',
'drivers' => [
'english' => [
'format' => '%s, %s!',
],
'french' => [
'format' => '%s, %s :)',
],
],
];
All the drivers classes exist in the src/Drivers
, alongside the Driver.php
which every driver extends from.
To run the tests, run the following command from the project folder.
$ ./vendor/bin/phpunit
Please check out our contribution Guidelines for details.
Issues on Github.
The MIT License (MIT). See the License File for more information.