What is a custom package? A custom package is a reusable piece of code that can be used across different projects to avoid code duplica...
A custom package is a reusable piece of code that can be used across different projects to avoid code duplication and repetition. Think of it as a mini application that you can easily plug into your main application and get it going.
👉 Rule of thumb: Package it when reuse becomes real. Not before.
I'll walk you through how to manually create a package so you understand the internals. But once you're familiar, you can use these tools to speed things up:
These tools can scaffold about 80% of the boilerplate work.
Enough of theory :)
Create a directory for packages. Laravel packages typically reside in Packages
directory. Here, I am taking an example of creating a custom package to show weather description based on city input given by the user.
The package directory structure should look like below:
Packages/
└── PankajVasnani/
└── WeatherForecast/
├── src/
│ ├── WeatherInfoServiceProvider.php
│ ├── WeatherService.php
├── config/
│ ├── weatherforecast.php
├── composer.json
Next step is to create a service provider for it where i register package's services and other configurations required for our package.
It has two methods :-
<?php
namespace PankajVasnani\WeatherForecast;
use Illuminate\Support\ServiceProvider;
class WeatherForecastServiceProvider extends ServiceProvider
{
public function boot()
{
$this->publishes([
__DIR__.'/../config/weatherforecast.php' => config_path('weatherforecast.php'),
], 'config');
}
public function register()
{
$this->mergeConfigFrom(
__DIR__.'/../config/weatherforecast.php',
'weatherforecast'
);
$this->app->singleton(WeatherService::class, function ($app) {
return new WeatherService();
});
}
}
Now its time to create the actual functionality of our package which is to tell the weather based on the input city by the end user.
<?php
namespace PankajVasnani\WeatherForecast;
class WeatherService
{
/**
* Get the weather forecast for the specified city.
* Returns mock data for demonstration.
*
* @param string|null $city
* @return array
*/
public function getForecastByCity(?string $city = null): array
{
// Take city input by the user
if (!$city) {
$city = config('weatherforecast.default_city');
}
// Retrieve API token from config
$apiToken = config('weatherforecast.api_token');
// Call the mock weather API with authentication header
$response = Http::withHeaders([
'Authorization' => "Bearer {$apiToken}",
])->get("https://api.mockweather.com/forecast?city={$city}");
// Return the response data
return $response->json();
}
}
Note: I have taken mock weather api. You can replace it with actual weather forecast API and token.
Now, lets define the package's config that contains the API token and the default city, that will be used by weather forecast api to gather weather details about the particular city.
<?php
return [
'api_key' => env('WEATHER_API_KEY', 'your-default-api-key'),
'default_city' => 'New York',
];
Next, I define the package's composer.json which lists all important details about package information.
{
"name": "pankaj-vasnani/weather-forecast",
"description": "A simple weather forecasting Laravel package",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"PankajVasnani\\WeatherForecast\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"PankajVasnani\\WeatherForecast\\WeatherForecastServiceProvider"
]
}
},
"require": {},
"minimum-stability": "dev",
"prefer-stable": true
}
PankajVasnani\\WeatherForecast\\
Maps this namespace to the src/
directory so Laravel can automatically detect and load the required classes from src/
folder.Now, the most exciting part, how to use the package in main laravel application. Let's have a look.
Define repositories section in main application's composer.json
file, that tells where the custom packages can be found. It has two keys:
path
defines that it is in a local directory."repositories": [
{
"type": "path",
"url": "app/Packages/PankajVasnani/WeatherForecast"
}
]
Note: Make sure you always use relative path, not abolute path. Absolute path might break if you decide to move your project to different directory, environments or other machines.
Now lets proceed to install the package using composer which is a simple and straight forward process.
composer require pankaj-vasnani/weather-forecast:@dev
Now we publish the package's config file in laravel main application.
php artisan vendor:publish --provider="PankajVasnani\WeatherForecast\WeatherForecastServiceProvider" --tag=config
php artisan vendor:publish
publishes the config file from the package in main laravel application.--provider="PankajVasnani\WeatherForecast\WeatherForecastServiceProvider"
specifies the service provider from where to publish the files.--tag=config
publishes only the configuration files tagged as config.Next and the last step, we define the controller and route where we use our package's functionality. It is very easy to understand. No complex coding. Let me show you.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\WeatherForecastController;
Route::get('/weather-forecast/{city}', [WeatherForecastController::class, 'getForecastByCity']);
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PankajVasnani\WeatherForecast\WeatherService;
class WeatherForecastController extends Controller
{
private $weatherService;
public function __construct(WeatherService $weatherService)
{
// Constructor injection of the WeatherService
$this->weatherService = $weatherService;
}
/**
* Get the weather forecast for a specific city.
*
* @param string|null $city
* @return \Illuminate\Http\JsonResponse
*/
public function getForecastByCity(?string $city = "Jaipur")
{
$forecast = $this->weatherService->getForecastByCity($city);
return response()->json($forecast);
}
}
If you're planning to build a package for Backpack for Laravel—an admin panel that saves developers countless hours—you can check out how to create Backpack add-ons. It follows a similar package structure, but is tailored to integrate with Backpack’s ecosystem. Perfect if you're looking to level up your Laravel toolset.
Build once, use everywhere! — your next innovative solution is waiting to be discovered!
Want me to turn this into a shareable GitHub Package? Let me know in the comments below.
Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.
What do you think about this?
Wondering what our community has been up to?