{"id":36384026,"url":"https://github.com/pixelkarma/pkrouter","last_synced_at":"2026-01-11T15:00:20.039Z","repository":{"id":253592397,"uuid":"842704862","full_name":"pixelkarma/PkRouter","owner":"pixelkarma","description":"An easy PHP router for JSON APIs","archived":false,"fork":false,"pushed_at":"2025-10-05T20:46:58.000Z","size":101,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-05T21:32:37.484Z","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/pixelkarma.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":"2024-08-14T22:33:35.000Z","updated_at":"2025-10-05T20:30:35.000Z","dependencies_parsed_at":"2024-10-27T06:27:36.403Z","dependency_job_id":null,"html_url":"https://github.com/pixelkarma/PkRouter","commit_stats":null,"previous_names":["pixelkarma/pkrouter"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/pixelkarma/PkRouter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelkarma%2FPkRouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelkarma%2FPkRouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelkarma%2FPkRouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelkarma%2FPkRouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pixelkarma","download_url":"https://codeload.github.com/pixelkarma/PkRouter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelkarma%2FPkRouter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28309504,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"last_error":"SSL_read: 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-11T15:00:17.997Z","updated_at":"2026-01-11T15:00:19.968Z","avatar_url":"https://github.com/pixelkarma.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PkRouter\n\n**Note: This project is no longer maintained and will not receive updates. While overengineering can be enjoyable, I’ve decided that PHP is better suited to simpler approaches: https://github.com/pixelkarma/cascadephp**\n\nPkRouter is a fast and robust modern PHP router intended to be used for API creation. It has no dependencies, and encourages an object oriented approach.\n\nPlease see the [Example](https://github.com/pixelkarma/PkRouter/tree/main/Examples/crud) to see in in action.\n\n## Features\n\n- Supports all HTTP methods, including custom ones.\n- Flexible middleware for pre- and post-route execution.\n- Extensible request and response classes for handling custom payloads.\n- Supports both function and class method callbacks, ideal for MVC projects.\n- Efficient, robust regex-based routing.\n- Extensible parameter pattern validation.\n- Dynamic properties enable seamless data storage throughout the request lifecycle.\n- Custom exceptions enhance error handling and clarity.\n\n## Installation\n\n```\ncomposer require pixelkarma/pkrouter\n```\n\n## Usage\n\n```php\nuse Pixelkarma\\PkRouter\\PkRouter;\n\n$pkRouter = new PkRouter();\n```\n\n### Functions\n\n```php\nuse Pixelkarma\\PkRouter\\PkRoute;\n\n$pkRouter-\u003eroutes-\u003eaddRoute(\n  new PkRoute(\n    \"home\", [\"GET\"], \"/\",\n    function (PkRouter $router) {\n      $message = \"Hello World!\";\n      return $router-\u003erespond([\"message\" =\u003e $message]);\n    }\n  )\n);\n$pkRouter-\u003erun();\n```\n\n### Controller Methods\n\nSee [Controller Method Callbacks](#controller-method-callbacks)\n\n```php\n# ./public/index.php\n$pkRouter-\u003eroutes-\u003eaddRoute(\n  new PkRoute(\"home\", [\"GET\"], \"/\", \"YourNamespace\\Controllers\\HelloController@sayHello\")\n);\n$pkRouter-\u003erun();\n```\n\n## Router (`PkRouter`)\n\n```php\n  $pkRouter = new PkRouter(\n    $routes = null, // An instance of PkRoutesConfig\n    $request = null, // An instance of PkRequest\n    $response = null, // An instance of PkResponse\n    $logFunction = null // a callable function that excepts one Exception parameter\n  );\n```\n\nIf no options are passed when creating the router, the default classes are\nused and an empty [Route Config](#route-config) is created. You will then\nneed to add routes individually.\n\n```php\nuse Pixelkarma\\PkRouter\\PkRoute;\n\n$homeRoute = new PkRoute(\n  name: \"home\",\n  path: \"/\",\n  methods: [\"GET\"],\n  callback: /* function or class method string */,\n  meta: [],\n  before: [\n    /* PkMiddlewareInterface */\n  ],\n  after: [\n    /* PkMiddlewareInterface */\n  ],\n);\n\n$pkRouter-\u003eroutes-\u003eaddRoute($homeRoute);\n```\n\n### Finding a match\n\nThere are two ways to find a match and execute its callback.\n\n```php\n$boolResult = $pkRouter-\u003erun();\n```\n\nor\n\n```php\nif (true === $pkRouter-\u003ematch()) {\n  $boolResult = $pkRouter-\u003erun();\n}else{\n  // Handle the 404\n}\n```\n\n### Responding\n\n\u003e This is a _shortcut_ to `$router-\u003eresponse-\u003esendJson();`\n\n```php\n$router-\u003erespond([\"key\"=\u003e\"value\"], 200);\n```\n\n### Dynamic Properties\n\nIn PkRouter, you have the ability to set dynamic properties on the $router instance.\nThese properties can be used to store data that needs to be accessed or modified at\ndifferent stages of the request lifecycle, such as during the before middleware, the\nroute callback, and the after middleware.\n\n```php\n// Setting up a user object\n$router-\u003euser = (object)[\n  \"username\" =\u003e \"j.doe\"\n];\n```\n\n# Route Creation\n\n```php\nnew PkRoute(\n  name: \"name\",\n  path: \"/path/\",\n  methods: [\"GET\", \"POST\"],\n  callback: \"YourNamespace\\Controllers\\HelloController@sayHello\",\n  meta: [\n    \"permissions\" =\u003e \"admin\"\n    \"anything\" =\u003e \"else\"\n  ],\n  before: [\n    // PkMiddlewareInterface, - run before route\n    // PkMiddlewareInterface, ...\n  ],\n  after: [\n    // PkMiddlewareInterface, - run after route\n    // PkMiddlewareInterface, ...\n  ]\n);\n```\n\n## Route Callback\n\nThe callback is executed when a matching route is found. This value can either\nbe a function, or a string representing your own controller method. Both should\naccept one parameter, an instance of `PkRouter`\n\n### Functional Callbacks\n\n```php\n// Function\ncallback: functionName(PkRouter $router)\n\n// Anonymous Function\ncallback: function(PkRouter $router){\n  $router-\u003erespond([\"message\" =\u003e \"Hello!\"]);\n}\n```\n\n### Controller Method Callbacks\n\n```php\n// Controller Method\ncallback: \"YourNamespace\\Controllers\\ExampleController@methodName\"\n```\n\nYour Contoller will need to accept the `$router` on construct, not the method.\n\n```php\nnamespace YourNamespace\\Controllers;\nclass ExampleController {\n  private $router;\n  public function __construct(PkRouter $router) {\n    $this-\u003erouter = $router;\n  }\n  public function methodName(){\n    return $this-\u003erouter-\u003erespond([\"message\" =\u003e \"Hello!\"]);\n  }\n}\n```\n\n## Route Meta\n\nMeta is an array of values used to provide additional data on a route level. This information\nis accessible from [Middleware](#middleware) and Callbacks\n\n```php\nmeta: [\n  \"userAccess\" =\u003e [\"group1\", \"group2\"],\n  \"something\" =\u003e \"else\"\n]\n```\n\n## Before and After Middleware\n\nSee [Middleware](#middleware)\n\n## URL Parameters\n\n\u003e Path: `/user/[s:username]/`\n\nIn this example `s`, is the type and `username` is the param name accessible with:\n\n```php\n$router-\u003erequest-\u003egetParam('username')\n```\n\nSee [PkRoute Methods](#pkroute-methods) for more information about `getParam()`\n\n|  Type  | Description                        |\n| :----: | ---------------------------------- |\n|  `i`   | Integer                            |\n|  `f`   | Float                              |\n|  `a`   | Alpha                              |\n|  `n`   | Alphanumeric                       |\n|  `s`   | String (URL acceptable characters) |\n|  `e`   | Email                              |\n|  `b`   | Binary: 1, 0, true, false          |\n|  `ip`  | IPV4 Address                       |\n| `ipv6` | IPV6 Address                       |\n|  `uu`  | UUID String                        |\n| `uu4`  | UUID Version 4 String              |\n| `ymd`  | Date: YYYY-MM-DD                   |\n| `hms`  | Time: H:i:s                        |\n|  `*`   | Wildcard — Be careful.             |\n\n### Add additional match patterns\n\nBy calling the static function _addMatchPattern_, you can add additional\nparam types. This can be used at any point prior to matching a route.\n\nA common place to put this is in a [Route Config](#route-config) file, as shown below\n\n```php\nuse Pixelkarma\\PkRouter\\PkRoute;\nuse Pixelkarma\\PkRouter\\PkRoutesConfig;\n\nclass MyRoutes extends PkRoutesConfig {\n  public function routes(): array {\n    /**\n     *  Match 'Serial Number' 'AA-1234'\n     *  /path/AA-1234/ == /path/[sn:serialNumber]/\n     */\n    PkRoute::addMatchPattern(\"sn\", \"(/^[A-Z]{2}-\\d{4}$/)\");\n    /* add routes here */\n  }\n}\n```\n\n## Route Methods\n\nMethods that allow the `$key` parameter will return `$default` (default: null) if the key is not found.\nThis is useful when validating a payload when you might want a value other than `null`.\n\n```php\n$router-\u003eroute-\u003egetParam(\"userId\", false);\n$router-\u003eroute-\u003egetParam(\"userId\", 0);\n```\n\n```php\n// Returns key value or all `meta` with `getMeta('name')`\n$router-\u003eroute-\u003egetMeta(string $key = null, $default = null)\n\n// Returns key value or all `params` with `getParam('name')`\n$router-\u003eroute-\u003egetParam(string $key = null, $default = null)\n\n// Returns route name string\n$router-\u003eroute-\u003egetName()\n\n// Returns the path `/user/[s:username]/`\n$router-\u003eroute-\u003egetPath()\n\n// Returns an array of allowed methods `[\"GET\", \"POST\"]`\n$router-\u003eroute-\u003egetMethods()\n```\n\n# Route Config\n\n`PkRoutesConfig` is an extensible class for setting up multiple Routes, and adding Middleware.\n\n```php\n# ./public/index.php\nuse Pixelkarma\\PkRouter\\PkRouter;\n$pkRouter = new PkRouter(new MyRoutes());\n$pkRouter-\u003erun();\n```\n\n```php\n# ./src/Routes/MyRoutes.php\nnamespace YourNamespace\\Router;\n\nuse YourNamespace\\Router\\Middleware\\AuthorizationMiddleware;\nuse YourNamespace\\Router\\Middleware\\AnalyticsMiddleware;\n\nuse Pixelkarma\\PkRouter\\PkRoute;\nuse Pixelkarma\\PkRouter\\PkRoutesConfig;\n\nclass MyRoutes extends PkRoutesConfig {\n  public function routes(): array {\n\n    // Define Middleware\n    $authorizationMiddleware = new AuthorizationMiddleware();\n    $analyticsMiddleware = new AnalyticsMiddleware();\n\n    // Create Routes\n    $readRoute = new PkRoute(\n      name: \"read\",\n      path: \"/storage/\",\n      methods: [\"GET\"],\n      callback: \"YourNamespace\\Controllers\\StorageController@read\",\n      after: [\n        $analyticsMiddleware,\n      ]\n    );\n\n    $writeRoute = new PkRoute(\n      name: \"write\",\n      path: \"/storage/\",\n      methods: [\"POST\"],\n      callback: \"YourNamespace\\Controllers\\StorageController@write\",\n      before: [\n        $authorizationMiddleware,\n      ],\n      after: [\n        $analyticsMiddleware,\n      ]\n    );\n\n    // Return all routes\n    return [$readRoute, $writeRoute];\n  }\n}\n```\n\n# Request (`PkRequest`)\n\n`PkRequest` contains all of the information about the request being made.\n\n### Request Methods\n\nMethods that allow the `$key` parameter will return `$default` (default: null) if there is no data.\nThis is useful when validating a payload when you might want a value other than `null`.\n\n```php\n$router-\u003erequest-\u003egetHeader(\"authorization\", false);\n$router-\u003erequest-\u003egetHeader(\"user-agent\", \"Unknown\");\n```\n\n```php\n// Returns key value or all `headers` with `getHeader('name')`\n$router-\u003erequest-\u003egetHeader(string $key = null, $default = null);\n\n// Returns key value or all `?query=string` with `getQuery('name')`\n$router-\u003erequest-\u003egetQuery(string $key = null, $default = null);\n\n// Returns key value or all `body content` with `getBody('name')`\n$router-\u003erequest-\u003egetBody(string $key = null, $default = null);\n\n// Returns key value or all `cookies` with `getCookie('name')`\n$router-\u003erequest-\u003egetCookie(string $key = null, $default = null);\n\n// Returns key value or all `$_FILES` with `getFile('name')`\n$router-\u003erequest-\u003egetFile(string $key = null, $default = null);\n\n// Returns a string like \"GET\" or \"POST\"\n$router-\u003erequest-\u003egetMethod();\n\n// Returns true if the connection is SSL\n$router-\u003erequest-\u003eisSecure();\n\n// Returns the hostname\n$router-\u003erequest-\u003egetHost();\n\n// Returns the requested path\n$router-\u003erequest-\u003egetPath();\n\n// Returns the Content-Type, usually `application/json`\n$router-\u003erequest-\u003egetContentType();\n\n// Returns the RAW body of the request.\n$router-\u003erequest-\u003egetRawBody();\n\n// Returns \"https\" or \"http\"\n$router-\u003erequest-\u003egetScheme();\n\n// Returns the port: 80, 443\n$router-\u003erequest-\u003egetPort();\n\n// Returns the `username` in http://username:password@hostname/path\n// !DANGER! This is insecure and depreciated. Use with caution.\n$router-\u003erequest-\u003egetUser();\n\n// Returns the `password` in http://username:password@hostname/path\n// !DANGER! This is insecure and depreciated. Use with caution.\n$router-\u003erequest-\u003egetPass();\n```\n\n# Response (`PkResponse`)\n\nHeaders and response code do not send until the _payload_ sends.\n\n```php\n// Add a response header.\n$router-\u003eresponse-\u003esetHeader(string $name, string $value = '');\n\n// Clear all set response headers\n$router-\u003eresponse-\u003eclearHeaders();\n\n// Set the response code (200, 404, 500, ...)\n$router-\u003eresponse-\u003esetCode(int $code);\n\n// Sends an Array as JSON.\n// Optionally set the http response code.\n$router-\u003eresponse-\u003esendJson(array $payload, int $code = null);\n/* also */ $router-\u003erespond(array $payload, int $code = null);\n\n// Sends whatever you pass without processing it.\n// Optionally set the http response code.\n$router-\u003eresponse-\u003esendRaw($payload, int $code = null);\n\n// Returns the response payload exactly how it was sent.\n$router-\u003eresponse-\u003egetPayload();\n```\n\n## Extending `PkResponse`\n\nPkRouter only supports JSON out of the box, but you can extend it to do more.\n\n```php\n# ./src/Router/CustomResponse.php\nnamespace YourNamespace\\Router;\n\nuse Pixelkarma\\PkRouter\\PkResponse;\n\nclass CustomResponse extends PkResponse {\n  public function sendXml($xml, int $code = null): bool {\n    $this-\u003esetHeader('Content-Type', 'application/xml');\n    return $this-\u003esendRaw($xml, $code);\n  }\n}\n```\n\n```php\n# ./public/index.php\nuse YourNamespace\\Router\\CustomResponse;\n\n// Create PkRouter with your response class\n$pkRouter = new PkRouter(\n  response: new CustomResponse()\n);\n```\n\n```php\n# ./src/Controllers/MyController.php\nnamespace YourNamespace\\Controllers;\n\nuse Pixelkarma\\PkRouter\\PkRouter;\n\nclass MyController {\n  private $router;\n\n  public function __construct(PkRouter $router) {\n    $this-\u003erouter = $router;\n  }\n\n  public function getXml(){\n    // Execute in your controller/function\n    $this-\u003erouter-\u003eresponse-\u003esendXml($xmlData, int $code = null);\n  }\n}\n```\n\n# Middleware\n\nMiddleware are instances of `PkMiddlewareInterface` that can be\nrun before your route code and after the payload has sent.\n\n\u003e _Note: Middleware is executed in the order you place it in the array._\n\n```php\nnew PkRoute(\n  /* ... */\n  before: [\n    /* PkMiddlewareInterface,\n       PkMiddlewareInterface */\n  ],\n  after: [\n    /* PkMiddlewareInterface */\n  ],\n);\n```\n\n### Creating your own Middleware\n\n\u003e **Note:** If your handle() function returns `false`, it will not continue\n\u003e to the next middleware. The routing will end and `run()` will return _false_.\n\u003e If you need to pass data between middleware, consider returning an array\n\u003e or an object.\n\n```php\nnamespace YourNamespace\\Router\\Middleware;\n\nuse Pixelkarma\\PkRouter\\PkMiddlewareInterface;\nuse Pixelkarma\\PkRouter\\PkRouter;\n\nclass AuthorizationMiddleware implements PkMiddlewareInterface {\n  public function handle(PkRouter $router, $previous = null) {\n    // Check the headers for `auth-token`\n    if (false === $router-\u003erequest-\u003egetHeader(\"auth-token\", false)) {\n      $router-\u003eresponse-\u003esendRaw(\"Unauthorized\", 401);\n      exit; // Also acceptable to return false or throw and Exception\n    }\n    $router-\u003euser = YourAuthorizationCode(\n                      $router-\u003erequest-\u003egetHeader(\"auth-token\")\n                    );\n    return true;\n  }\n}\n```\n\n### Passing information between Middleware\n\n\u003e _Note:_ Middleware returns are not passed to the callback. See [Dynamic Properties](#dynamic-properties).\n\n```php\npublic function handle(PkRouter $router, $previous = 0) {\n  $count = $previous + 1;\n  print \"Count: {$count}\\n\";\n  return $count;\n}\n```\n\n```\nCount: 1\nCount: 2\nCount: 3\nCount: 4\n```\n\n## License\n\nMIT License, see LICENSE.md\n\nCopyright (c) 2024 Pixel Karma, LLC \u003csocial+pkrouter@pixelkarma.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelkarma%2Fpkrouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpixelkarma%2Fpkrouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelkarma%2Fpkrouter/lists"}