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 ([email protected]).
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.gitcomposer 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\Nextpackto 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,autoloadand don't forget to update thenamespaces. (you might need to runcomposer dump-autoloadafter the changes). - Run
composer install - Delete the files
Say.phpandSing.php, then add yourCustom.phpAPI class. - Delete
English.php,French.phpandSayInterface.php, then add yourCustom.phpDriver classes (if necessary). - Delete
NameValidator.phpandMissedNameException.php. - Rename
SayFacadeAccessor.phpand update the returned string inside thegetFacadeAccessor()function. - Rename
NextpackServiceProviderand 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.mdfile. And rename theREADME.md.READYtoREADME.md. - Update
CONTRIBUTING.mdandLICENSEby replacing::Vendor-Nameand::Package-Namewith your vendor and package names. - Open the new
README.mdand replace the following: - Delete everytihng in the
testsdirectory 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/phpunitPlease check out our contribution Guidelines for details.
Issues on Github.
The MIT License (MIT). See the License File for more information.