{"id":20346189,"url":"https://github.com/talesoft/tale-view","last_synced_at":"2025-03-04T15:45:53.455Z","repository":{"id":152351790,"uuid":"52918403","full_name":"Talesoft/tale-view","owner":"Talesoft","description":"A view renderer middleware for the Tale Framework","archived":false,"fork":false,"pushed_at":"2016-03-01T23:58:50.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-14T21:49:07.002Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/Talesoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2016-03-01T23:36:15.000Z","updated_at":"2016-03-01T23:58:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"0ad29105-6a24-48ba-8014-c0af826a8d38","html_url":"https://github.com/Talesoft/tale-view","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Talesoft%2Ftale-view","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Talesoft%2Ftale-view/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Talesoft%2Ftale-view/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Talesoft%2Ftale-view/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Talesoft","download_url":"https://codeload.github.com/Talesoft/tale-view/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241877021,"owners_count":20035401,"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":[],"created_at":"2024-11-14T22:11:56.490Z","updated_at":"2025-03-04T15:45:53.444Z","avatar_url":"https://github.com/Talesoft.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Tale Controller\n**A Tale Framework Component**\n\n# What is Tale Controller?\n\nA middleware for `talesoft/tale-app` that allows easy instanciation and handling of controllers.\n\nYou can either use single, static controllers or use a dispatcher that automatically handles everything.\n\n# Installation\n\nInstall via Composer\n\n```bash\ncomposer require \"talesoft/tale-controller:*\"\ncomposer install\n```\n\n# Usage\n\n## Single usage\n\nA single controller can make up a whole website.\nThis is really useful for small websites with 5-10 sub-pages.\nNo configuration needed.\n\n```php\n\nuse Tale\\App;\nuse Tale\\Controller;\n\n//Define a controller of some kind\nclass MyController extends Controller\n{\n    \n    //GET|POST /\n    public function indexAction()\n    {\n        \n        $res = $this-\u003egetResponse();\n        $res-\u003egetBody()-\u003ewrite('Hello index!');\n        return $res;\n    }\n    \n    //GET|POST /?action=about-us\n    public function aboutUsAction()\n    {\n        \n        $res = $this-\u003egetResponse();\n        $res-\u003egetBody()-\u003ewrite('About us!');\n        return $res;\n    }\n    \n    //GET /?action=contact\n    public function getContactAction()\n    {\n        \n        $res = $this-\u003egetResponse();\n        $res-\u003egetBody()-\u003ewrite('Contact form!');\n        return $res;\n    }\n    \n    //POST /?action=contact\n    public function postContactAction()\n    {\n        \n        //Handle contact form\n        $res = $this-\u003egetResponse();\n        $res-\u003egetBody()-\u003ewrite('Success!');\n        return $res;\n    }\n}\n\n\n//Create a new app context\n$app = new App();\n\n//Make sure we can target the \"action\" somehow.\n//Normally you'd use a router, we use a simple GET-variable in this case\n//\"index.php?action=about-us\" would dispatch \"MyController-\u003eaboutUsAction\"\n\n//This is a simple middleware mapping query's \"action\" to the required request attribute \"action\"\n$app-\u003eappend(function($req, $res, $next) {\n\n    $params = $req-\u003egetQueryParams();\n    $action = isset($params['action']) ? $params['action'] : null;\n\n    if ($action)\n        $req = $req-\u003ewithAttribute('action', $action);\n\n    return $next($req, $res);\n});\n\n//Append our controller middleware\n$app-\u003eappend(MyController::class);\n\n//Display the app\n$app-\u003edisplay();\n\n```\n\n## Using the Dispatcher\n\nWhen apps get larger, you want to split functionality into single modules.\nWith the Dispatcher you can control an automatic controller dispatching mechanism.\n\nImagine the following controller structure:\n```\n/\n    /index.php\n    /app\n        /controllers\n            IndexController.php\n            ContactController.php\n            PortfolioController.php\n            /Admin\n                /IndexController.php\n```\n                \n                \nThis is a common case that the dispatcher can handle with a low configuration profile.\n\n```php\n\nuse Tale\\App;\nuse Tale\\Controller\\Dispatcher;\n\n//Create a new app context\n$app = new App([\n    'controller' =\u003e [\n        'nameSpace' =\u003e 'My\\\\Controllers',\n        'loader' =\u003e ['path' =\u003e __DIR__.'/app/controllers']\n    ]\n]);\n\n//This is a middleware mapping \"module\", \"controller\" and \"action\" GET-values to\n//ServerRequestInterface-attributes\n$app-\u003eappend(function($req, $res, $next) {\n\n    $params = $req-\u003egetQueryParams();\n    $module = isset($params['module']) ? $params['module'] : null;\n    $controller = isset($params['controller']) ? $params['controller'] : null;\n    $action = isset($params['action']) ? $params['action'] : null;\n\n    if ($module)\n        $req = $req-\u003ewithAttribute('module', $module);\n            \n    if ($controller)\n        $req = $req-\u003ewithAttribute('controller', $controller);\n\n    if ($action)\n        $req = $req-\u003ewithAttribute('action', $action);\n\n    return $next($req, $res);\n});\n\n//Append our dispatcher middleware\n$app-\u003eappend(Dispatcher::class);\n\n//Display the app\n$app-\u003edisplay();\n```\n\nNow you could call the `editAction` of the `Admin\\IndexController` by requesting\n`index.php?module=admin\u0026action=edit`\n\nNotice that all values are completely optional.\n\n## ServerRequestInterface attributes\n\nThe following attributes are handled by the dispatcher:\n\n### `module` (Default: `null`)\n\nTells the dispatcher which namespace to find controllers in.\nThe `controller.nameSpace` option will be prepended in any case.\n\n### `controller` (Default: `index`)\n\nTells the dispatcher, which controller to load.\n`my-blog` will be parsed to `MyBlogController`\n\nThe following attributes are handled by the controllers:\n\n### `action` (Default: `index`)\n\nTells the controller which action to call.\n`edit-user` will be parsed to `editUserAction`\n\nIf there's an `getEditUserAction`-method, that one will only listen to `GET`-requests\nThe same goes for `POST`-requests with `postEditUserAction`.\nNot prefixing will handle all request methods.\n\n### `id` (Default: null)\n\nSpecifies the first parameter given to the action.\nAllowed values are numerical values and canonical strings (`some-user-name`)\n\n### `format` (Default: html)\n\nSpecifies the format the result should appear in.\nThis mostly equals the file extension of the called URI (`/some-file.xml` will yield format `xml`)\n\nThis format is to be used by some kind of output formatter/renderer.\n\n\n## Handle 404-errors\n\nWhat if there's no fitting controller/it doesn't extend the correct class/the input is malformed etc.\n\nThat's all checked by tale-controller. Upon any kind of failure, control will be passed on\nto the next middleware.\n\nHandling 404 is as simple as adding an \"end\"-middleware that results in said 404-error\n\n```php\n\n$app-\u003eappend(Dispatcher::class)\n    -\u003eappend(function($req, $res) {\n        \n        $res-\u003egetBody()-\u003ewrite('\u003ch1\u003e404 - Not found!\u003c/h1\u003e');\n        return $res-\u003ewithStatus(404);\n    });\n```\n\n## Shorten things up\n\nThis module is specially designed to work with the `Tale\\Router`.\nYou can use it stand-alone, but it will require extra-work (but is still really cool!)\n\nHere's an example of how it could look like by installing `talesoft/tale-router` via composer\n\n**env.json**\n```json\n{\n    \"middlewares\": [\"Tale\\\\Router\"],\n    \"routes\": {\n        \"/blog/:action?/:id?\": \"My\\\\Controller\\\\BlogController\",\n        \"/:controller?/:action?/:id?.:format?\": \"Tale\\\\Controller\\\\Dispatcher\"\n    },\n    \"controller\": {\n        \"nameSpace\": \"My\\\\Controller\",\n        \"loader\": {\n            \"path\": \"{{path}}/app/controllers\"\n        }\n    }\n}\n```php\n\n**index.php**\n```php\n\nuse Tale\\App;\n\n$app = new App(['path' =\u003e __DIR__]);\n$app-\u003edisplay();\n```\n\n\n## Configuration options\n\nAll configuration options.\n\n```\ncontroller.defaultModule            The default module to use (Default: null)\ncontroller.defaultController        The default controller to use (Default: index)\ncontroller.defaultAction            The default action to use (Default: index)\ncontroller.defaultId                The default ID to use (Default: null)\ncontroller.defaultFormat            The default format to use (Default: html)\n\ncontroller.nameSpace                The namespace where controllers reside in (Default: null)\ncontroller.modules                  A map [module-name =\u003e namespace] for module mapping\n\ncontroller.controllerPattern        The pattern for controllers (Default: %sController)\ncontroller.controllerInflection     How to inflect the controller name (Default: [Tale\\Inflector, camelize]\n\ncontroller.actionPattern            The pattern for actions (Default: %sAction)\ncontroller.actonInflection          How to inflect the action name (Default: [Tale\\Inflector, variablize]\ncontroller.getActionPattern         The pattern for GET actions (Default: get%sAction)\ncontroller.getActonInflection       How to inflect the GET action name (Default: [Tale\\Inflector, camelize]\ncontroller.postActionPattern        The pattern for POST actions (Default: post%sAction)\ncontroller.postActonInflection      How to inflect the POST action name (Default: [Tale\\Inflector, camelize]\n\ncontroller.loader.enabled           Enable an auto-loader for controllers (Default: true)\ncontroller.loader.path              The path for controller classes (Default: getcwd()/controllers)\ncontroller.loader.pattern           The pattern for controller loading (Default: %s.php)\n```\n\n## Using multiple dispatchers\n\nUsing multiple dispatchers is as easy as extending the dispatcher.\nYou can set an option namespace to load different configuration values.\n\n```php\n\nclass FirstDispatcher\n{\n\n    public function getOptionNameSpace()\n    {   \n    \n        return 'firstDispatcher';\n    }\n}\n\n\nclass SecondDispatcher\n{\n\n    public function getOptionNameSpace()\n    {   \n    \n        return 'secondDispatcher';\n    }\n}\n\n$app-\u003eget(Router::class)\n    -\u003eall('/:controller?/:action?', FirstDispatcher::class)\n    -\u003eall('/sub-module/:controller?/:action?', SecondDispatcher::class);\n\n$app-\u003edisplay();\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftalesoft%2Ftale-view","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftalesoft%2Ftale-view","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftalesoft%2Ftale-view/lists"}