PHPackages                             onspli/chess - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. onspli/chess

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

onspli/chess
============

PHP library for reading and editing FEN and PGN chess formats.

v0.2.0(4y ago)41.6k↑26.2%1MITPHPPHP ^7.2|^8.0

Since Sep 18Pushed 4y ago1 watchersCompare

[ Source](https://github.com/onspli/chess)[ Packagist](https://packagist.org/packages/onspli/chess)[ RSS](/packages/onspli-chess/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (2)Dependencies (4)Versions (3)Used By (0)

onspli/chess
============

[](#onsplichess)

PHP library for reading and editing FEN and PGN chess formats.

[![build](https://github.com/onspli/chess/actions/workflows/build.yml/badge.svg)](https://github.com/onspli/chess/actions/workflows/build.yml/badge.svg) [![license](https://camo.githubusercontent.com/f00d1046ce10f8e8f563e85ff31859c4aad8f7d7369f0334e8af4348e27275ef/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6f6e73706c692f63686573733f6c6162656c3d6c6963656e7365)](https://github.com/onspli/chess/blob/master/LICENSE) [![coverage](https://camo.githubusercontent.com/9dea4f8200830bc5018f048c64998fafd2544171524c8b3e0fcdc0d4e8534653/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6f6e73706c692f63686573732f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/onspli/chess?branch=master) [![maintainability](https://camo.githubusercontent.com/acf8762bf8c5d96b203d58e242b9a5f4edec5ec42a76471c289498ea90f761cf/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f34633266376161663536336131663439326332312f6d61696e7461696e6162696c697479)](https://codeclimate.com/github/onspli/chess/maintainability) [![last commit](https://camo.githubusercontent.com/53c31c78654b20a0c375d7c66d2994b0c6ccc34dba4a3f39657f40db5ada074d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6f6e73706c692f6368657373)](https://github.com/onspli/chess)

Features
--------

[](#features)

### FEN class

[](#fen-class)

- load FEN representing chess position (standard or Shredder-FEN)
- read and modify all FEN fields
- export FEN
- read and set piece placement
- get or set piece on any square
- test position for check, mate, stalemate
- test position for fifty-move rule
- perform move in given position
- test if move is legal in given position
- list all legal moves in given position
- supports Fisher's random (Chess960)

### PGN class

[](#pgn-class)

- load PGN representing chess game
- read and set all tag pairs (PGN headers)
- export PGN
- read and add moves
- get FEN position after any move
- supports Fisher's random (Chess960)

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

[](#installation)

Install with composer:

```
composer require onspli/chess

```

Usage
-----

[](#usage)

Read complete auto-generated [documentation](docs) or learn from the following examples.

Setup chess board to starting position and read FEN fields.

```
$fen = new Onspli\Chess\FEN;
echo($fen->export());
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
echo($fen->export_short());
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -
echo($fen->get_board());
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
echo($fen->get_active_color());
// w
echo($fen->get_castling());
// KQkq
echo($fen->get_en_passant());
// -
echo($fen->get_halfmove());
// 0
echo($fen->get_fullmove());
// 1
echo($fen->preview());
/*
rnbqkbnr
pppppppp
........
........
........
........
PPPPPPPP
RNBQKBNR
*/
```

Initialize custom position and read FEN fields.

```
$fen = new Onspli\Chess\FEN('rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQq c6 1 2');
echo($fen->export());
// rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQq c6 1 2
echo($fen->export_short());
// rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQq c6
echo($fen->get_board());
// rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR
echo($fen->get_active_color());
// b
echo($fen->get_castling());
// KQq
echo($fen->get_en_passant());
// c6
echo($fen->get_halfmove());
// 1
echo($fen->get_fullmove());
// 2
echo($fen->preview());
/*
rnbqkbnr
pp.ppppp
........
..p.....
....P...
........
PPPP.PPP
RNBQKBNR
*/
```

Manipulate with pieces.

```
$fen = new Onspli\Chess\FEN;
echo($fen->get_square('a1'));
// R
$fen->set_square('a1', '');
$fen->set_square('a3', 'R');
echo($fen->preview());
/*
rnbqkbnr
pppppppp
........
........
........
R.......
PPPPPPPP
.NBQKBNR
*/
```

Each of the fields can be set with the corresponding setter:

```
$fen = new Onspli\Chess\FEN;
echo($fen->export());
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
$fen->set_board('rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR');
$fen->set_active_color('b');
$fen->set_castling('KQq');
$fen->set_en_passant('c6');
$fen->set_halfmove(1);
$fen->set_fullmove(2);
echo($fen->export());
// rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR b KQq c6 1 2
echo($fen->preview());
/*
rnbqkbnr
pp.ppppp
........
..p.....
....P...
........
PPPP.PPP
RNBQKBNR
*/
```

Perform moves:

```
$fen = new Onspli\Chess\FEN;
echo($fen->preview());
/*
rnbqkbnr
pppppppp
........
........
........
........
PPPPPPPP
RNBQKBNR
*/
$fen->move('e4');
$fen->move('g6');
$fen->move('Nf3');
$fen->move('Nf6');
$fen->move('Bc4');
$fen->move('Bg7');
$fen->move('O-O');
$fen->move('O-O');
echo($fen->preview());
/*
rnbq.rk.
ppppppbp
.....np.
........
..B.P...
.....N..
PPPP.PPP
RNBQ.RK.
*/
echo($fen->export());
// rnbq1rk1/ppppppbp/5np1/8/2B1P3/5N2/PPPP1PPP/RNBQ1RK1 w - - 6 5
```

Test check, mate, stalemate:

```
$fen = new Onspli\Chess\FEN;
$fen->set_active_color('w');
$fen->set_board('1q5k/8/8/8/8/8/8/K7');
$fen->set_castling('-');
echo($fen->is_check() ? 'true' : 'false');
// false
echo($fen->is_stalemate() ? 'true' : 'false');
// false
echo($fen->preview());
/*
.q.....k
........
........
........
........
........
........
K.......
*/
$fen->move('Ka2');
$fen->move('Qa8');
echo($fen->is_check() ? 'true' : 'false');
// true
echo($fen->is_mate() ? 'true' : 'false');
// false
echo($fen->preview());
/*
q......k
........
........
........
........
........
K.......
........
*/
```

List all possible moves:

```
$fen = new Onspli\Chess\FEN;
$fen->move('e4');
$fen->move('g6');
echo($fen->preview());
/*
rnbqkbnr
pppppp.p
......p.
........
....P...
........
PPPP.PPP
RNBQKBNR
*/
print_r($fen->get_legal_moves());
/*
Array
(
    [0] => a4
    [1] => a3
    [2] => b4
    [3] => b3
    [4] => c4
    [5] => c3
    [6] => d4
    [7] => d3
    [8] => f4
    [9] => f3
    [10] => g4
    [11] => g3
    [12] => h4
    [13] => h3
    [14] => e5
    [15] => Nc3
    [16] => Na3
    [17] => Ne2
    [18] => Nh3
    [19] => Nf3
    [20] => Be2
    [21] => Bd3
    [22] => Bc4
    [23] => Bb5
    [24] => Ba6
    [25] => Qe2
    [26] => Qf3
    [27] => Qg4
    [28] => Qh5
    [29] => Ke2
)

*/
```

Load game in PGN notation and read tags and moves:

```
$pgn = new Onspli\Chess\PGN('[Event "Testing"] 1.Nf3 Nf6 2.c4 g6');
echo($pgn->get_tag('Event'));
// Testing
echo($pgn->get_halfmove(2));
// Nf6
echo($pgn->get_initial_halfmove_number());
// 1
echo($pgn->get_last_halfmove_number());
// 4
```

Record new moves, add tags and export PGN:

```
$pgn = new Onspli\Chess\PGN('[Event "Testing"] 1.Nf3 Nf6 2.c4 g6');
$pgn->set_tag('Site', 'Github');
$pgn->move('a4');
$pgn->move('a5');
print_r($pgn->get_tags());
/*
Array
(
    [Event] => Testing
    [Site] => Github
)

*/
echo($pgn->export_tags());
/*
[Event "Testing"]
[Site "Github"]

*/
echo($pgn->export_movetext());
// 1. Nf3 Nf6 2. c4 g6 3. a4 a5
echo($pgn->export());
/*
[Event "Testing"]
[Site "Github"]
1. Nf3 Nf6 2. c4 g6 3. a4 a5
*/
```

Extract position after certain move:

```
$pgn = new Onspli\Chess\PGN('1.Nf3 Nf6 2.c4 g6');
echo($pgn->get_current_fen());
// rnbqkb1r/pppppp1p/5np1/8/2P5/5N2/PP1PPPPP/RNBQKB1R w KQkq - 0 3
echo($pgn->get_initial_fen());
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
echo($pgn->get_fen_after_halfmove(0));
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
echo($pgn->get_fen_after_halfmove(2));
// rnbqkb1r/pppppppp/5n2/8/8/5N2/PPPPPPPP/RNBQKB1R w KQkq - 2 2
echo($pgn->get_fen_after_halfmove(Onspli\Chess\PGN::get_halfmove_number(1, 'b')));
// rnbqkb1r/pppppppp/5n2/8/8/5N2/PPPPPPPP/RNBQKB1R w KQkq - 2 2
```

FEN is returned as `string` by default. Passing parameter `$as_object = true` makes it FEN object:

```
$pgn = new Onspli\Chess\PGN('1.Nf3 Nf6 2.c4 g6');
echo($pgn->get_current_fen(true)->preview());
/*
rnbqkb.r
pppppp.p
.....np.
........
..P.....
.....N..
PP.PPPPP
RNBQKB.R
*/
echo($pgn->get_fen_after_halfmove(2, true)->preview());
/*
rnbqkb.r
pppppppp
.....n..
........
........
.....N..
PPPPPPPP
RNBQKB.R
*/
```

PGN with custom initial position:

```
$pgn = new Onspli\Chess\PGN('[FEN "rnbqkb1r/pppp1ppp/5n2/4p3/2P1P3/5N2/PP1P1PPP/RNBQKB1R b KQkq - 0 3"] 3... Nc6 4. Qb3');
echo($pgn->get_initial_fen());
// rnbqkb1r/pppp1ppp/5n2/4p3/2P1P3/5N2/PP1P1PPP/RNBQKB1R b KQkq - 0 3
echo($pgn->get_initial_halfmove_number());
// 6
echo($pgn->get_halfmove(6));
// Nc6
```

###  Health Score

28

—

LowBetter than 52% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~251 days

Total

2

Last Release

1499d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/413b99f734b277cbf822e1726f13864540b9ae61e5dfe18154507605dc1af4ab?d=identicon)[onspli](/maintainers/onspli)

---

Top Contributors

[![onspli](https://avatars.githubusercontent.com/u/7120489?v=4)](https://github.com/onspli "onspli (138 commits)")

---

Tags

chessfenpgnphp

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/onspli-chess/health.svg)

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

###  Alternatives

[epartment/nova-dependency-container

A Laravel Nova field container allowing to depend on other fields values

3834.6M13](/packages/epartment-nova-dependency-container)

PHPackages © 2026

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