{"id":15714475,"url":"https://github.com/slack-php/slack-php-block-kit","last_synced_at":"2025-04-12T21:25:18.971Z","repository":{"id":37208384,"uuid":"358292134","full_name":"slack-php/slack-php-block-kit","owner":"slack-php","description":"OOP interface for composing Slack Block Kit messages and modals in PHP","archived":false,"fork":false,"pushed_at":"2025-04-01T21:16:46.000Z","size":540,"stargazers_count":50,"open_issues_count":5,"forks_count":16,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T01:06:54.516Z","etag":null,"topics":["block-kit","chatbot","php","slack","slack-block-kit","slack-php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slack-php.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"jeremeamia"}},"created_at":"2021-04-15T14:39:28.000Z","updated_at":"2024-12-28T16:19:19.000Z","dependencies_parsed_at":"2023-12-20T08:40:05.116Z","dependency_job_id":"30a48bc6-52b2-463d-9965-c68dd769b525","html_url":"https://github.com/slack-php/slack-php-block-kit","commit_stats":{"total_commits":101,"total_committers":8,"mean_commits":12.625,"dds":0.1089108910891089,"last_synced_commit":"8fc2cc680e0ed1f24ae88e41de94c090465e5adf"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slack-php%2Fslack-php-block-kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slack-php%2Fslack-php-block-kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slack-php%2Fslack-php-block-kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slack-php%2Fslack-php-block-kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slack-php","download_url":"https://codeload.github.com/slack-php/slack-php-block-kit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248633266,"owners_count":21136844,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["block-kit","chatbot","php","slack","slack-block-kit","slack-php"],"created_at":"2024-10-03T21:37:23.007Z","updated_at":"2025-04-12T21:25:18.946Z","avatar_url":"https://github.com/slack-php.png","language":"PHP","funding_links":["https://github.com/sponsors/jeremeamia"],"categories":[],"sub_categories":[],"readme":"\u003cheader\u003e\n  \u003ch1 align=\"center\"\u003eSlack Block Kit for PHP\u003c/h1\u003e\n  \u003cp align=\"center\"\u003e:point_right: \u003cem\u003eFor formatting messages and modals for Slack using their Block Kit syntax via an OOP interface\u003c/em\u003e :point_left:\u003c/p\u003e\n  \u003cp align=\"center\"\u003eBy Jeremy Lindblom (\u003ca href=\"https://twitter.com/jeremeamia\"\u003e@jeremeamia\u003c/a\u003e)\u003c/p\u003e\n\u003c/header\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://repository-images.githubusercontent.com/358292134/398fbb00-9dbe-11eb-9167-fd67cf034596\" alt=\"Slack logo placed on top of blocks\" width=\"50%\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"http://php.net/\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/code-php%208.1-8892bf.svg\" alt=\"Coded in PHP 8.1\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://packagist.org/packages/slack-php/slack-block-kit\"\u003e\n    \u003cimg src=\"https://img.shields.io/packagist/v/slack-php/slack-block-kit.svg\" alt=\"Packagist Version\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://actions-badge.atrox.dev/slack-php/slack-php-block-kit/goto?ref=main\"\u003e\n    \u003cimg alt=\"Build Status\" src=\"https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fslack-php%2Fslack-php-block-kit%2Fbadge%3Fref%3Dmain\u0026style=flat\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Introduction\n\nFrom Slack's [Block Kit documentation](https://api.slack.com/block-kit):\n\n\u003e **Block Kit** is a UI framework for Slack apps that offers a balance of control and flexibility when building\n\u003e experiences in messages and other _surfaces_.\n\u003e \n\u003e Customize the order and appearance of information and guide users through your app's capabilities by composing,\n\u003e updating, sequencing, and stacking _blocks_ — reusable components that work almost everywhere in Slack.\n\nThis library provides an OOP interface in PHP for composing messages/modals using Slack Block Kit. It also does the\nreverse, meaning you can \"hydrate\" message/modal JSON into an object hierarchy.\n\n## Block Kit Concepts\n\nThis library helps you build Slack messages and modals programmatically and dynamically in your code, but you need to\nknow how they work generally first. The library does try to prevent you from doing things you are not permitted to do\nin Block Kit, but it may not validate against every single or condition.\n\nYou may want to review the following concepts in the Slack documentation:\n\n- [Surfaces](https://api.slack.com/surfaces) – There are 3 main types: Message, Modal, and App Home\n- [Blocks](https://api.slack.com/reference/block-kit/blocks) – Includes _section_, _context_, _actions_, and more\n- [Block Elements](https://api.slack.com/reference/block-kit/block-elements) – Includes buttons, menus, text inputs, and other interactive components. We call all of these \"Elements\" in this library.\n- [Composition Objects](https://api.slack.com/reference/block-kit/composition-objects) – We call these \"Parts\" in the library\n\nIn general, we refer to ALL of these different things in Block Kit collectively as \"components\".\n\n## Installation\n\nInstall easily via Composer:\n\n```bash\ncomposer require slack-php/slack-block-kit\n```\n\nThen include the Composer-generated autoloader in your project's initialization code.\n\n**Note**: This library is built for PHP 8.1+.\n\n_[Version 1](https://github.com/slack-php/slack-php-block-kit/tree/v1) of this library supports version 7.3/7.4._\n\n## Basic Usage\n\nThis library supports an intuitive syntax for composing Slack surfaces (e.g., messages, modals) that utilizes PHP 8's \nnamed parameters feature.\n\n```php\n\u003c?php\n\nuse SlackPhp\\BlockKit\\Surfaces\\Message;\nuse SlackPhp\\BlockKit\\Blocks\\Section;\nuse SlackPhp\\BlockKit\\Blocks\\Divider;\nuse SlackPhp\\BlockKit\\Blocks\\BlockImage;\n\n// ...\n\n// CONSTRUCTION\n$msg = new Message(\n    ephemeral: true,\n    blocks: [\n        new Section('Don\\'t you just love XKCD?'),\n        new Divider(),\n        new BlockImage(\n            title: 'Team Chat',\n            imageUrl: 'https://imgs.xkcd.com/comics/team_chat.png',\n            altText: 'Comic about the stubbornness of some people switching chat clients',\n        ),\n    ]\n);\n\n// VALIDATION\n// Throws a ValidationException if any of the components are invalid or missing required properties.\n$msg-\u003evalidate();\n\n// OUTPUT\n// To convert to JSON (e.g., to send to Slack API, webhook, or response_url), use PHP's `json_encode()` function.\necho json_encode($msg);\n// OR you can use the surfaces's `toJson()` method, which also includes a convenience parameter for pretty printing.\necho $msg-\u003etoJson(true);\n// OR you can just convert to an array and do something else with the data.\nprint_r($msg-\u003etoArray());\n```\n\n### The `Kit` Façade\n\nThe `Kit` class acts as a façade for the whole library's set of components and has factory methods for each one. It\nallows you to limit the number of classes you have to import to build a message (or other surface).\n\nEach factory method has the same parameters as the original component's constructor.\n\n```php\n\u003c?php\n\nuse SlackPhp\\BlockKit\\Kit;\n\n// ...\n\n$msg = Kit::message(\n    ephemeral: true,\n    blocks: [\n        Kit::section('Don\\'t you just love XKCD?'),\n        Kit::divider(),\n        Kit::blockImage(\n            title: 'Team Chat',\n            imageUrl: 'https://imgs.xkcd.com/comics/team_chat.png',\n            altText: 'Comic about the stubbornness of some people switching chat clients',\n        ),\n    ]\n);\n```\n\n### Fluent Interface\n\nIf named parameters aren't your jam, there is another way to set a component's properties, through the setter methods.\nEach component has chainable setter methods for each of its properties, which allows for a fluent-style interface.\n\n```php\n$msg = Kit::message()\n    -\u003eephemeral()\n    -\u003eblocks(\n        Kit::section('Don\\'t you just love XKCD?'),\n        Kit::divider(),\n        Kit::blockImage()\n            -\u003etitle('Team Chat')\n            -\u003eimageUrl('https://imgs.xkcd.com/comics/team_chat.png')\n            -\u003ealtText('Comic about the stubbornness of some people switching chat clients')\n        ),\n    );\n```\n\nThe fluent syntax is not dependent on the `Kit` façade. Component classes have a static `new()` method that can be\nused for chaining as well.\n\n```php\n$msg = Message::new()\n    -\u003eephemeral()\n    -\u003eblocks(\n        Section::new('Don\\'t you just love XKCD?'),\n        Divider::new(),\n        BlockImage::new()\n            -\u003etitle('Team Chat')\n            -\u003eimageUrl('https://imgs.xkcd.com/comics/team_chat.png')\n            -\u003ealtText('Comic about the stubbornness of some people switching chat clients')\n        ),\n    );\n```\n\n#### Null Values\n\nAll properties are considered as null/empty until set.\n\nYou can also set a property explicitly to null to remove its value (e.g., from a component you created from existing data).\n\n```php\n$section-\u003eaccessory(null);\n```\n\nFinally, null values are allowed in lists of blocks, elements, options, etc., so it's safe to use conditional items.\n\n```php\n$msg = Kit::message(\n    blocks: [\n        Kit::section('Don\\'t you just love XKCD?'),\n        ($includeDivider) ? Kit::divider() : null,\n        Kit::blockImage(\n            title: 'Team Chat',\n            imageUrl: 'https://imgs.xkcd.com/comics/team_chat.png',\n            altText: 'Comic about the stubbornness of some people switching chat clients',\n        ),\n    ]\n);\n```\n\n### Preview in Block Kit Builder\n\nSlack provides an [interactive Block Kit Builder](https://app.slack.com/block-kit-builder) for composing/testing\nmessages and other surfaces. This is a great way to play around with and learn the Block Kit format.\n\nThe `Kit::preview` method allows you to render your message/surface as a Block Kit Builder URL, so you can link to a\npreview or your message/surface in the browser via their interactive tool. This will help you see how it would be\nrendered in a Slack client.\n\n```php\n$msg = Kit::message(\n    ephemeral: true,\n    blocks: [\n        Kit::section('Don\\'t you just love XKCD?'),\n        Kit::divider(),\n        Kit::blockImage(\n            title: 'Team Chat',\n            imageUrl: 'https://imgs.xkcd.com/comics/team_chat.png',\n            altText: 'Comic about the stubbornness of some people switching chat clients',\n        ),\n    ]\n);\n\necho Kit::preview($msg);\n```\n\n#### Output\n\n```\nhttps://app.slack.com/block-kit-builder#%7B\"blocks\":%5B%7B\"type\":\"section\"%2C\"text\":%7B\"type\":\"mrkdwn\"%2C\"text\":\"Don%27t%20you%20just%20love%20XKCD%3F\"%7D%7D%2C%7B\"type\":\"divider\"%7D%2C%7B\"type\":\"image\"%2C\"title\":%7B\"type\":\"plain_text\"%2C\"text\":\"Team%20Chat\"%7D%2C\"image_url\":\"https:%5C%2F%5C%2Fimgs.xkcd.com%5C%2Fcomics%5C%2Fteam_chat.png\"%2C\"alt_text\":\"Comic%20about%20the%20stubbornness%20of%20some%20people%20switching%20chat%20clients\"%7D%5D%7D\n```\n\nAnd here's the [actual Block Kit Builder link](https://app.slack.com/block-kit-builder#%7B\"blocks\":%5B%7B\"type\":\"section\"%2C\"text\":%7B\"type\":\"mrkdwn\"%2C\"text\":\"Don%27t%20you%20just%20love%20XKCD%3F\"%7D%7D%2C%7B\"type\":\"divider\"%7D%2C%7B\"type\":\"image\"%2C\"title\":%7B\"type\":\"plain_text\"%2C\"text\":\"Team%20Chat\"%7D%2C\"image_url\":\"https:%5C%2F%5C%2Fimgs.xkcd.com%5C%2Fcomics%5C%2Fteam_chat.png\"%2C\"alt_text\":\"Comic%20about%20the%20stubbornness%20of%20some%20people%20switching%20chat%20clients\"%7D%5D%7D). \n\nIt will show up in the Block Kit Builder looking something like this:\n\n![Screenshot of rendered message in Block Kit Builder](block-kit-screenshot.png)\n\n### Component Hydration\n\nSome Slack application integrations (such as with Modals) require receiving the JSON of an existing surface and then \nmodifying or replacing that surface with another. You can \"hydrate\" the JSON of a surface (or element) into its object\nrepresentation using its `fromArray` method (or `fromJson`).\n\n```php\n$messageJson = \u003c\u003c\u003cJSON\n{\n    \"blocks\": [\n        {\n            \"type\": \"section\",\n            \"block_id\": \"block1\",\n            \"text\": {\n                \"type\": \"mrkdwn\",\n                \"text\": \"*foo bar*\"\n            }\n        }\n    }\n}\nJSON;\n\n// Use fromArray to hydrate the message from parsed JSON data.\n$decodedMessageJson = json_decode($messageJson, true);\n$message = Message::fromArray($decodedMessageJson);\n\n// OR... use fromJson to hydrate from a JSON string.\n$message = Message::fromJson($messageJson);\n```\n\n### Message Formatting\n\nThe `Md` class exists to provide helpers for formatting \"mrkdwn\" text. These helpers can be used so that you\ndon't have to have the Slack mrkdwn syntax memorized. Also, these functions will properly escape `\u003c`, `\u003e`, and `\u0026`\ncharacters automatically, if it's needed.\n\nExample:\n```php\n// Note: $event is meant to represent some kind of DTO from your own application.\n$md = Kit::md();\n$msg = Kit::message(\n    blocks: [\n        Kit::section(\n            text: $md-\u003esub(\n                'Hello, {audience}! On {date}, {host} will be hosting an AMA in the {channel} channel at {time}.',\n                [\n                    'audience' =\u003e $md-\u003eatHere(),\n                    'date'     =\u003e $md-\u003edate($event-\u003etimestamp),\n                    'host'     =\u003e $md-\u003euser($event-\u003ehostId),\n                    'channel'  =\u003e $md-\u003echannel($event-\u003echannelId),\n                    'time'     =\u003e $md-\u003etime($event-\u003etimestamp),\n                ]\n            )\n        )\n    ]\n);\n```\n\nExample Result:\n```json\n{\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"Hello, \u003c!here\u003e! On \u003c!date^1608322949^{date}|2020-12-18T20:22:29+00:00\u003e, \u003c@U12345678\u003e will be hosting an AMA in the \u003c#C12345678\u003e channel at \u003c!date^1608322949^{time}|2020-12-18T20:22:29+00:00\u003e.\"\n      }\n    }\n  ]\n}\n```\n\n## Virtual Blocks\n\nIn addition to the standard blocks, the following are virtual/custom blocks composed of one or\nmore other blocks:\n\n* `TwoColumnTable` - Uses Sections with Fields to create a two-column table with an optional header.\n* `CodeBlock` - Uses Sections to create a code block with an optional header.\n\n## Class Structure\n\n- `Surface`s, `Block`s, `Element`s, and `Part`s are all types of Block Kit `Component`s.\n- The `Kit` façade can be used as a factory to create any `Component`.\n- `Component`s contains properties and sub-`Component`s that define their appearance and behavior.\n- `Part`s are repeated patterns that form the properties of other `Component`s.\n- `Surface`s contain one or more `Block`s.\n- `Block`s contain one or more `Element`s.\n- Most `Element`s are interactive in some way.\n- Many `Element`s are also `Input`s that receive user input.\n\n![UML diagram for slack-block-kit](https://yuml.me/369b7a0f.png)\n\n\u003cdetails\u003e\n\u003csummary\u003eSee the YUML\u003c/summary\u003e\n\u003cpre\u003e\n[Kit]-creates\u003e[Component]\n[Surface]^[Message]\n[Surface]^[Modal]\n[Surface]^[AppHome]\n[Surface]^[Attachment]\n[Component]^[Surface]\n[Component]^[Block]\n[Component]^[Element]\n[Component]^[Part]\n[Component]\u003c\u003e-\u003e[Part]\n[Surface]\u003c\u003e-\u003e[Block]\n[Message]\u003c\u003e-\u003e[Attachment]\n[Block]\u003c\u003e-\u003e[Element]\n[Element]^[Input]\n[Element]-[note:Examples: Button, OverflowMenu {bg:cornsilk}]\n[Input]-[note:Examples: Select Menu, DatePicker {bg:cornsilk}]\n[Part]-[note: Examples: Text, Fields {bg:cornsilk}]\n[Block]-[note: Examples: Section, Actions {bg:cornsilk}]\n\u003c/pre\u003e\n\u003c/details\u003e\n\n### Contributions\n\nContributions welcome to support new elements, add tests, improve code, etc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslack-php%2Fslack-php-block-kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslack-php%2Fslack-php-block-kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslack-php%2Fslack-php-block-kit/lists"}