meita/shams 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

meita/shams

最新稳定版本:1.0.0

Composer 安装命令:

composer require meita/shams

包简介

Shams template engine: Blade-style PHP views with .shams templates and component support.

README 文档

README

Shams is a Blade-style PHP template engine with .shams templates, reusable components, and a compact, dependency-free core.

Features

  • Blade-like syntax: @if, @foreach, @extends, @section, @include, @component, stacks, and more.
  • HTML-escaped and raw echo tags: {{ }} and {!! !!}.
  • Bootstrap 5-friendly built-in components with attribute bags and slots.
  • Component tags like <x-alert> and <x-slot>.
  • View composers and shared data.
  • Optional cache auto-reload for a fast dev loop.
  • Helpers like @csrf, @method, @json, @asset, @once, @env, and attribute helpers.

Installation

composer require meita/shams

Frontend Dependencies (Bootstrap 5, jQuery, DataTables, Select2)

Shams does not bundle CSS/JS. Use your own build pipeline or drop in CDNs. DataTables and Select2 require jQuery.

CDN (quick start)

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/datatables.net-bs5@1.13.8/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet">

<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/datatables.net@1.13.8/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/datatables.net-bs5@1.13.8/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
  $(function () {
    $('.datatable').DataTable();
    $('.select2').select2();
  });
</script>

npm (optional)

npm i bootstrap@5 jquery datatables.net datatables.net-bs5 select2

Quick Start

<?php

require __DIR__ . '/vendor/autoload.php';

use Meita\Shams\Shams;

$shams = new Shams([
    'views_path' => __DIR__ . '/views',
    'cache_path' => __DIR__ . '/storage/shams-cache',
    'components_path' => __DIR__ . '/components',
    'asset_url' => '/assets',
    'csrf_token' => $_SESSION['_token'] ?? '',
    'env' => getenv('APP_ENV') ?: 'production',
]);

echo $shams->render('home', [
    'title' => 'Hello Shams',
    'user' => ['name' => 'Mohamed'],
]);

Templates live in .shams files:

views/
  home.shams
  layouts/
    app.shams

Template Basics

Echo and Raw Echo

<h1>{{ $title }}</h1>
<p>{!! $html !!}</p>

Comments

{{-- This will not render --}}

PHP Blocks

@php
    $now = date('Y-m-d');
@endphp

Control Structures

@if($user)
  Hello {{ $user['name'] }}
@elseif($guest)
  Hello guest
@else
  Hello friend
@endif

@unless($isAdmin)
  <p>Standard user</p>
@endunless

@foreach($items as $item)
  <li>{{ $item }}</li>
@endforeach

@for($i = 0; $i < 3; $i++)
  <span>{{ $i }}</span>
@endfor

@while($loading)
  <span>Loading...</span>
@endwhile

@switch($status)
  @case('active')
    Active
    @break
  @default
    Unknown
@endswitch

Loop helper $loop is available in @foreach:

@foreach($items as $item)
  <div class="{{ $loop->first ? 'first' : '' }}">{{ $item }}</div>
@endforeach

Layouts, Sections, and Yields

views/layouts/app.shams

<html>
  <head>
    <title>@yield('title', 'Shams')</title>
  </head>
  <body>
    @yield('content')
  </body>
</html>

views/home.shams

@extends('layouts.app')

@section('title', 'Home Page')

@section('content')
  <h1>Welcome</h1>
  @parent
@endsection

Stacks

@push('scripts')
  <script src="/app.js"></script>
@endpush

@prepend('scripts')
  <script src="/vendor.js"></script>
@endprepend

@stack('scripts')

Includes

@include('partials.nav')
@include('partials.nav', ['active' => 'home'])
@includeIf('partials.optional')
@includeWhen($showPromo, 'partials.promo', ['discount' => 20])
@includeFirst(['partials.a', 'partials.b'])

@each('partials.item', $items, 'item', 'partials.empty')

Components

Tag Components

<x-alert type="success">
  <x-slot name="title">Saved</x-slot>
  Profile updated successfully.
</x-alert>

<x-button variant="primary">Save</x-button>
<x-badge variant="info">New</x-badge>

Directive Components

@component('alert', ['type' => 'warning'])
  @slot('title')
    Heads up
  @endslot

  Check your input.
@endcomponent

Built-in Components

Shams ships with ready-to-use components (from resources/components):

  • UI: alert, button, badge, card, datatable
  • Forms: form, input, textarea, select, checkbox, radio, switch, file, range, color, input-group, label, fieldset, datalist, option, optgroup, output

Form Components (Bootstrap 5)

<x-form action="/users" method="POST">
  <x-input name="name" label="Full name" placeholder="Enter your name" required />
  <x-input type="email" name="email" label="Email" placeholder="you@example.com" />
  <x-textarea name="bio" label="Bio" rows="4"></x-textarea>

  <x-select name="status" label="Status" placeholder="Choose status">
    <option value="active">Active</option>
    <option value="paused">Paused</option>
  </x-select>

  <x-checkbox name="agree" label="I agree to the terms" checked />

  <x-radio name="role" value="admin" label="Admin" />
  <x-radio name="role" value="user" label="User" />

  <x-switch name="notifications" label="Enable notifications" />

  <x-file name="avatar" label="Profile photo" />

  <x-range name="volume" label="Volume" min="0" max="100" value="50" />

  <x-color name="theme" label="Theme color" value="#0d6efd" />

  <x-input-group prepend="$" append=".00">
    <x-input name="price" type="number" :wrapper="false" />
  </x-input-group>

  <x-button type="submit" variant="primary">Save</x-button>
</x-form>

Useful options (available on most form components):

  • label, help, state (valid or invalid), feedback
  • size (sm or lg), wrapper (true or false), wrapperClass
  • floating (true) for floating labels on inputs/textareas/selects

Datalist and Output

<x-input name="city" label="City" list="cities" />
<x-datalist id="cities">
  <x-option value="Cairo">Cairo</x-option>
  <x-option value="Alexandria">Alexandria</x-option>
</x-datalist>

<x-output label="Calculated total" :value="$total"></x-output>

DataTables Component

<x-datatable class="table-bordered">
  <x-slot name="head">
    <tr>
      <th>#</th>
      <th>Name</th>
      <th>Email</th>
    </tr>
  </x-slot>
  <tr>
    <td>1</td>
    <td>Mohamed</td>
    <td>maa1987@hotmail.com</td>
  </tr>
</x-datatable>

Disable DataTables behavior:

<x-datatable :datatable="false">
  ...
</x-datatable>

Select2 Component

<x-select name="status" placeholder="Choose status">
  <option value="active">Active</option>
  <option value="paused">Paused</option>
</x-select>

Disable Select2 behavior:

<x-select name="status" :select2="false">
  ...
</x-select>

Component Attributes

Attributes are passed into a component attribute bag:

<x-button class="w-100" variant="primary">Save</x-button>

Inside the component:

<button {{ $attributes->merge(['class' => 'btn btn-primary']) }}>
  {!! $slot !!}
</button>

Custom Component Views

$shams->addComponentPath(__DIR__ . '/components');

components/notice.shams

<div class="notice notice-{{ $type ?? 'info' }}">
  {!! $slot !!}
</div>

Use it:

<x-notice type="info">Hello</x-notice>

Class-based Components

use Meita\Shams\Component;

class ProfileCard extends Component
{
    public function data(): array
    {
        return ['title' => 'User'];
    }

    public function render(): string
    {
        return 'components.profile-card';
    }
}

$shams->registerComponentClass('profile-card', ProfileCard::class);

View Composers

$shams->composer('profile.*', function (string $view, array $data, Shams $shams): array {
    return ['nav' => ['home', 'settings']];
});

Custom Directives

$shams->registerDirective('datetime', function (?string $expression): string {
    $expression = $expression ?: 'time()';
    return "<?php echo date('Y-m-d H:i', {$expression}); ?>";
});
Last updated: @datetime($updatedAt)

Utility Directives

@csrf
@method('PUT')
@json($payload)
@asset('css/app.css')
@env('local')
  <p>Local mode</p>
@endenv

@checked($isActive)
@selected($isSelected)
@disabled($isDisabled)
@readonly($isReadonly)
@required($isRequired)

@once
  <script src="/only-once.js"></script>
@endonce

@set('title', 'Dashboard')

Rendering Strings

echo $shams->renderString('<h1>{{ $title }}</h1>', ['title' => 'Inline']);

Configuration Options

$config = [
    'views_path' => __DIR__ . '/views',
    'view_paths' => [__DIR__ . '/views', __DIR__ . '/modules'],
    'cache_path' => __DIR__ . '/storage/shams-cache',
    'extension' => '.shams',
    'components_path' => __DIR__ . '/components',
    'use_builtin_components' => true,
    'auto_reload' => true,
    'debug' => false,
    'asset_url' => '/assets',
    'csrf_token' => $_SESSION['_token'] ?? '',
    'env' => getenv('APP_ENV') ?: 'production',
];

New Ideas Included

  • Inline templates via renderString for CMS or database-stored views.
  • Component tags with slot support, plus attribute bags for clean HTML composition.
  • View composers for shared data injection without polluting controllers.
  • Bootstrap-ready components plus DataTables and Select2 friendly defaults.
  • Helper directives for common HTML attributes and request security.

Tips

  • Use @verbatim ... @endverbatim to prevent Blade parsing inside blocks.
  • Use {!! !!} only for trusted HTML.
  • Turn off auto_reload in production for faster renders.

License

MIT

统计信息

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

GitHub 信息

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

其他信息

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