PHPackages                             pup/placeholderapi - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. pup/placeholderapi

ActiveLibrary[API Development](/categories/api)

pup/placeholderapi
==================

A simple and efficient placeholder system for PocketMine-MP. Originally created for the Kyro core.

2.0.0(7mo ago)013GPL-3.0-or-laterPHPPHP &gt;=8.1

Since Oct 2Pushed 7mo agoCompare

[ Source](https://github.com/Pupggerss/PlaceholderApi)[ Packagist](https://packagist.org/packages/pup/placeholderapi)[ RSS](/packages/pup-placeholderapi/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (4)Used By (0)

PlaceholderAPI v2.0
===================

[](#placeholderapi-v20)

A powerful, type-safe placeholder system for PocketMine-MP plugins. Create reusable, parameterized placeholders with a clean, extensible API.

What's New in v2.0
------------------

[](#whats-new-in-v20)

- **Type-safe interface system** - Implement `Placeholder` interface for full control
- **Parameterized placeholders** - Use `{placeholder:parameter}` syntax
- **Better organization** - Separate `PlayerPlaceholder` and `ServerPlaceholder` base classes
- **Validation &amp; safety** - Automatic player requirement checks, recursion protection
- **Backward compatible** - All v1.x code still works!

Features
--------

[](#features)

- Built-in color formatting with named placeholders
- Extensive player data placeholders
- Server information placeholders
- Easy custom placeholder registration (closure or class-based)
- Parameterized placeholders for dynamic content
- Gradient text effects
- Recursive placeholder parsing
- Type-safe architecture

Installation
------------

[](#installation)

### As a Virion (Recommended)

[](#as-a-virion-recommended)

```
composer require pup/placeholderapi
```

### Direct Include

[](#direct-include)

Drop the `src/pup/placeholderapi` folder into your plugin's source directory.

Quick Start
-----------

[](#quick-start)

### Initialization

[](#initialization)

**IMPORTANT:** Always initialize PlaceholderAPI before registering custom placeholders to ensure all placeholders are registered to the same manager instance.

```
use pup\placeholderapi\PlaceholderApi;

// In your plugin's onEnable()
public function onEnable(): void
{
    // Initialize PlaceholderAPI first
    PlaceholderApi::initialize();

    // Now register your custom placeholders
    PlaceholderApi::registerPlaceholder(...);
}
```

### Basic Usage

[](#basic-usage)

```
use pup\placeholderapi\PlaceholderApi;

// Parse message without player context (colors + server placeholders)
$message = "{gold}Server: {server_online}/{server_max} players online";
$formatted = PlaceholderApi::parse($message);

// Parse with player context (includes player-specific placeholders)
$message = "{green}Welcome {player_name}! Health: {player_health}";
$formatted = PlaceholderApi::parse($message, $player);
$player->sendMessage($formatted);

// Parse multiple messages at once
$messages = [
    "{gold}Welcome to the server!",
    "{aqua}You have {player_health} health",
    "{yellow}TPS: {server_tps}"
];
$parsed = PlaceholderApi::parseMultiple($messages, $player);
```

### Register Custom Placeholders

[](#register-custom-placeholders)

#### Method 1: Quick Closure Registration

[](#method-1-quick-closure-registration)

```
use pup\placeholderapi\PlaceholderApi;

// Simple server-wide placeholder
PlaceholderApi::registerPlaceholder(
    "server_name",
    fn(?Player $player, ?string $params): string => "My Server",
    requiresPlayer: false,
    supportsParameters: false
);

// Player-specific placeholder
PlaceholderApi::registerPlaceholder(
    "player_coins",
    function(?Player $player, ?string $params): string {
        if ($player === null) return "0";
        return (string)MyEconomy::getCoins($player);
    },
    requiresPlayer: true,
    supportsParameters: false
);

// Placeholder with parameters: {top_player:1}, {top_player:5}
PlaceholderApi::registerPlaceholder(
    "top_player",
    fn(?Player $player, ?string $params): string =>
        MyPlugin::getTopPlayer($params !== null ? (int)$params : 1),
    requiresPlayer: false,
    supportsParameters: true
);
```

#### Method 2: Class-Based Registration (Recommended)

[](#method-2-class-based-registration-recommended)

```
use pocketmine\player\Player;
use pup\placeholderapi\PlaceholderApi;
use pup\placeholderapi\placeholder\PlayerPlaceholder;
use pup\placeholderapi\placeholder\ServerPlaceholder;

// Player-specific placeholder
class PlayerBalancePlaceholder extends PlayerPlaceholder
{
    public function __construct()
    {
        parent::__construct("player_balance");
    }

    protected function processPlayer(Player $player, ?string $params): string
    {
        $balance = MyEconomy::getBalance($player);
        return "$" . number_format($balance, 2);
    }
}

// Server-wide placeholder
class TotalMoneyPlaceholder extends ServerPlaceholder
{
    public function __construct()
    {
        parent::__construct("total_money");
    }

    protected function processServer(?string $params): string
    {
        return "$" . number_format(MyEconomy::getTotalMoney(), 2);
    }
}

// Register them
PlaceholderApi::registerCustomPlaceholder(new PlayerBalancePlaceholder());
PlaceholderApi::registerCustomPlaceholder(new TotalMoneyPlaceholder());
```

Built-in Placeholders
---------------------

[](#built-in-placeholders)

### Player Placeholders (require player context)

[](#player-placeholders-require-player-context)

PlaceholderDescriptionExample Output`{player}` or `{player_name}`Player's name`Steve``{player_display}`Display name`§aSteve``{player_health}`Current health`20.0``{player_max_health}`Max health`20.0``{player_food}`Food level`20``{player_level}`XP level`5``{player_xp}`Total XP`250``{player_gamemode}`Game mode`Survival``{player_ping}`Network ping`42``{player_x}`X coordinate`123.45``{player_y}`Y coordinate`64.00``{player_z}`Z coordinate`-789.12``{player_world}`World name`world`### Server Placeholders (work without player)

[](#server-placeholders-work-without-player)

PlaceholderDescriptionExample Output`{server_motd}`Server MOTD`My Server``{server_online}`Online players`15``{server_max}`Max players`20``{server_tps}`Server TPS`19.95`### Color Placeholders

[](#color-placeholders)

**Colors:** `{black}` `{dark_blue}` `{dark_green}` `{dark_aqua}` `{dark_red}` `{dark_purple}` `{gold}` `{gray}` `{dark_gray}` `{blue}` `{green}` `{aqua}` `{red}` `{light_purple}` `{yellow}` `{white}`

**Formatting:** `{bold}` `{italic}` `{underline}` `{strikethrough}` `{obfuscated}` `{reset}`

Advanced Features
-----------------

[](#advanced-features)

### Parameterized Placeholders

[](#parameterized-placeholders)

```
// Register a placeholder that accepts parameters
PlaceholderApi::registerPlaceholder(
    "player_stat",
    function(?Player $player, ?string $params): string {
        if ($player === null || $params === null) return "N/A";

        return match($params) {
            "kills" => (string)Stats::getKills($player),
            "deaths" => (string)Stats::getDeaths($player),
            "wins" => (string)Stats::getWins($player),
            default => "Unknown"
        };
    },
    requiresPlayer: true,
    supportsParameters: true
);

// Use in messages: {player_stat:kills}, {player_stat:deaths}, {player_stat:wins}
$msg = "{player_name} has {player_stat:kills} kills!";
```

### Recursive Placeholders

[](#recursive-placeholders)

Placeholders can return other placeholders, which will be automatically parsed:

```
PlaceholderApi::registerPlaceholder(
    "welcome_msg",
    fn(?Player $p, ?string $params): string =>
        "{gold}Welcome {player_name}! You have {player_coins} coins.",
    requiresPlayer: true
);

// The nested {player_name} and {player_coins} will be automatically parsed
$result = PlaceholderApi::parse("{welcome_msg}", $player);
```

### Gradient Text Effects

[](#gradient-text-effects)

```
// Character-by-character gradient
$text = "Rainbow Text!";
$colors = ['red', 'gold', 'yellow', 'green', 'aqua', 'blue', 'light_purple'];
$gradient = PlaceholderApi::createCharacterGradient($text, $colors);
$player->sendMessage($gradient);

// Word-by-word gradient
$text = "Each word different color";
$colors = ['red', 'yellow', 'green', 'aqua'];
$gradient = PlaceholderApi::createWordGradient($text, $colors);
$player->sendMessage($gradient);
```

Complete Plugin Example
-----------------------

[](#complete-plugin-example)

```
namespace MyPlugin;

use pocketmine\plugin\PluginBase;
use pocketmine\player\Player;
use pup\placeholderapi\PlaceholderApi;
use pup\placeholderapi\placeholder\PlayerPlaceholder;

class Main extends PluginBase
{
    public function onEnable(): void
    {
        // IMPORTANT: Initialize PlaceholderAPI first
        PlaceholderApi::initialize();

        // Now register custom placeholders
        PlaceholderApi::registerPlaceholder(
            "server_name",
            fn(?Player $p, ?string $params): string => $this->getConfig()->get("name", "My Server"),
            requiresPlayer: false
        );

        PlaceholderApi::registerCustomPlaceholder(new PlayerKillsPlaceholder($this));
    }

    public function onDisable(): void
    {
        // Clean up
        PlaceholderApi::unregisterPlaceholder("server_name");
        PlaceholderApi::unregisterPlaceholder("player_kills");
    }

    public function sendWelcome(Player $player): void
    {
        $messages = [
            "{gold}{bold}========================",
            "{aqua}Welcome {player_name}!",
            "{gray}Health: {red}{player_health}§r{gray}/{player_max_health}",
            "{gray}World: {yellow}{player_world}",
            "{gray}Your kills: {green}{player_kills}",
            "{gray}Online: {white}{server_online}/{server_max}",
            "{gold}{bold}========================"
        ];

        $parsed = PlaceholderApi::parseMultiple($messages, $player);
        foreach ($parsed as $msg) {
            $player->sendMessage($msg);
        }
    }
}

class PlayerKillsPlaceholder extends PlayerPlaceholder
{
    public function __construct(private Main $plugin)
    {
        parent::__construct("player_kills");
    }

    protected function processPlayer(Player $player, ?string $params): string
    {
        // Get kills from your stats system
        return (string)$this->plugin->getKills($player);
    }
}
```

Migration from v1.x
-------------------

[](#migration-from-v1x)

All v1.x code continues to work! The old API is fully supported:

```
// Old way (still works)
PlaceholderApi::registerPlaceholder('my_placeholder', function($player) {
    return "value";
});

// New way (recommended)
PlaceholderApi::registerPlaceholder(
    'my_placeholder',
    fn(?Player $player, ?string $params): string => "value",
    requiresPlayer: false,
    supportsParameters: false
);
```

Best Practices
--------------

[](#best-practices)

1. **Initialize first** - Always call `PlaceholderApi::initialize()` in `onEnable()` before registering placeholders
2. **Use class-based placeholders** for complex logic (easier to test &amp; maintain)
3. **Always validate player null** in player-specific placeholders
4. **Clean up on disable** - unregister your placeholders in `onDisable()`
5. **Use parameters** for flexibility - one placeholder can handle multiple cases
6. **Handle errors gracefully** - wrap risky operations in try-catch

Credits
-------

[](#credits)

Originally created for the Kyro core by Pupggers. Refactored to v2.0 with improved architecture and type safety.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance64

Regular maintenance activity

Popularity5

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 83.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

3

Last Release

219d ago

Major Versions

1.1.0 → 2.0.02025-10-11

### Community

Maintainers

![](https://www.gravatar.com/avatar/46732f92d240874fa56b1adba695cf975523eed14d00e3d669ee584aa8ada2ad?d=identicon)[Pupggerss](/maintainers/Pupggerss)

---

Top Contributors

[![Pupggerss](https://avatars.githubusercontent.com/u/164761956?v=4)](https://github.com/Pupggerss "Pupggerss (10 commits)")[![poggit-bot](https://avatars.githubusercontent.com/u/22427965?v=4)](https://github.com/poggit-bot "poggit-bot (2 commits)")

---

Tags

apiplaceholderpocketminevirion

### Embed Badge

![Health badge](/badges/pup-placeholderapi/health.svg)

```
[![Health](https://phpackages.com/badges/pup-placeholderapi/health.svg)](https://phpackages.com/packages/pup-placeholderapi)
```

###  Alternatives

[m165437/laravel-blueprint-docs

API Blueprint Renderer for Laravel

22779.0k](/packages/m165437-laravel-blueprint-docs)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
