定制 shmandalf/excelentor 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

shmandalf/excelentor

Composer 安装命令:

composer require shmandalf/excelentor

包简介

A wizard-grade PHP library that turns boring spreadsheets into elegant PHP objects. Cast spells on Excel/CSV files to automatically parse, map, and hydrate data into strongly-typed object collections.

README 文档

README

Caution

🏛️ ARCHIVED PROJECT

This project is maintained for legacy purposes only. My engineering focus has shifted toward High-Performance Asynchronous PHP and system architecture.

Looking for speed? Check out my latest work: 🚀 FAST.Atomic.FlowAsynchronous PHP engine powered by Swoole.

Excelentor is a wizard-grade PHP library that transforms mundane spreadsheets into elegant, strongly-typed PHP objects. Cast powerful spells (annotations) upon your DTOs and watch as Excel/CSV files magically hydrate into object collections.

Latest VersionTotal DownloadsTestsLicense

✨ What Sorcery Is This?

Tired of writing the same boring spreadsheet parsing code? Excelentor transforms your Excel/CSV files into strongly-typed PHP objects with just a few magical annotations. No more array indices, no more manual validation, no more type juggling.

<?php
require "./vendor/autoload.php";

use Shmandalf\Excelentor\Attributes\{Header, Column};
use Shmandalf\Excelentor\Parser;
use Shmandalf\Excelentor\ValidatorFactory;

// Excel like column names, can be numeric indexes instead or even skipped
#[Header(columns: ['A' => 'name', 'B' => 'email', 'C' => 'age'])]
class ApprenticeWizard
{
    #[Column(rule: 'required|min:2', mandatory: true)]
    private string $name;

    #[Column(rule: 'required|email')]
    private string $email;

    #[Column]
    private int $age;

    // More magical properties & getters...
    public function getName()
    {
        return $this->name;
    }
}

$spreadsheetData = [
    [
        // header values are ignored here for a reason
        // it can be configured in the Header attribute
        // by passing the $rows argument
        'Some header',
        'Name',
        'Here',
    ],
    // Demo data
    [
        'Melissa',
        'daughter3@example.com',
        45,
    ],
    [
        'Lera',
        'daughter2@example.com',
        46,
    ],
    [
        'Anastasia',
        'daughter1@example.com',
        47,
    ],
    [
        'Dmitry',
        'dshmanatov@gmail.com',
        48,
    ],
];

// Cast the parsing incantation on the ancient scroll!
$parser = new Parser(ApprenticeWizard::class, new ValidatorFactory('ru'));

// Scry for cursed runes and magical anomalies
$errors = $parser->validateAll($spreadsheetData);
// The scroll is pure, magical currents are stable
foreach ($errors as $error) {
    echo "Arcane disturbance: " . $error->getMessage() .
        " at spell line " . $error->getLineNo() . "\n";
}

// Summon entities from the magical parchment!
// Entries with dark enchantments vanish into the mist
$wizards = $parser->parse($spreadsheetData);
foreach ($wizards as $wizard) {
    echo "{$wizard->getName()} has sworn the Oath of Arcana!\n";
}

🆚 Why Not Just array_map?

With Excelentor Without Excelentor
$user->email $row[42]
Automatic validation Manual if-else
Type hints in IDE "What's in index 7 again?"

🧙‍♂️ Magical Prerequisites

  • PHP 8.1+ (The ancient language of wizards)
  • ext-mbstring (For deciphering runes)
  • League/CSV or PhpSpreadsheet (Scroll readers)

🚀 Installation

composer require shmandalf/excelentor

🔮 Features That Feel Like Magic

Annotation-Based Mapping

// Supports excel-style column names
#[Header(columns: ['A' => 'sku', 'B' => 'price', 'C' => 'stock'])]

// You can even skip certain columns if you want
#[Header(columns: ['B' => 'sku', 'AB' => 'stock'])]

// For files without a header row
#[NoHeader(columns: [0 => 'name', 1 => 'email'])]

// Or simply
#[NoHeader(columns: ['name', 'email'])]

Automatic Type Casting

#[Column] public string $name;   // "John" → "John"
#[Column] public int $age;       // "30" → 30
#[Column] public float $price;   // "99.99" → 99.99
#[Column] public bool $active;   // "true" → true
#[Column] public Carbon $date;   // "2023-01-15" → Carbon instance
#[Column] public ?float $score;  // "" → null (nullable!)

Built-In Validation

// not sure about this unique rule yet haha
#[Column(rule: 'required|email|unique:users,email')]
#[Column(rule: 'required|integer|min:18|max:100')]
#[Column(rule: 'required|numeric|min:0|max:999999.99')]

Meaningful Error Messages

Error at line 42 (property 'email'):
"not.an.email" is not a valid email address.

Error at line 87 (property 'age'):
Cannot convert "not a number" to integer.

📚 Quick Start Guide

1. Define Your Data Structure

use Shmandalf\Excelentor\Attributes\{Header, Column};
use Carbon\Carbon;

#[Header(columns: [
    'A' => 'sku',
    'B' => 'name',
    'C' => 'price',
    'D' => 'in_stock',
    'E' => 'created_at'
])]
class ProductImport {
    #[Column(rule: 'required|alpha_dash')]
    public string $sku;

    #[Column(rule: 'required|min:3')]
    public string $name;

    #[Column(rule: 'required|numeric|min:0')]
    public float $price;

    #[Column]
    public bool $in_stock;

    #[Column(format: 'Y-m-d')]
    public Carbon $created_at;
}

2. Parse Your Spreadsheet

use Shmandalf\Excelentor\Parser;
use Shmandalf\Excelentor\ValidatorFactory;

$parser = new Parser(ProductImport::class, new ValidatorFactory());

// From array (Excel/CSV readers)
$data = [
    ['SKU', 'Name', 'Price', 'In Stock', 'Created At'],
    ['PROD-001', 'Laptop', '999.99', 'true', '2023-01-15'],
    ['PROD-002', 'Mouse', '49.50', 'false', '2023-02-20'],
];

// From CSV file (using League\Csv)
// $csv = Reader::createFromPath('products.csv');
// $data = $csv->getRecords();

foreach ($parser->parse($data) as $product) {
    // $product is a fully typed ProductImport object!
    echo "{$product->sku}: {$product->name} - \${$product->price}\n";
}

🏗️ Real-World Examples

E-commerce Product Import

#[Header(columns: [
    'A' => 'sku',
    'D' => 'name',
    'F' => 'price',
    'G' => 'stock',
    'X' => 'active'
])]
class EcommerceImport {
    // unique? :) prolly not now
    #[Column(rule: 'required|unique:products,sku')]
    public string $sku;

    #[Column(rule: 'required|min:3|max:255')]
    public string $name;

    #[Column(rule: 'required|numeric|min:0|decimal:0,2')]
    public float $price;

    #[Column(rule: 'required|integer|min:0')]
    public int $stock;

    #[Column]
    public bool $active;
}

User Registration from CSV

#[NoHeader(columns: [0 => 'email', 1 => 'name', 2 => 'birth_date'])]
class UserRegistration {
    #[Column(rule: 'required|email|unique:users,email')]
    public string $email;

    #[Column(rule: 'required|min:2|max:100')]
    public string $name;

    #[Column(rule: 'required|date|before:today')]
    public Carbon $birth_date;
}

🔧 Advanced Usage

Custom Date Formats

#[Column(format: 'd/m/Y')]       // "15/01/2023" → Carbon
#[Column(format: 'm-d-Y')]       // "01-15-2023" → Carbon
#[Column(format: 'Y年m月d日')]    // "2023年01月15日" → Carbon

Boolean Parsing (Supports Multiple Formats)

#[Column] public bool $flag; // Accepts: true/false, yes/no, 1/0, on/off, да/нет, +/-

Working with Different Data Sources

// From PhpSpreadsheet
$spreadsheet = IOFactory::load('file.xlsx');
$data = $spreadsheet->getActiveSheet()->toArray();

// From League CSV
$csv = Reader::createFromPath('file.csv');
$data = $csv->getRecords();

// From database export
$data = $pdo->query('SELECT * FROM export')->fetchAll(PDO::FETCH_NUM);

// All work with the same parser!

⚡ Performance

Excelentor is built for speed:

  • Zero configuration overhead - annotations are cached
  • Generator-based parsing - memory efficient for large files
#[Header(columns: [...])]
class StrictImport {
    // Parsing stops at first validation error
}

🤝 Contributing

Found a bug? Have a feature request? Contributions are welcome!

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

Excelentor is open-sourced software licensed under the MIT license.

🧙‍♂️ About the Wizard

Excelentor was crafted by Shmandalf during a magical coding session that lasted exactly 21 days. When not parsing spreadsheets, he can be found optimizing database queries and arguing about monads.

"May your types be strong and your exceptions meaningful!"

Ready to transform your spreadsheet chaos into typed harmony?

shmandalf/excelentor 适用场景与选型建议

shmandalf/excelentor 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3 次下载、GitHub Stars 达 3, 最近一次更新时间为 2025 年 12 月 24 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「annotations」 「excel」 「spreadsheet」 「csv」 「parser」 「import」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 shmandalf/excelentor 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 shmandalf/excelentor 我们能提供哪些服务?
定制开发 / 二次开发

基于 shmandalf/excelentor 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 37
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-24