gyselroth/micro

This package is abandoned and no longer maintained. The author suggests using the micro-http, micro-container, micro-auth package instead.

Micro PHP library

0.0.5 2017-10-26 14:50 UTC

This package is not auto-updated.

Last update: 2018-02-01 12:04:01 UTC


README

Use the micro components instead:

  • micro-auth
  • micro-log
  • micro-config
  • micro-container
  • micro-http

Micro (Yet another PHP library)

...but no shit

Build Status Scrutinizer Code Quality Latest Stable Version GitHub release GitHub license

Description

Micro provides minimalistic core features to write a new Application. Instead providing a rich featured fatty library it only provides a couple of namespaces. It comes with a logger (and multiple adapters), configuration parser, HTTP routing/response, Authentication (and multiple adapters) and some wrapper around databases and ldap.

  • \Micro\Auth
  • \Micro\Config
  • \Micro\Container
  • \Micro\Http
  • \Micro\Log

Requirements

The library is only >= PHP7.1 compatible.

Download

The package is available at packagist: https://packagist.org/packages/gyselroth/micro

To install the package via composer execute:

composer require gyselroth/micro

Configuration (\Micro\Config)

Read

Simply read an xml configuration and initialize your configuration:

$config = new \Micro\Config(new \Micro\Config\Xml($path));
var_dump($config->myconfigentry);
string(1) "1"

And your actual XML configuration would look like:

<config version="1.0">
  <production>
    <myconfigentry>1</myconfigentry>
  </production>
</config>

Every configuration got configuration environment, if you only have one, just stick with as your first node within . See environments for further information.

Merge

Merge multiple configuration files:

$config1 = new \Micro\Config\Xml($path);
$config2 = new \Micro\Config\Xml($path);
$config1->merge($config2);
$config = new \Micro\Config($config1);

Environments

You can request a custom configuration environment:

$config = new \Micro\Config(new \Micro\Config\Xml($path, 'development'));
var_dump($config->myconfigentry);
string(1) "2"

While your XML configuration would look like:

<config version="1.0">
  <production>
    <myconfigentry>1</myconfigentry>
  </production>
  <development>
    <myconfigentry>2</myconfigentry>
  </development>
</config>

Inheritance

The configuration parser supports inheritance. A simple example would be to just inherit one environment from another:

<config version="1.0">
  <production>
    <a>a</a>
  </production>
  <development inherits="production">
  </development>
</config>
$config = new \Micro\Config(new \Micro\Config\Xml($path, 'development'));
var_dump($config->a);
string(1) "a"

You can also inherit single elements (recursively) within one environment and overwrite elements which were inherit in the first place:

<config version="1.0">
  <production>
    <a>a</a>
    <b inherits="a"/>
    <c>
        <child>c</child>
    </c>
    <d inherits="c">
        <child2>d</child2>
    </d>
  </development>
</config>
$config = new \Micro\Config(new \Micro\Config\Xml($path));
var_dump($config->a);
string(1) "a"

var_dump($config->b);
string(1) "a"

var_dump($config->c->child);
string(1) "c"

var_dump($config->d->child);
var_dump($config->d->child2);
string(1) "c"
string(1) "d"

It possible as well to access any elements (node path is separated with a "."):

<config version="1.0">
  <production>
    <a>
        <child>
            <subchild>a</subchild>
        </child>
    </a>
    <b inherits="c">
        <child inherits="a.child">
        <child2 inherits="a.child.subchild">
    </b>
  </development>
</config>
$config = new \Micro\Config(new \Micro\Config\Xml($path));
var_dump($config->a->child->subchild);
string(1) "a"

var_dump($config->b->child->subchild);
var_dump($config->b->child2);
string(1) "a"
string(1) "a"

XML Attributes

There is no more a difference between XML attributes and XML nodes. \Micro\Config\Xml parses both equally. So you can decide or switch on the fly whether a name/value should be an attribute or a node.

<config version="1.0">
  <production>
    <a enabled="1"/>
  </development>
</config>

Meaning the above configuration gets parsed as the same Config object as the following:

<config version="1.0">
  <production>
    <a>
      <enabled>1</enabled>
    </a>
  </development>
</config>

Logger (\Micro\Log)

Description

\Micro\Log is a PSR-3 compatible logger with multiple log adapters.

Initialize

$logger = new Logger(Iterable $options);
$logger->info(string $message, array $context);

Configuration

$logger = new Logger([
  'adapter_name' => [
    'class'  => '\Micro\Log\Adapter\File',
    'config' => [
      'file'        => '/path/to/file',
      'date_format' => 'Y-d-m H:i:s', //http://php.net/manual/en/function.date.php
      'format'      => '{date} {level} {message} {context.category}',
      'level'       => 7 //PSR-3 log levels 1-7
    ],
  ],
  'adapter2_name' => []
]);

Of course you can initialize the logger with a configuration object as well (any any other iterable objects):

<log>
  <adapter_name enabled="1" class="\Micro\Log\Adapter\File">
    <config>
      <file>/path/to/file</file>
      <date_format>Y-d-m H:i:s</date_format>
      <format>{date} {level} {message} {context.category}</format>
      <level>7</level>
    </config
  </adapter_name>
</log>
$config = new \Micro\Config(new \Micro\Config\Xml($path));
$logger = new Logger($config);

Format

The message formate is configured in each adapter separately. Available variables are:

  • {message} - The message iteself
  • {date} - The current timestamp formatted with the configured date_format option
  • {level} - The log level, the configured number will be replaced with a string, for exampe 7 => debug
  • {context.} - You can acces each context option and include them in the message format. For example you have a context ['category' => 'router'] then you can configure {context.category} to include this context value within your message.

Log adapters

  • \Micro\Log\Adapter\File
  • \Micro\Log\Adapter\Blackhole
  • \Micro\Log\Adapter\Stdout
  • \Micro\Log\Adapter\Syslog

You can always create your own log adapter using \Micro\Log\Adapter\AdapterInterface.

HTTP (\Micro\Http)

Initialize router

The http router requires an array with http headers, usually this is $_SERVER and a PSR-3 compatible logger.

$router = new \Micro\Http\Router(array $server, \Psr\Log\LoggerInterface $logger)

Adding routes

$router = (new \Micro\Http\Router($_SERVER, $logger))
  ->clearRoutingTable()
  ->addRoute(new \Micro\Http\Router\Route('/api/v1/user', 'MyApp\Rest\v1\User'))
  ->addRoute(new \Micro\Http\Router\Route('/api/v1/user/{uid:#([0-9a-z]{24})#}', 'MyApp\Rest\v1\User'))
  ->addRoute(new \Micro\Http\Router\Route('/api/v1$', 'MyApp\Rest\v1\Rest'))
  ->addRoute(new \Micro\Http\Router\Route('/api/v1', 'MyApp\Rest\v1\Rest'))
  ->addRoute(new \Micro\Http\Router\Route('/api$', 'MyApp\Rest\v1\Rest'));
  ->run(array $controller_params);

The router tries to map a request to the first matching route in his routing table. The request gets mappend to a class and method. Optional parameters/query string gets automatically submitted to the final controller class.

Given the routing table above and the following final controller class:

namespace MyApp\Rest\v1;

class User
{
    /**
     * GET http://localhost/api/v1/user/540f1fc9a641e6eb708b4618/attributes
     * GET http://localhost/api/v1/user/attributes?uid=540f1fc9a641e6eb708b4618
     */
    public function getAttributes(string $uid=null): \Micro\Http\Response
    {

    }

    /**
     * GET http://localhost/api/v1/user/540f1fc9a641e6eb708b4618
     * GET http://localhost/api/v1/user?uid=540f1fc9a641e6eb708b4618
     */
    public function get(string $uid=null): \Micro\Http\Response
    {

    }

    /**
     * POST http://localhost/api/v1/user/540f1fc9a641e6eb708b4618/password / POST body password=1234
     * POST http://localhost/api/v1/user/password?uid=540f1fc9a641e6eb708b4618 / POST body password=1234
     * POST http://localhost/api/v1/user/password / POST body password=1234, uid=540f1fc9a641e6eb708b4618
     */
    public function postPassword(string $uid, string $password): \Micro\Http\Response
    {

    }

    /**
     * DELETE http://localhost/api/v1/user/540f1fc9a641e6eb708b4618/mail
     * DELETE http://localhost/api/v1/user/mail?uid=540f1fc9a641e6eb708b4618
     */
    public function deleteMail(string $uid=null): \Micro\Http\Response
    {

    }

    /**
     * DELETE http://localhost/api/v1/540f1fc9a641e6eb708b4618/mail
     * DELETE http://localhost/api/v1/user?uid=540f1fc9a641e6eb708b4618
     */
    public function delete(string $uid=null): \Micro\Http\Response
    {

    }

    /**
     * HEAD http://localhost/api/v1/user/540f1fc9a641e6eb708b4618
     * HEAD http://localhost/api/v1/user?uid=540f1fc9a641e6eb708b4618
     */
    public function headExists(string $uid=null): \Micro\Http\Response
    {

    }
}

Response

Each endpoint needs to return a Response object to the router.

/**
 * HEAD http://localhost/api/v1/user/540f1fc9a641e6eb708b4618
 * HEAD http://localhost/api/v1/user?uid=540f1fc9a641e6eb708b4618
 */
public function headExists(string $uid=null): \Micro\Http\Response
{
  if(true) {
    return (new \Micro\Http\Response())->setCode(200)->setBody('user does exists');
  } else {
    return (new \Micro\Http\Response())->setCode(404);  
  }
}