Sharp for Laravel

repository·9.x·Indexed 21 days ago

https://github.com/code16/sharp

A content management framework for Laravel that provides a code-driven approach to managing structured data and building CMS interfaces without writing front-end code. It features structured data management, data interaction (search, sort, filter), and a flexible command system including Entity, Instance, and multi-step Wizard commands. Sharp is data-agnostic and requires PHP 8.3+ and Laravel 11+.

Tokens
134K
Snippets
434
Records
547
Agent score
73%

What's inside sharp

  1. Overview of Sharp for Laravel

    9.x

    Sharp is a content management framework designed specifically as a Laravel package. It allows developers to build CMS sections with a clean UI and developer experience (DX) without writing front-end code.

    Key capabilities include:

    • Structured Data Management: Create, update, or delete data with built-in validation and error handling.
    • Data Interaction: Display, search, sort, and filter data.
    • Command Execution: Run custom commands on single instances, selections, or all instances.
    • Security: Integrated authorization and validation handling.

    Sharp is data-agnostic, meaning it does not dictate your persistence layer, and it follows standard Laravel conventions and coding styles.

  2. Overview of Sharp Content Management Framework

    9.x

    Sharp is a content management framework built as a Laravel package. It is designed to help developers build CMS sections with a clean UI and developer experience (DX).

    Key characteristics include:

    • Code-driven: Everything is managed through a documented PHP API following Laravel conventions.
    • Data-agnostic: It has no expectations regarding your persistence layer.
    • Decoupled: It avoids hard-coded adherence to specific business logic, allowing the project to remain independent of the core application logic.

    Sharp 9 is built using Laravel, Tailwind CSS, Inertia, Vue, and Alpine.JS.

  3. What is an Entity class in Sharp

    9.x

    An entity is a data structure representing a meaningful concept in your application (e.g., Person, Post, or Order). While often mapping to a Model, an entity can represent a portion of a Model or multiple Models.

    The entity class is the central configuration point where you define how that entity is presented in the application, including its List, Form, Show page, and authorization policies.

  4. Authorize and restrict reordering actions

    9.x

    Reordering is governed by permissions and can be conditionally disabled based on the state of the list.

    Permissions

    The reorder action requires the reorder permission. This should be defined in your Entity Policy.

    Conditional Disabling

    You can prevent the reorder action from appearing or being available by calling $this->disableReorder(bool $condition) within your getListData() method. This is useful for restricting reordering when certain filters or search terms are active.

    class PostList extends SharpEntityList
    {
        public function getListData(): array|Arrayable
        {
            // Disable reordering if a search is currently active
            $this->disableReorder($this->queryParams->hasSearch());
            
            // ...
        }
    }
  5. Format data for SharpFormListField

    9.x

    The SharpFormListField uses specific formatting methods to handle data flow:

    • toFront: Expects an array or a Collection of models. Each model must contain attributes corresponding to the keys defined in the list items (e.g., id, title, etc.) so the field formatters can process them.
    • fromFront: Returns an array with the same shape as the input. Note that newly added items will have a null id.
  6. What are entities and instances in Sharp?

    9.x

    In Sharp, an entity is a data structure with application context (e.g., Person, Post, or Order). While optimized for Eloquent Models, an entity is not strictly a 1-1 relationship with a Model; it can represent a portion of a Model or multiple Models.

    An instance is a single occurrence of an entity.

    Entities are typically surfaced in three ways:

    1. Entity List: A collection of instances supporting sorting, filtering, pagination, search, commands (applied to instances or lists), and state management.
    2. Show Page: An optional detailed view of a specific instance.
    3. Form: A UI for creating or updating an instance.
  7. Use Commands in a Dashboard

    9.x

    Dashboards support commands with a slightly different API than Entity or Show Page commands:

    • No distinction between Instance and Entity: Commands are context-agnostic within the dashboard.
    • Base Class: A dashboard command handler must extend Code16\Sharp\Dashboard\Commands\DashboardCommand.
    • Return Actions: A Dashboard Command cannot return a refresh() action because there is no specific instance context to refresh.
  8. How custom embeds work in the Editor

    9.x

    Custom embeds allow you to insert structured data (like a reference to another model) into the editor content.

    1. Create a class that extends Code16\Sharp\Form\Fields\Embeds\SharpFormEditorEmbed.
    2. Register the embed class using allowEmbeds([ClassName::class]) on the SharpFormEditorField instance.
    3. The embed can then be added to the toolbar by including its class name in the setToolbar() array.
  9. Interact with Sharp's Breadcrumb

    9.x

    You can navigate or inspect the breadcrumb trail using sharp()->context()->breadcrumb(). This returns a breadcrumb context that allows you to inspect segments.

    Breadcrumb methods:

    • currentSegment(): BreadcrumbItem: Gets the current breadcrumb item.
    • previousSegment(): BreadcrumbItem: Gets the previous breadcrumb item.
    • previousShowSegment(?string $entityKeyOrClassName = null, ?string $subEntity = null): ?BreadcrumbItem: Gets the closest preceding Show segment. It is recommended to use the entity class name (e.g., MyEntity::class) instead of the entity key.
    • previousListSegment(?string $entityKeyOrClassName = null): ?BreadcrumbItem: Gets the closest preceding List segment.

    BreadcrumbItem methods: A BreadcrumbItem provides the same context methods as SharpContext (entityKey(), isEntityList(), isShow(), isForm(), isUpdate(), isCreation(), instanceId()) plus:

    • entityIs(string $entityKeyOrClassName, ?string $subEntity = null): bool: Checks if the segment matches a specific entity or sub-entity.
    // Example: Using breadcrumb to find a parent Post ID when creating a Comment
    class CommentForm extends SharpForm
    {
        function update($id, array $data)
        {
            $comment = $id 
                ? Comment::find($id) 
                : new Comment([
                    'post_id' => sharp()->context()
                        ->breadcrumb()
                        ->previousShowSegment(PostEntity::class)
                        ->instanceId()
                ]);
    
            $this->save($comment, $data);
            return $comment->id;
        }
    }
  10. Access query parameters in EntityList and Dashboard

    9.x

    In Sharp 7.x, query parameters are no longer passed as arguments to data-building methods. Instead, they are available as instance properties on the object itself.

    • EntityList: Replace the $params argument in getListData() with $this->queryParams.
    • Dashboard: Replace the $params argument in buildWidgetsData() with $this->queryParams.

    This change allows you to easily build components based on the current request (e.g., hiding specific columns).

  11. Use SharpFormAutocompleteListField for N-N relationships

    9.x

    The SharpFormAutocompleteListField is used to build a list where each item contains exactly one field: an Autocomplete. This is specifically useful for handling Many-to-Many (belongsToMany) relationships where a standard List (designed for hasMany) would not suffice. Each item in the list is represented by a single Autocomplete field that handles the entire item object.

    SharpFormAutocompleteListField::make('winners')
            ->setLabel('Winners')
            ->setItemField(
                SharpFormAutocompleteRemoteField::make('item')
                    ->setRemoteEndpoint('/players')
                    // [...]
            )
    );
  12. Access related attributes using the `:` separator

    9.x

    You can reference nested attributes (e.g., $post->author->name) in field definitions using the : separator. The transform() method will interpret this separator to resolve the deep attribute path.

    Usage in Entity Lists: Use EntityListDataContainer::make('relation:attribute').

    Usage in Forms: Use field components like SharpFormTextField::make('relation:attribute').

    // In an Entity List field definition
    $fields->addField(
        EntityListDataContainer::make('author:name')
            ->setLabel('Author')
    );
    
    // In a Form field definition
    $formFields->addField(
        SharpFormTextField::make('picture:legend')
            ->setLabel('Legend')
    );