{"id":22092122,"url":"https://github.com/krakphp/presenter","last_synced_at":"2025-03-23T23:44:58.769Z","repository":{"id":57009033,"uuid":"92967278","full_name":"krakphp/presenter","owner":"krakphp","description":"Simple, Flexible Presenter System","archived":false,"fork":false,"pushed_at":"2017-05-31T16:40:57.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-29T06:52:28.693Z","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/krakphp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-31T16:38:31.000Z","updated_at":"2017-05-31T16:40:30.000Z","dependencies_parsed_at":"2022-08-21T14:50:51.438Z","dependency_job_id":null,"html_url":"https://github.com/krakphp/presenter","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fpresenter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fpresenter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fpresenter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fpresenter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krakphp","download_url":"https://codeload.github.com/krakphp/presenter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245186925,"owners_count":20574554,"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-12-01T03:08:22.818Z","updated_at":"2025-03-23T23:44:58.729Z","avatar_url":"https://github.com/krakphp.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"Krak Presenter\n==============\n\nSimple yet powerful implementation of the presenter pattern.\n\n## Installation\n\ninstall via composer.\n\n```javascript\n{\n    \"repositories\": [\n        {\n            \"type\": \"vcs\",\n            \"url\": \"http://gitlab.bighead.net/bighead/krak-presenter.git\"\n        }\n    ],\n    \"require\": {\n        \"krak/presenter\": \"~2.0\",\n\n        /* only if you use the CachePresenter */\n        \"doctrine/cache\": \"~1.0\",\n\n        /* include if you use the EventListener\\ViewListener */\n        \"symfony/event-dispatcher\": \"~2.0\",\n        \"symfony/http-kernel\": \"~2.0\",\n        \"symfony/http-foundation\": \"~2.0\",\n\n        /* include if you use the Provider\\ViewPresenterServiceProvider */\n        \"pimple/pimple\": \"~3.0\"\n    }\n}\n```\n\n## Design\n\nThe Krak Presenters are broken up into 3 main components: Presenters, Decorators, and View Models.\n\nThe Presenters and Decorators all implement the `Presenter` interface:\n\n```php\ninterface Presenter\n{\n    /**\n     * Present the view and return the content associated with it\n     * @param mixed $view\n     * @return string\n     */\n    public function present($view);\n\n    /**\n     * Whether or not the presenter can actually present the data/view\n     * @param mixed $data\n     * @return bool\n     */\n    public function canPresent($view);\n}\n```\n\nA presenter/decorator will accept a view model to present and then return it's contents.\n\nSo the call\n\n```php\n$content = $presenter-\u003epresent($view);\n```\n\nwill always return the content associated with view.\n\n## Presenters\n\nThe Presenters will take view models and \"present\" them i.e. render them into a string response. This library comes bundled with 2 different presenters: View and Mock.\n\nThe View presenter will take a View model and return the appropriate content from the view file associated with the View model.\n\nThe Mock presenter is primarily used for testing, but it's just a simple wrapper around the [SplObjectStorage](http://php.net/manual/en/class.splobjectstorage.php).\n\n### ViewPresenter\n\n```php\n\u003c?php\n\nuse Krak\\Presenter\\ViewPresenter;\nuse Krak\\Presenter\\View\\View;\nuse Krak\\Presenter\\View\\ViewTrait;\nuse Symfony\\Component\\Config\\FileLocator;\n\nclass MyView implements View\n{\n    use ViewTrait;\n\n    private $view_file = 'my-view';\n\n    // or just define the getViewFile function\n\n    public function getViewFile()\n    {\n        return 'my-view';\n    }\n\n    public function getHeader()\n    {\n        return '\u003ch1\u003eHeader\u003c/h1\u003e';\n    }\n}\n\n$presenter = new ViewPresenter(FileLocator(__DIR__ . '/views'), 'php', 'v');\necho $presenter-\u003epresent(new MyView());\n```\n\n```php\n// __DIR__ . /views/my-view.php\n\u003chtml\u003e\n    \u003c?=$v-\u003egetData()?\u003e\n\u003c/html\u003e\n```\n\nthe last echo statement would ouptut:\n\n    \u003chtml\u003e\n        \u003ch1\u003eHeader\u003c/h1\u003e\n    \u003c/html\u003e\n\nThe ViewPresenter constructor takes a [FileLocator](http://symfony.com/doc/current/components/config/resources.html), an extension (defaults to an empty string), and an alias for the view model (defaults to 'view').\n\n#### Extension\n\n```php\n$presenter-\u003esetExtension('php');\necho $presenter-\u003egetExtension();\n// outputs: php\n```\n\nIf there is an extension set, then it will append `.{ext}` to the end of each view file name.\n\n#### Alias\n\n```php\n$presenter-\u003esetViewAlias('v_alias');\necho $presenter-\u003egetViewAlias();\n// outputs: v_alias\n\n// then in some-view file\n\u003chtml\u003e\n    \u003c?=$v_alias-\u003egetData()?\u003e\n\u003c/html\u003e\n```\n\n### MockPresenter\n\n```php\nuse Krak\\Presenter\\MockPresenter;\n\n$presenter = new MockPresenter();\n$view = new stdClass();\n$presenter-\u003emock($view, 'some-data');\n\necho $presenter-\u003epresent($view);\n```\n\nthe output will be\n\n    some-data\n\n## Decorators\n\nThe presenter system is designed around the `Presenter` interface which makes the use of decorators very easily.\n\nThis library comes with two decorators: Cache and Tree.\n\n### Caching\n\nThe caching presenter is just a decorator that will try to get the presenter data out of\ncache before actually going through the process of rendering the view.\n\n```php\nuse Krak\\Presenter\\CachePresenter;\nuse Krak\\Presenter\\View\\CacheableView;\nuse Doctrine\\Common\\Cache\\ArrayCache;\n\nclass MyView implements CacheableView\n{\n    public function getCacheTuple()\n    {\n        return array('my-view-cache-key', 3600);\n    }\n}\n\n/* $presenter is another instanceof Presenter defined beforehand */\n$cache = new ArrayCache();\n$cache_presenter = new CachePresenter($presenter, $cache);\n\n$data = $cache_presetner-\u003epresent(new MyView());\n\nvar_dump($data === $cache-\u003efetch('my-view-cache-key');\n```\n\nthe output will be true because the cache presenter added the data to the cache, and the next call to present on the same view model would just return the data from cache instead of delegating the presentation to it's internal presenter.\n\n    bool(true)\n\nNow, the CachePresenter will only cache views models that implement the `CacheableView` interface.\n\n### Tree\n\nThe tree presenter is another decorator that allows a hierarchy/tree of views to be presented. A tree presenter will only traverse a tree of views if they implement the `TreeView` interface. One important note about the tree view is how it handles the presenting of multiple items at once.\n\nThe call `$tree_presenter-\u003epresenter($view)` will return the output of the `$view` object which is the root of the tree. It will then traverse the tree down and use it's internal presenter to get all of the data for each child view. It then injects the content presented back into child views to be used by any of the parents. Look at the following example.\n\n```php\nuse Krak\\Presenter\\TreePresenter;\nuse Krak\\Presenter\\View\\View;\nuse Krak\\Presenter\\View\\TreeView;\nuse Krak\\Presenter\\View\\TreeViewTrait;\nuse Krak\\Presenter\\ViewPresenter;\n\nclass TreeViewChild implements View, TreeView\n{\n    use ViewTrait;\n    use TreeViewTrait;\n\n    private $view_file = 'child-view.php';\n\n    public function getData()\n    {\n        return 'some-data';\n    }\n}\n\nclass TreeViewParent implements View, TreeView\n{\n    use TreeViewTrait;\n\n    private $child1;\n    private $view_file = 'parent-view.php';\n\n    public function __construct()\n    {\n        $this-\u003echild1 = new TreeViewChild();\n    }\n\n    public function getChildren()\n    {\n        return array($this-\u003echild1);\n    }\n\n    public function getChild1()\n    {\n        return $this-\u003echild1;\n    }\n}\n\n$view_presenter = new ViewPresenter($locator);\n$tree_presenter = new TreePresenter($view_presenter);\n\necho $tree_presenter-\u003epresent(new TreeViewParent());\n```\n\n```php\n// child-view.php\n\u003cspan\u003e\u003c?=$view-\u003egetData()?\u003e\u003c/span\u003e\n```\n\n```php\n// parent-view.php\n\u003cdiv\u003e\n    \u003c?=$view-\u003egetChild1()-\u003egetContent()?\u003e\n\u003c/div\u003e\n```\n\nthe last echo statement would display\n\n    \u003cdiv\u003e\n        \u003cspan\u003esome-data\u003c/span\u003e\n    \u003c/div\u003e\n\n## View Models\n\nThe view models are the actual object responsible for rendering the views. There are four types of views with the Krak Presenter library: Views, TreeViews, CacheableViews, and AnonymousViews.\n\n### View\n\n```php\ninterface View\n{\n    /**\n     * @return string\n     */\n    public function getViewFile();\n}\n```\n\nVery simple interface for retrieving the view file to be loaded. This interface is used by the ViewPresenter. You can use the `ViewTrait` to define those methods for you.\n\n### TreeView\n\n```php\ninterface TreeView\n{\n    /**\n     * @return TreeView[]\n     */\n    public function getChildren();\n\n    /**\n     * Set the rendered content for this view\n     * @var string\n     */\n    public function setContent($content);\n\n    /**\n     * get the rendered content for this view\n     * @return string\n     */\n    public function getContent();\n}\n```\n\nThis interface is designed to be used with TreePresenter, and as you can see it allows traversal of a tree of TreeView models and allows each view to hold store their content. You can use the `TreeViewTrait` to define those methods for you.\n\n### CacheableView\n\n```php\ninterface CacheableView\n{\n    /**\n     * Returns a tuple of the cache key and ttl\n     * @return array\n     */\n    public function getCacheTuple();\n}\n```\n\nThis interface is designed to be used with the CachePresenter. A cache tuple looks like the following:\n\n```php\narray('key', 3600);\n```\n\nwhere the tuple has a key of 'key' and a ttl of 3600.\n\n### Anonymous Views\n\nSometimes you don't need to build an entire class to just render a file with some data, for that, we have the Anonymous View models.\n\nAn Anonymous View implements the `View` interface. You can create anonymous view like so:\n\n```php\nuse Krak\\Presenter\\View\\AnonymousView;\n\n$v = new AnonymousView('some-view-file', array('key'=\u003e'val'));\n// or\n$v = AnonymousView::create('some-view-file'); // data is defaulted to an empty array\n```\n\nthen in `some-view-file`\n\n```php\n\u003cdiv\u003e\n    \u003c?=$view-\u003ekey?\u003e\n\u003c/div\u003e\n```\n\nthis view will render to:\n\n    \u003cdiv\u003e\n        val\n    \u003c/div\u003e\n\n## Buffer\n\nThe buffer is a simple utility that comes in handy when working with TreeViews. A buffer essentially just holds string content, but you can share the same buffer with multiple views, and they will append to the same buffer.\n\nFor example, let's say you wanted to let each view define some javascript. And the javascript defined by each view should then be output at the bottom of the page. You could that easily with a buffer.\n\nFirst, we'll assume that each view has the same instance of a buffer as a public variable with the name, `js_buf`.\n\n```php\n// root view file\n\u003chtml\u003e\n    \u003cbody\u003e\n        \u003c?=$view-\u003egetInnerView()-\u003egetContent()?\u003e\n    \u003c/body\u003e\n    \u003c?=$view-\u003ejs_buf-\u003egetContents()?\u003e\n\u003c/html\u003e\n```\n\n```php\n// inner view file\n\u003c?php $view-\u003ejs_buf-\u003estart()?\u003e\n\u003cscript type=\"text/javascript\"\u003e\n    // some javascript\n\u003c/script\u003e\n\u003c?php $view-\u003ejs_buf-\u003eend()?\u003e\n\u003cdiv\u003e\n    \u003c!-- content --\u003e\n\u003c/div\u003e\n```\n\n## View Listener\n\nIf you use a project that is based off of the [Symfony HttpKernel](http://symfony.com/doc/current/components/http_kernel/introduction.html), you can register the view listener so that your controllers can return views and have them converted to responses.\n\n```php\nuse Krak\\Presenter\\EventListener\\ViewListener,\n    Krak\\Presenter\\ViewPresenter;\n\n$view_presenter = ...\n$listener = new ViewListener($view_presenter);\n\n/* dispatcher instanceof Symfony\\Component\\EventDispatcher\\EventDispatcher */\n$dispatcher-\u003eaddSubscriber($listener);\n```\n\nThen in your controllers, you can just return a view model like so, and it will be converted to a response\n\n```php\n    public function showAction()\n    {\n        // ...\n\n        /* instanceof Krak\\Presenter\\View\\View */\n        return new ViewModel();\n    }\n```\n\n## Service Provider\n\nIf you use [Pimple](http://pimple.sensiolabs.org) in your projects, you can use the `ViewPresenterServiceProvider` to register the view presenter as a service.\n\n```php\n$container-\u003eregister(new ViewPresenterServiceProvider(), [\n    'presenter.ext' =\u003e 'php',\n    'presenter.view_alias' =\u003e 'view',\n    'presenter.paths' =\u003e [__DIR__],\n    // instead of paths, you can also just specify the file locator\n    'presenter.file_locator' =\u003e function() {\n        return new Symfony\\Component\\Config\\FileLocator([__DIR__]);\n    }\n]);\n\n$locator = $container['presenter.file_locator'];\n$presenter = $container['presenter'];\n```\n\nIf you want to use decorators, then you can use the `Pimple::extend` method like so:\n\n```php\nuse Krak\\Presenter\\TreePresenter;\n\n$container-\u003eextend('presenter', function($presenter, $c)\n{\n    return new TreePresenter($presenter);\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrakphp%2Fpresenter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrakphp%2Fpresenter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrakphp%2Fpresenter/lists"}