Skip to content

Miscellaneous Packages

Miscellaneous packages providing specialized utilities.

Lightweight XML to PHP array conversion.

  • DOM-based XML parsing
  • Automatic type casting
  • CDATA and attribute handling
  • Nil element support
use RightCapital\XmlParser\XmlParser;
$xml = <<<'XML'
<root>
<scalar>apple</scalar>
<empty/>
<cdata><![CDATA[<foo></bar>]]></cdata>
</root>
XML;
$array = XmlParser::toArray($xml);
// [
// 'scalar' => 'apple',
// 'empty' => null,
// 'cdata' => '<foo></bar>',
// ]
XML AttributePHP Type
type="decimal"float
type="integer"int
type="*"string
nil="true"null
  • Attributes: Stored under @attributes key
  • Content with attributes: Stored under @content key
  • Repeated elements: Grouped into arrays
$xml = '<root id="1"><item>a</item><item>b</item></root>';
$array = XmlParser::toArray($xml);
// [
// '@attributes' => ['id' => '1'],
// 'item' => ['a', 'b'],
// ]
  • ext-dom, ext-libxml
  • thecodingmachine/safe

Database schema manipulation and ENUM column management.

  • Column repositioning
  • ENUM value management
  • MySQL privilege SQL generation
use RightCapital\LaravelDatabaseTools\DataDefinitionLanguageManager;
$manager = new DataDefinitionLanguageManager('users');
// Move column to first position
$sql = $manager->generateMoveColumnToFirstSql('email');
DB::statement($sql);
// Move columns after targets
$sql = $manager->generateMoveColumnAfterTargetColumnSql([
'phone' => 'email', // phone after email
'address' => 'phone', // address after phone
]);
DB::statement($sql);
use RightCapital\LaravelDatabaseTools\EnumColumnManager;
$enum = new EnumColumnManager('orders', 'status');
// Get current options
$options = $enum->getEnumOptions(); // ['pending', 'completed']
// Add new options
$newOptions = $enum->getAddEnumOptionsString(['cancelled', 'refunded']);
// Delete options
$remaining = $enum->getDeleteEnumOptions(['pending']);
// Rename values with data migration
$enum->renameEnumOptions([
'pending' => 'pending_review',
'completed' => 'finished',
]);
// Safely: expands → migrates data → contracts
use RightCapital\LaravelDatabaseTools\GrantPrivilegesSqlsGenerator;
$privileges = [
'users' => [
'SELECT',
'INSERT' => ['id', 'email'], // Column-specific
'UPDATE' => '*',
],
'logs' => 'SELECT',
];
$sqls = GrantPrivilegesSqlsGenerator::generateSqls(
$privileges,
'production_db',
'app_user',
'app-server.local'
);
foreach ($sqls as $sql) {
DB::statement($sql);
}
  • illuminate/database, illuminate/support

Aspect-Oriented Programming via PHP attributes.

  • Declarative method decoration
  • Composable delegate chains
  • Built-in delegates: Cache, Retry, Transactional, RescueFrom, Once
use RightCapital\LaravelAop\Cache;
class UserService {
#[Cache(key: 'user.list', ttl: 3600)]
public function listUsers(): array {
return User::all()->toArray();
}
#[Cache(
key: [self::class, 'userCacheKey'],
ttl: 7200,
tags: ['users']
)]
public function getUser(int $id): array {
return User::find($id)?->toArray() ?? [];
}
private function userCacheKey(Cache $delegate, array $args): string {
return 'user.profile.' . $args[0];
}
}
use RightCapital\LaravelAop\Retry;
class ApiClient {
#[Retry(
times: 3,
sleep_ms: [100, 500, 1000], // Exponential backoff
)]
public function fetchData(): array {
return Http::get('/api/data')->json();
}
#[Retry(
times: 5,
sleep_ms: 200,
when: HttpException::class
)]
public function postData(array $payload): array {
return Http::post('/api', $payload)->json();
}
}
use RightCapital\LaravelAop\Transactional;
class OrderService {
#[Transactional]
public function createOrder(array $items): Order {
$order = Order::create(['status' => 'pending']);
foreach ($items as $item) {
$order->items()->create($item);
}
return $order;
}
#[Transactional(attempts: 3, connection: 'secondary')]
public function syncToSecondary(Order $order): void {
// Transaction with retries on secondary connection
}
}
use RightCapital\LaravelAop\RescueFrom;
class PaymentProcessor {
#[RescueFrom(
exception: PaymentException::class,
as: null,
report: true
)]
public function process(float $amount): ?string {
return $this->gateway->charge($amount);
}
#[RescueFrom(
exception: [PaymentException::class, TimeoutException::class],
as: [self::class, 'handleFailure'],
report: [self::class, 'shouldReport']
)]
public function charge(string $token): array {
return $this->gateway->charge($token);
}
private function handleFailure(Throwable $e, string $token): array {
return ['success' => false, 'reason' => 'unavailable'];
}
private function shouldReport(Throwable $e): bool {
return !$e instanceof PaymentException;
}
}
use RightCapital\LaravelAop\Once;
class DatabaseSeeder {
#[Once]
public function seedAdmin(): User {
// Executes only once per request
return User::firstOrCreate(['role' => 'admin']);
}
}
// Usage
$seeder = new DatabaseSeeder();
$admin1 = $seeder->seedAdmin(); // Executes
$admin2 = $seeder->seedAdmin(); // Returns cached result
use RightCapital\LaravelAop\DI;
class LoggingDelegate extends Delegate {
public function __construct(private Logger $logger) {}
public function __invoke(mixed ...$args): mixed {
$this->logger->info("Calling {$this->method_name}");
return ($this->next)(...$args);
}
}
class UserController {
#[DI(LoggingDelegate::class)]
public function store(Request $request): Response {
// Logged via DI-resolved delegate
}
}
class ReportingService {
#[Transactional]
#[Retry(times: 2)]
#[Cache(key: 'report.monthly', ttl: 86400)]
public function generateReport(int $month): Report {
// Execution order (outermost first):
// 1. Check cache
// 2. Retry up to 2 times
// 3. Wrap in transaction
// 4. Execute method
}
}
  • rightcapital/method-delegate
  • illuminate/container, illuminate/support

PackageTypePurpose
xml-parserUtilityXML → Array conversion
laravel-database-toolsUtilitySchema manipulation, ENUM management
laravel-aopFrameworkAspect-oriented programming