Mikronuke

Description

Mikronuke is a small framework for webservices and websites written in PHP.

Setup

Using Composer


$ composer require augmentedlogic/mikronuke
If you do not want to create the folder structure yourself, you may run

$ php vendor/augmentedlogic/mikronuke/src/setup_project.php

Without Composer


$ git clone https://github.com/augmentedlogic/mikronuke.git
See below how to autoload mikronuke without composer.

Project Structure


/srv/myproject/
              composer.json

              /public/
                      index.php   - entry point

              /app/
                      /app/src/       - handlers and other classes 
                      /app/view/      - templates (optional)

              /log/                   - default log directory

              /vendor/                - created when running composer (optional)

Entry Point

Your index.php (the single entry point) does handle the routing:

<?php

require_once dirname(__FILE__).'/../vendor/autoload.php';

$routing = new \com\augmentedlogic\mikronuke\Routing();
          $routing->add("/", "DefaultHandler");
          $mikronuke = new \com\augmentedlogic\mikronuke\Service($routing);
          $mikronuke->setLogLevel(1);
          $mikronuke->boom();
If you do not use composer, you can instead load all mikronuke classes via

require_once '/path/to/mikronuke/src/mn_loader.php';
Note that routes are processed in the order added. You may use wildcards, e.g.:

         $routing->add("/*", "DefaultHandler");

Using parts of the URL as parameters


<?php

require_once dirname(__FILE__).'/../vendor/autoload.php';

$routing = new \com\augmentedlogic\mikronuke\Routing();
          $routing->add("/api/{key}/{value}", "DefaultHandler");
          $routing->add("/", "DefaultHandler");
          $mikronuke = new \com\augmentedlogic\mikronuke\Service($routing);
          $mikronuke->setLogLevel(1);
          $mikronuke->boom();
"{key}" and "{value}" will be converted to GET parameters named "key" and "value" (see "Handling GET and POST Parameters").

Handlers

Once a certain URL matches a set route, the appropriate handler class will be run. By default handlers are located in app/src/ .

A Simple Example Handler


<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;

class DefaultHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {
          $response->addBody("This is an example.");
          $response->addBody("Another bit of info.");
          $response->write();
       }

}
$response->addBody() will add payload to your response. $response->write() will return your complete payload to the client.

Receiving POST and GET Parameter

Note: mikronuke does not distinguish between GET and POST parameters.

<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;

class DefaultHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {

          // returns the Request Method, e.g. GET, POST etc
          $method = $request->getMethod();

          // extract the full path of the request, e.g. "/api/v1/test"
          $path = $request->getPath();

          // get the raw value
          $param = $request->getParameter("a");

          // get a typed value, returns null if the parameter is not set
          $param1 = $request->getInt("b");
          $param3 = $request->getNumber("d");

          // getString() will return a cleaned (tags stripped) string
          $param2 = $request->getString("c");

          // all of the above methods may also be used with a default value
          // if the parameter is null
          $param1 = $request->getInt("b", 7);

          // get the raw post body, e.g. for json POST data
          $postdata = $request->getPostData();

          $response->addBody("This is an example.");
          $response->write();
       }

}

Content Types: Serving A Json Response


<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;

class DefaultHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {
          $response->addBody(json_encode("test", "parameter", "hello"));
          $response->setContentType("application/json");
          $response->write();
       }

}

Reading and Setting Headers


<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;

class DefaultHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {
          // reading a header from a request
          $user_agent = $request->getHeader("user-agent");

          // adding a custom header to a response
          $response->addHeader("custom", "myinfo");
          $response->write();
       }

}

Handling Cookies


<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;
use \com\augmentedlogic\mikronuke\Cookie;


class DefaultHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {

          // get the value of a cookie
          $cookie_value = $request->getCookie("firstcookie");

          // set a new cookie
          $c = new Cookie("testcookie");
          $response->addCookie($c->setValue("thisisacookie")
                                 ->setSecure(true)
                                 ->setHttpOnly(true)
                                 ->setDomain("example.com")
                                 ->setExpires(time() + (Cookie::HOUR * 1))
                                 ->setPath("/"));
          // delete a cookie
          $response->delCookie("oldcookie");

      
          $response->addBody("cookie example");
          $response->write();
       }

}

Handling File Uploads


<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;
use \com\augmentedlogic\mikronuke\Cookie;

class UploadHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {
           $f = $request->getFile("myfile");
           if($f->valid()) {
              $size = $f->getSize();
              $mimetype = $f->getMimetype();
              $f->saveTo("/path/to/cache", $f->getName());
              $response->addBody("File uploaded");
           } else {
              $response->addBody("no file attached");
           }
           $response->write();
     }
}

Logging

Setting the log diretory path Mikronuke comes with a build in service and benchmark log, the service log and the benchmark log are turned off by default. You can configure the logging behaviour in your entry point (where you initialize mikronuke).

    $mikronuke = new \com\augmentedlogic\mikronuke\Service($routing);
    $mikronuke->setLogLevel(1);

    // the default log dir is /myproject/log , but you may set a custom log path
    $mikronuke->setLogDir("/my/log/dir");

    // enable the benchmark.log
    $mikronuke->enableBenchmarkLog();

    // enable the service.log
    $mikronuke->enableServiceLog();
Of course, you can also log your own messages, by default those will be written to a file called app.log, but you can also set the name of the file to log to.

    // write to app.log
    Toolkit::log("hello world");

    // write to app.log with a log level. If global the loglevel is equal or smaller than what you set here,
    // the message will be logged 
    Toolkit::log("hello world", 1);

    // write to a custom log file inside your log dir
    Toolkit::log("hello world", 1 , "custom.log");

Toolkit

The Toolkit class comes with a few help full static methods

      // returns a random HEX string, 24 characters long
      $s = Toolkit::genRandomString(24, Toolkit::RANDOM_HEX);
      
      // returns a random BASE64 encoded string, 24 characters long
      $s = Toolkit::genRandomString(24, Toolkit::RANDOM_BASE64);

      // returns a random 24 characters long alphanumeric string
      $s = Toolkit::genRandomString(24, Toolkit::RANDOM_ALNUM);

      // returns a random UUID v4
      $s = Toolkit::genUUIDv4();

NanoTemplate - an extremely tiny template library

NanoTemplate is a very simple way to use templates, it supports * single variables in a template * subtemplates An example template (test.html) looks like this

<h1>Hello {$var}</h1>

<p>
Message: {% _subtemp.html %}
</p>
and the subtemplate

This is a message for {$person}.
The two files (test.html, _subtemp.html) will be located in app/view Using this in a handler

<?php

use \com\augmentedlogic\mikronuke\Request;
use \com\augmentedlogic\mikronuke\Response;
use \com\augmentedlogic\mikronuke\HttpHandler;
use \com\augmentedlogic\mikronuke\NanoTemplate;

class DefaultHandler implements HttpHandler
{

      public function handle(Request $request, Response $response)
      {
          $nt = new NanoTemplate("test.html");
          $nt->set("var", "World");
          $nt->set("person", "you");
          $html = $nt->render();

          $response->addBody($html);
          $response->write();
       }

Other Utils

HttpClient

A simple get request:

           $httpclient = new HttpClient();
           $json = $httpclient->get("https://example.com/api/item/1");
A more elaborate example

           $httpclient = new HttpClient();
           $httpclient->addHeader("Token", "XXXXXXXX");
           $httpclient->setFollowRedirect(true);
           $httpclient->setUserAgent("my-client 1.0");
           $payload = $httpclient->get("https://example.com/api/item/1");
           $httpclient->getStatusCode();
A post example

           $httpclient = new HttpClient();
           $httpclient->setParameter("firstname", "john");
           $httpclient->setParameter("lastname", "doe")
           $payload = $httpclient->post("https://example.com/api/postbox");

Server Setup

For Apache with mod-php

<VirtualHost *:80>
        ServerName example.com
        DocumentRoot /path/to/my/public

        <Directory /path/to/my/public>
          RewriteEngine on
          RewriteCond %{REQUEST_FILENAME} !-d
          RewriteCond %{REQUEST_FILENAME} !-f
          RewriteRule . /index.php [L]
          AllowOverride All
          Require all granted
        </Directory>
</VirtualHost>
For Nginx with php-fpm

server {

    root /path/to/public;
    server_name example.com;

    try_files $uri $uri/ /index.php?$args;

    location ~ \.php$ {
            include /etc/nginx/fastcgi_params;
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root/index.php;
            fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
    }

}

FAQ

Isn't "mikronuke" spelled wrongly?

Yes it is. It's deliberate.

Should I use mikronuke for a large project?

You may, though some other frameworks offer much more for that purpose.

Is anyone actually using mikronuke in real life?

Yes.

Where is the source code?
https://github.com/augmentedlogic/mikronuke

License

Mikronuke is licensed under the Apache-2.0 License.