The Stubborn package enhances the PHP development workflow by providing a set of customizable stubs. Stubs are templates used to scaffold code snippets for various components like models, controllers, and migrations. With Stubborn, developers can easily tailor these stubs to match their project's coding standards and conventions. This package aims to streamline the code generation process, fostering consistency and efficiency in PHP projects. Explore the customization options and boost your development speed with Stubborn.
Generating new files from stubs can be as simple as this:
<?php
Stub::from('Support/Enums.php')
->name('Color')
->generate();
PHP >= 8.0
You can install the package with Composer, but make sure to add this repository (as type git) in your composer.json. When this package is available on packagist, you can skip this step (and it won't be mentioned here). Once the repository is added, run:
composer require dakin/stubborn
You don't need to publish anything.
Note that for many of these examples, especially those towards the bottom, I've omitted the
->generate()
call for the sake of brevity. If you want your stubs to actually generate, don't forget to add->generate()
!
First of all, create a stub file called model.stub
:
touch model.stub
Add some code to that, like this:
<?php
namespace {{ NAMESPACE }};
class {{ CLASS }}
{
}
In order to use Stubborn, you need to import the Stubborn\Stub
class:
<?php
use Dakin\Stubborn\Stub;
Stub::class;
First thing, you need to use the from
method to give the stub path:
<?php
Stub::from(__DIR__ . 'model.stub');
Next, you'll want to specify the destination directory of the stub file:
<?php
Stub::from(__DIR__ . 'model.stub')
->to(__DIR__ . '/App');
You can set the stub file with this, but make sure to leave out the stub extension:
<?php
Stub::from(__DIR__ . 'model.stub')
->to(__DIR__ . '/App')
->name('new-model');
You can determine the stub extension:
<?php
Stub::from(__DIR__ . 'model.stub')
->to(__DIR__ . '/App')
->name('new-model')
->ext('php');
The replace
method takes two parameters, the first one is the key (variable) and the second one is the value. The value will be replaced with the variable:
<?php
Stub::from(__DIR__ . 'model.stub')
->to(__DIR__ . '/App')
->name('new-model')
->ext('php')
->replace('NAMESPACE', 'App');
The replaces
method takes an array. If you want to replace multiple variables you can use this method:
<?php
Stub::from(__DIR__ . 'model.stub')
->to(__DIR__ . '/App')
->name('new-model')
->ext('php')
->replaces([
'NAMESPACE' => 'App',
'CLASS' => 'MyClass'
]);
To generate the stub file, you need to use the generate
method at the end of the chain to generate stub file:
<?php
Stub::from(__DIR__ . 'model.stub')
->to(__DIR__ . '/App')
->name('new-model')
->ext('php')
->replaces([
'NAMESPACE' => 'App',
'CLASS' => 'MyClass'
])
->generate();
If you're following along, the final file should be named new-model.php
and look something like this:
<?php
namespace App;
class MyClass
{
}
Stubborn adds support for modifiers. Modifiers let you use a single replace string in multiple forms. Here's an example... Let's say you have a class stub that can introduce itself:
<?php
namespace App;
class {{ NAME }}
{
public function introduce(): string {
return "I am a {{ NAME }}";
}
}
This is fine, but maybe I want the class to shout its name in ALL CAPS. Instead of declaring that behavior from my Stub generation code, I can put that intention directly in the stub file.
Mind you, this particular use case would benefit more from not having the class name statically declared twice, but for demo purposes...
<?php
namespace App;
class {{ NAME::studly }}
{
public function introduce(): string {
return "I am a {{ NAME::upper }}!";
}
}
Great, now I can pass class name
or Class Name
to Stubborn a single time, and still get that token presented in the proper way.
There's a new Str class that's been adopted from the Laravel framework to offer several helpers as modifiers. Most of the single parameter methods from that class can be used as modifiers by adding ::methodName
after the variable name.
These modifiers can also be chained together: {{ NAME::upper::trim }}
.
In addition, you can add your own modifiers by editing the Stub::modFunctions associative array. You can pass in the modifier name as the key and a function accepting a string as the value:
<?php
use Dakin\Stubborn\Stub;
Stub::modFunctions['repeat'] = fn ($theString) => $theString . $theString;
Now, stubs with {{ VAR_NAME::repeat }}
will repeat the replace value once.
It's likely you'll have a single place where you want to keep all of your stubs ({project_path}/stubs
, for example). It can be a pain to keep providing that folder path as context when generating stubs.
<?php
$stubber = Stub::from('path/to/my/stubs/the-actual.stub');
Instead, you may set the stub folder a single time using the static setStubFolder
method.
<?php
// During setup...
Stub::setStubFolder('path/to/my/stubs');
// Later on...
$stubber = Stub::from('the-actual.stub');
A couple notes about this:
setStubFolder
checks that your path is, in fact, a directory. Disable that behavior by setting thesafe
parameter to false.- Related static methods
resetStubFolder
andstubFolder
are available for you to, respectively:- Set the stub folder to null, restoring standard
from
behavior - Get the current stub folder value
- Set the stub folder to null, restoring standard
setStubFolder
returns a boolean representing success/failure. If the path given is not a directory and $safe is set to true, it will return false. Otherwise, it returns the stubFolder value casted to a bool.
<?php
Stub::setContextFolder('path/to/my/src_folder')
Similar to the Stub Folder option, Stubborn provides a Context Folder option. If you have something like a src
directory where all of your stubs tend to go, you may provide the path to that directory as a parameter to Stubborn::setContextFolder
. By doing so, you can remove that part of the path when you call Stub::to.
Before Stub and Context folder:
<?php
$stubber = Stub::from('./stubs/the_actual.stub')
->to('./src/Support')
->name('NewClass')
->ext('php');
After:
<?php
$stubber = Stub::from('the_actual.stub')
->to('Support')
->name('NewClass')
->ext('php');
An additional benefit to setting up the Stub and Context folders is being able to omit some of these chained calls from your Stub generation.
Imagine a stub folder structure that matches the src folder. Basic Stub generation with this structure may look something like this:
<?php
$stubber = Stub::from('./stubs/Support/Enums.php')
->to('./src/Support/Enums')
->name('Color')
->ext('php');
Fine, but a bit redundant. When you provide the context folder, Stubborn will try to infer your Stub::$to and your Stub::$ext based on the path provided to Stub::from.
<?php
$stubber = Stub::from('Support/Enums.php')
->name('Color');
Great, this still creates the same file, but with a much slimmer set of calls.
The crew at Binafy did most of the heavy lifting for the core stub features with their Laravel-embedded version of this package.
If you discover any security-related issues, please email [email protected]
instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.