{"id":41736409,"url":"https://github.com/mailmojo/kolibri","last_synced_at":"2026-01-25T00:05:30.702Z","repository":{"id":5456565,"uuid":"6650852","full_name":"mailmojo/kolibri","owner":"mailmojo","description":"A lightweight, flexible web application framework in PHP 5","archived":false,"fork":false,"pushed_at":"2021-01-23T23:18:39.000Z","size":981,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-03-26T07:38:44.791Z","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":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mailmojo.png","metadata":{"files":{"readme":"README","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":"2012-11-12T09:14:32.000Z","updated_at":"2021-01-23T23:18:41.000Z","dependencies_parsed_at":"2022-09-25T03:12:03.833Z","dependency_job_id":null,"html_url":"https://github.com/mailmojo/kolibri","commit_stats":null,"previous_names":["mailmojo/kolibri"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mailmojo/kolibri","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailmojo%2Fkolibri","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailmojo%2Fkolibri/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailmojo%2Fkolibri/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailmojo%2Fkolibri/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mailmojo","download_url":"https://codeload.github.com/mailmojo/kolibri/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mailmojo%2Fkolibri/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28739332,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T22:12:27.248Z","status":"ssl_error","status_checked_at":"2026-01-24T22:12:10.529Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":"2026-01-25T00:05:28.038Z","updated_at":"2026-01-25T00:05:30.693Z","avatar_url":"https://github.com/mailmojo.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"***************\n ABOUT KOLIBRI\n***************\n\nKolibri is a lightweight, flexible web application framework written in PHP 5.\nKolibri's focus is on providing you with the tools to customize the framework to\nyour liking -- from its custom URI mapper and plug-in-based core architecture,\nto the view technology of your choice. Kolibri flies either way.\n\nKolibri is under active development and is not feature complete, nor is the API\nstable. It is however fully functional and is already used in several production\napplications.\n\n\n**************\n INSTALLATION\n**************\n\nRequirements:\n\t* Apache with mod_rewrite support PHP 5.2 with: (PHP 5.1 should work but is\n\t* currently untested)\n\t\t- XSL extension\n\t\t- PostgreSQL or SQLite extensions for database applications\n\nCheck out our bazaar branch if not already done:\n\n\t$ bzr branch lp:kolibri\n\nThe src/ directory within the checked out directory contains the framework\nitself, and can be installed where ever you want where Apache has read access\n(it doesn't need to be in your Apache document root). Copy kolibri.php and\n.htaccess (which resides in the src/ directory as well) into an Apache document\nroot, and edit kolibri.php to set the install path and application directories.\n\n\n*****************\n GETTING STARTED\n*****************\n\nAs documentation is yet a major TODO, this is a [somewhat] small guide to help\nyou get started. A sample application you should look at when following this\nguide is provided in the examples/wishlist directory.\n\n1. Setup and directory structure\n--------------------------------\n\nCopy the contents of examples/wishlist to an Apache document root along with\nkolibri.php and .htaccess as mentioned in the general installation instructions\nabove. Modify the permissions on the db/ directory (which will hold the SQLite\ndatabase required for this application) to give Apache write access (i.e. \"chmod\n777 db/\" in a shell). As with Kolibri itself, the application files don't have\nto reside in the document root, but for simplicity's sake we'll keep it there\nfor this example.\n\nWith the exception of the db/ directory, the other directories are default\nKolibri application directories (although again, most can be changed). Their\nnames should be pretty self-evident.\n\nTo complete the installation of the example application, go to\nhttp://localhost/setup (or whatever hostname you're using) to create the\ndatabase tables.\n\n2. Configuration (or lack thereof)\n----------------------------------\n\nYou don't have to edit any configuration if you followed the defaults above, but\nlet's take a quick look. As mentioned above, kolibri.php defines Kolibri's and\nthe application's installation directories, while conf/config.php defines\napplication-specific configuration. You can change the web root, URI of static\nresources (.htaccess may also have to be updated if this is changed), database\nsettings among others.\n\nMore interesting is the sections related to action mappers and interceptor\nmappings. Action mappers are PHP classes that defines how URIs (and/or other\nrequest data) are mapped to actions, while the interceptor mappings specifies\nwhich interceptors (you could also call this \"plug-ins\" or \"filters\") are\ninvoked. We discuss both of these in more detail below.\n\n3. Actions and action mappers\n-----------------------------\n\nIn Kolibri, when using the default action mapper (appropriately named\nDefaultActionMapper, as can be seen in config.php), an URI maps to exactly one\naction class and vice versa. This mapper tries to find matching action classes\nby mapping the URI to directory and file names within the actions directory,\nwith a fallback to an Index.php action if no exact match is found. What this\nmeans is that a request to the web root will be mapped to Index.php directly\nwithin the actions/ directory, while /items maps to items/Index.php if an items/\ndirectory exists, else Items.php directly within the actions/ directory.\n\nAfter adding some wishlist items in the example application, take a look at the\nURI for the links to delete entries. It links to /items/del/\u003citemname\u003e, which\ncorresponds to the actions/items/Del.php file. As you can see, no action maps to\nthe item name. Instead, if the last URI-part is not matched to an action, it is\nput into a request parameter named \"id\".\n\nAs for the action classes themselves, their names must exactly match their file\nnames. They implement either one, or both, of doGet() and doPost() methods,\nwhich will be executed on HTTP GET or POST calls respectively. Action classes\ncan be plain old objects and need not extend ActionSupport as our example\nactions does, but more often than not they do simply because it provides some\nfunctionality commonly needed by most actions (specifically access to the\nsession and status message facility).\n\nHow you write your own action mappers are beyond the scope of this introduction,\nbut generally you simply extend DefaultActionMapper, override mapAction(),\nmapMethod() and/or mapParams() and put it in a directory named mappers/ in your\napplication. Writing your own mappers gives you complete freedom to lay out the\nactions however you want (i.e. you can have action methods instead of action\nclasses).\n\n4. Interceptors and the wings of Kolibri\n----------------------------------------\n\nKolibri makes use of interceptors for much of it's core functionality.\nInterceptors are like filters or plug-ins, but we like their names because they,\nwell, intercept requests and can change the outcome of the execution. Everything\nfrom session support through authentication to validation is implemented through\ninterceptors. This makes it easy to customize the framework however you like, by\ndisabling interceptors you don't need or writing your own.\n\nInterceptors are enabled per URI similar to action mappers. See the\ndocumentation in config.php for information how they are setup, and\nconf/interceptors.php in Kolibri for a list of the currently supported\ninterceptors.\n\nThe most interesting use of interceptors in our example application can be seen\nin the Add action. It implements ModelAware and ValidationAware and defines a\ncouple of fields that are used by the ModelInterceptor and ValidatorInterceptor\nrespectively. When the ModelInterceptor is invoked (which it is, as it's part of\nthe defaultStack interceptor stack we have configured), it checks to see if the\ntarget action is ModelAware. If it is (as is the case with the Add action), a\nmodel instance of the class named in the $model property of the action (in this\ncase Item) is created. Request parameters are traversed and the model instance\nis populated with their values before being put back into the action.\n\nFor the ValidatorInterceptor to have any meaning it must be invoked after the\nModelInterceptor, which it is as dictated by their order in the defaultStack. If\nthe target action is ValidationAware, it grabs the model object from the action\n(which was prepared by the ModelInterceptor) and validates the model according\nto its own rules. Any errors are put into the $errors field in the action, which\nthe action can look at to determine what to do during its execution.\n\nWhile the interceptors just described are among the most complex, more simple\nfunctionality such as session support and status messages are also implemented\nby interceptors. The session for instance can be access in SessionAware actions\nthrough $this-\u003esession['key'], while the messages we set by\n$this-\u003emsg-\u003esetMessage(...) is a facility provided to MessageAware actions by\nthe MessageInterceptor.\n\n5. Models and data access objects\n---------------------------------\n\nModels in Kolibri applications can, and will most often be, plain objects. You\ndon't have to extend any specific class, in fact, there is no provided\n\"super-model\" class to extend. Instead Kolibri makes use of the object-oriented\nproxy pattern to transparently wrap model objects in a proxy, which among other\nthings provides access to the model's corresponding data access object. Contrary\nto many other frameworks, Kolibri doesn't include an Object-Relational Mapper\n(ORM). Instead we prefer to write more complex SQL queries ourselves (as ORMs\nrarely manage), and provide a SQL-to-Object-Framework (acronyms are fun, let's\ncall it SOFA) which automatically maps the result of SQL to a nested structure\nof model objects according to their relationships (if joins were involved).\n\nClean separation of PHP logic and SQL queries are of course important, which is\nwhy the SQL should be put in a data access object (DAO). They must be put in a\ndao/ directory within the models/ directory, and each model (which cares about\nthe database) should have it's own DAO. As an example, our Item model has a\ncorresponding ItemDao class for its database access.\n\nTaking a step back, let's look at a model class and how it defines its\nvalidation rules which is used by the validation framework provided by the\nValidatorInterceptor. Our Item model implements Validateable and a rules()\nmethod which defines its validation criteria. See the Item class to see how it's\ndefined, and conf/validation.php in Kolibri for a list of all available\nvalidators.\n\nIf the validation is successful, you might want to save the model during the\naction execution. This is done by simply calling save() on the model. The model\nproxy will try to figure out if the model actually need saving (i.e. do we know\nif it was changed since it was retrieved from the database?), and if so calls\nthe appropriate method in the DAO (either insert() or update()). Similarly you\ncall delete() to, well, delete. Direct access to the DAO is provided through the\nobjects property, as demonstrated in the sample actions.\n\n6. Results and views\n--------------------\n\nOne of the cornerstones of Kolibri is the fact that it is not tied to any\nspecific view technology. While we prefer XSL for our views, we realize that not\nall do (although we urge you to take a look, not least due to the simplified\nform handling in XSL). This is why Kolibri does not tie actions to views\ndirectly. Instead actions return a Result object, of which there could be many\nkinds. Kolibri already has XsltResult for XSL views, SmartyResult for Smarty\ntemplates, PhpResult for regular PHP files, RedirectResult for HTTP redirects,\nJsonResult for JSON, and more. This makes it easy to support other view\ntechnologies and response data simply by providing other Result implementations.\n\nAs XSL is the view technology with most widespread use in current Kolibri\napplications, it has got some extra love to offer you. Most importantly it\nprovides simplified syntax to define HTML forms, which will automatically output\nvalidation errors and model data. Take a look at the form in views/index.xsl\nwhich targets the Add action (which, again, is ModelAware and ValidationAware).\nIf validation fails, XSL and thus the form receives and presents the errors and\nmodel data from the action without any extra code on your part.\n\nX. The end\n----------\n\nWhile this guide has only scratched the surface, it has hopefully got you going.\nAny questions, feedback and last but not least contributions are most welcome:\n\n\thttps://launchpad.net/kolibri\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmailmojo%2Fkolibri","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmailmojo%2Fkolibri","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmailmojo%2Fkolibri/lists"}