Implementation of an API application using the Phalcon Framework

Overview

phalcon-api

Sample API using Phalcon

Scrutinizer Code Quality Code Coverage Build Status

Implementation of an API application using the Phalcon Framework https://phalcon.io

Installation

  • Clone the project
  • In the project folder run nanobox run php-server
  • Hit the IP address with postman

NOTE This requires nanobox to be present in your system. Visit their site for installation instructions.

Features

JWT Tokens

As part of the security of the API, JWT are used. JSON Web Tokens offer an easy way for a consumer of the API to send requests without the need to authenticate all the time. The expiry of each token depends on the setup of the API. An admin can easily keep the expiry very short, thus consumers will always have to log in first and then access a resource, or they can increase the "life" of each token, thus having less calls to the API.

Middleware
  • Lazy loading to save resources per request
  • Stop execution as early as possible when an error occurs
  • Execution
    • NotFound - 404 when the resource requested is not found
    • Authentication - After a /login checks the Authentication header
    • TokenUser - When a token is supplied, check if it corresponds to a user in the database
    • TokenVerification - When a token is supplied, check if it is correctly signed
    • TokenValidation - When a token is supplied, check if it is valid (issuedAt, notBefore, expires)
JSONAPI

This implementation follows the JSON API standard. All responses are formatted according to the standard, which offers a uniformed way of presenting data, simple or compound documents, includes (related data), sparse fieldsets, sorting, patination and filtering.

Usage

Requests

The routes available are:

Method Route Parameters Action
POST login username, password Login - get Token
POST companies name, address, city, phone Add a company record in the database
GET companies Get companies. Empty resultset if no data present
GET companies Numeric Id Get company by id. 404 if record does not exist
GET individuals Get individuals. Empty resultset if no data present
GET individuals Numeric Id Get individual by id. 404 if record does not exist
GET individual-types Get individual types. Empty resultset if no data present
GET individual-types Numeric Id Get individual type by id. 404 if record does not exist
GET products Get products. Empty resultset if no data present
GET products Numeric Id Get product by id. 404 if record does not exist
GET product-types Get product types. Empty resultset if no data present
GET product-types Numeric Id Get product type by id. 404 if record does not exist
GET users Get users. Empty resultset if no data present
GET users Numeric Id Get user by id. 404 if record does not exist

Relationships

/companies/<number>?included=<individuals>,<products>

individuals/<number>?included=<companies>,<individual-types>

individual-types/<number>?included=<individuals>

products/<number>?included=<companies>,<product-types>

product-types/<number>?included=<products>

Fields

/companies?fields[<relationship>]=<field>,<field>&fields[<relationship>]=<field>,<field>

Sorting

/companies?sort=<[-]id>,<[-]status>,<[-]username>,<[-]issuer>

individuals?sort=<[-]id',<[-]companyId>,<[-]typeId>,<[-]prefix>,<[-]first>,<[-]middle>,<[-]last>,<[-]suffix'>,

individual-types?sort=<[-]id>,<[-]name>

products?sort=<[-]id',<[-]typeId>,<[-]name>,<[-]quantity>,<[-]price>

product-types?sort=<[-]id>,<[-]name>

Responses

Structure

Top Elements

  • jsonapi Contains the version of the API as a sub element
  • data Data returned. Is not present if the errors is present
  • errors Collection of errors that occurred in this request. Is not present if the data is present
  • meta Contains timestamp and hash of the json_encode($data) or json_encode($errors)

After a GET the API will always return a collection of records, even if there is only one returned. If no data is found, an empty resultset will be returned.

Each endpoint returns records that follow this structure:

{
  "id": 1051,
  "type": "users",
  "attributes": {
    "status": 1,
    "username": "niden",
    "issuer": "https:\/\/niden.net",
    "tokenPassword": "11110000",
    "tokenId": "11001100"
  }
}

The record always has id and type present at the top level. id is the unique id of the record in the database. type is a string representation of what the object is. In the above example it is a users record. Additional data from each record are under the attributes node.

Samples

404

{
  "jsonapi": {
    "version": "1.0"
  },
  "errors": {
    "404 not found"
  },
  "meta": {
    "timestamp": "2018-06-08T15:04:34+00:00",
    "hash": "e6d4d57162ae0f220c8649ae50a2b79fd1cb2c60"
  }
}

Error

{
  "jsonapi": {
    "version": "1.0"
  },
  "errors": {
    "Description of the error no 1",
    "Description of the error no 2"
  },
  "meta": {
    "timestamp": "2018-06-08T15:04:34+00:00",
    "hash": "e6d4d57162ae0f220c8649ae50a2b79fd1cb2c60"
  }
}
Success
{
  "jsonapi": {
    "version": "1.0"
  },
  "data": [
  ],
  "meta": {
    "timestamp": "2018-06-08T15:04:34+00:00",
    "hash": "e6d4d57162ae0f220c8649ae50a2b79fd1cb2c60"
  }
}

/products/1134?includes=companies,product-types

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": [
    {
      "type": "products",
      "id": "1134",
      "attributes": {
        "typeId": 890,
        "name": "prd-a-5b64af7e70741",
        "description": "5b64af7e7074a",
        "quantity": 25,
        "price": "19.99"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/products\/1134"
      },
      "relationships": {
        "companies": {
          "links": {
            "self": "http:\/\/api.phalcon.ld\/products\/1134\/relationships\/companies",
            "related": "http:\/\/api.phalcon.ld\/products\/1134\/companies"
          },
          "data": [
            {
              "type": "companies",
              "id": "1430"
            },
            {
              "type": "companies",
              "id": "1431"
            }
          ]
        },
        "product-types": {
          "links": {
            "self": "http:\/\/api.phalcon.ld\/products\/1134\/relationships\/product-types",
            "related": "http:\/\/api.phalcon.ld\/products\/1134\/product-types"
          },
          "data": {
            "type": "product-types",
            "id": "890"
          }
        }
      }
    }
  ],
  "included": [
    {
      "type": "companies",
      "id": "1430",
      "attributes": {
        "name": "com-a5b64af7e6c846",
        "address": "5b64af7e6c84f",
        "city": "5b64af7e6c855",
        "phone": "5b64af7e6c85c"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/companies\/1430"
      }
    },
    {
      "type": "companies",
      "id": "1431",
      "attributes": {
        "name": "com-b5b64af7e6e3d3",
        "address": "5b64af7e6e3dc",
        "city": "5b64af7e6e3e2",
        "phone": "5b64af7e6e3e9"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/companies\/1431"
      }
    },
    {
      "type": "product-types",
      "id": "890",
      "attributes": {
        "name": "prt-a-5b64af7e6f638",
        "description": "5b64af7e6f641"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/product-types\/890"
      }
    }
  ],
  "meta": {
    "timestamp": "2018-08-03T19:39:42+00:00",
    "hash": "384c6b3772727b1a9532865d2ae2d51c095c0fd9"
  }
}

For more information regarding responses, please check JSON API

TODO

  • Work on companies GET
  • Work on included data
  • Work on sorting
  • Write examples of code to send to the client
  • Create docs endpoint
  • Work on relationships
  • Work on pagination
  • Work on filters
  • Sorting on related resources
  • Perhaps add a new claim to the token tied to the device? setClaim('deviceId', 'Web-Server'). This will allow the client application to invalidate access to a device that has already been logged in.

Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]

Backers

Support us with a monthly donation and help us continue our activities. [Become a backer]

Comments
  • How to use automatical Routing?

    How to use automatical Routing?

    In Phalcon we can define a default route that includes a module wildcard:

    <?php
    
    use Phalcon\Mvc\Router;
    
    $router = new Router(false);
    
    $router->add(
        '/:module/:controller/:action/:params',
        [
            'module'     => 1,
            'controller' => 2,
            'action'     => 3,
            'params'     => 4,
        ]
    );
    

    How to use automatical routing in the REST api? It seems to be added manually:

    $routes = [
                // Class, Method, Route, Handler
                [LoginController::class,        '/login',     'post', '/'],
                [CompaniesAddController::class, '/companies', 'post', '/'],
                [UsersGetController::class,     '/users',     'get',  '/'],
                [UsersGetController::class,     '/users',     'get',  '/{recordId:[0-9]+}'],
            ];
    
    question 
    opened by xaero7 2
  • v5.0.0 prep

    v5.0.0 prep

    Prep for v5.0.0

    Before tagging we will need to change the pecl installation (in actions) for stable. Some of the functionality has not been released yet.

    opened by niden 1
  • How to access users, companies... with request?

    How to access users, companies... with request?

    For example, when I visit with postman http://localhost/users, It returns Invalid Token:

    {"jsonapi":{"version":"1.0"},"errors":["Invalid Token"],"meta":{"timestamp":"2020-02-10","hash":"76f4972fb2132f97070a0c8904c0f61de14a"}}
    

    How to access the lists of users, companies...etc.

    wontfix 
    opened by xaero7 1
  • Phalcon v4 [Iteration 2]

    Phalcon v4 [Iteration 2]

    • [x] Change domain to phalcon.io
    • [x] Add license to header in .php files
    • [x] Rename namespaces from Niden to Phalcon\Api
    • [x] Change usage of Phalcon\Plugin to Injectable
    • [x] Review rest of comments and suggestions in comments of #22 PR
    • [x] Return back usage of use Phalcon\Filter; (https://github.com/phalcon/phalcon-api/pull/22#discussion_r322131277)
    • [x] Psalm integration with (less strict) level 8 of checks
    • [x] PSR-2 (in code)
    • [x] Bug fixes (if any)
    • [x] Minor code refactors
    • [x] Refactor tests/unit/BootstrapCest.php by moving into bootstrap or/and module initialization
    • [x] Fix env CODECEPTION_* variables
    • [x] Adapt Cache Service Provider to get adapter from config and not work only with memcached
    • [x] See if envValue() function is needed
    • [x] ~Create conditional import of Phalcon\Filter for 4.0.0-beta.2~
    • [x] ~Travis integration~ (#25)
    • [x] ~Scrutinizer CI fix/reboot~ (#26)
    enhancement 
    opened by Jeckerson 1
  • Fixed API tests

    Fixed API tests

    You don't need to use Codeception's Phalcon module for API tests suite. These tests should be run in such way that they do not know anything about your code. So you shouldn't include tests/index.php, mock application classes, create stubs on fly, etc, what actually does Codeception's Phalcon module. API tests suite tests only the HTTP public interface (request and response) and that's what REST module actually does.

    Also I've moved global modules configuration to the codeception.yml.

    selection_024

    selection_025

    opened by sergeyklay 1
  • Sparse Fieldsets

    Sparse Fieldsets

    • [x] A client MAY request that an endpoint return only specific fields in the response on a per-type basis by including a fields[TYPE] parameter.
    • [x] The value of the fields parameter MUST be a comma-separated (U+002C COMMA, “,”) list that refers to the name(s) of the fields to be returned.
    • [x] If a client requests a restricted set of fields for a given resource type, an endpoint MUST NOT include additional fields in resource objects of that type in its response.
    GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
    Accept: application/vnd.api+json
    

    Note: The above example URI shows unencoded [ and ] characters simply for readability. In practice, these characters must be percent-encoded, per the requirements in RFC 3986.

    enhancement 
    opened by niden 0
  • Introduce sort capability

    Introduce sort capability

    Per the documentation

    • [x] A server MAY choose to support requests to sort resource collections according to one or more criteria (“sort fields”).
    • [x] An endpoint MAY support requests to sort the primary data with a sort query parameter. The value for sort MUST represent sort fields.
    • [x] An endpoint MAY support multiple sort fields by allowing comma-separated (U+002C COMMA, “,”) sort fields. Sort fields SHOULD be applied in the order specified.
    • [x] The sort order for each sort field MUST be ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, “-“), in which case it MUST be descending.
    • [x] If the server does not support sorting as specified in the query parameter sort, it MUST return 400 Bad Request.
    • [x] If sorting is supported by the server and requested by the client via query parameter sort, the server MUST return elements of the top-level data array of the response ordered according to the criteria specified. The server MAY apply default sorting rules to top-level data if request parameter sort is not specified.
    enhancement 
    opened by niden 0
  • How to read additional fields?

    How to read additional fields?

    opened by xaero7 0
  • running without nanobox

    running without nanobox

    Hi, I'm more comfortable running php apps without nanobox, docker etc, I can understand better..

    I managed to do following:

    1. built the app with composer install
    2. ran vendor/bin/phinx migrate that created tables
    3. ran vendor/bin/phinx seed:run --> nothing seems to happen -- is there any sample data? if not how do i create password
    4. checked db and tables are there but no data

    once i do this, i am encountered with 2 issues

    1. GET URL like /companies gives "Invalid Token" -- i guess this is understanble as i've not logged in got token
    2. POST URL like /login gives 500 Internal server error PHP Fatal error: Uncaught Phalcon\Mvc\Model\Exception: Failed to store metaData to the cache adapter in /apps/phalcon/rest-api/library/Traits/QueryTrait.php:137

    Any ideas how to resolve this .. thanks

    opened by rnvijay 2
  • Unable to write to metaData

    Unable to write to metaData

    Hello,

    I've built this project around Docker and have configured the right dependencies, project, but when I run a request to login, I keep getting an error exception thrown the MetaData class.

    Here is the exact error:

    <br />
    <b>Fatal error</b>:  Uncaught Phalcon\Mvc\Model\Exception: Failed to store metaData to the cache adapter in /api/library/Traits/QueryTrait.php:139
    Stack trace:
    #0 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;throwWriteException(true)
    #1 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;write('map-phalcon\\api...', Array)
    #2 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;initialize(Object(Phalcon\Api\Models\Users), NULL, NULL, NULL)
    #3 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;readColumnMapIndex(Object(Phalcon\Api\Models\Users), 1)
    #4 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;getReverseColumnMap(Object(Phalcon\Api\Models\Users))
    #5 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;hasAttribute(Object(Phalcon\Api\Models\Users), 'username')
    #6 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getQualified(Array)
    #7 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getExpression(Array, true)
    #8 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getExpression(Array, true)
    #9 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getEx in <b>/api/library/Traits/QueryTrait.php</b> on line <b>139</b><br />
    

    I did make sure that memcached was installed and also running on my machine. Permissions seem to be correct on the folders as it is able to write logs within the storage directory.

    Do you have any suggestions?

    opened by davidbiga 8
  • Scrutinizer CI fix/reboot [Iteration 4]

    Scrutinizer CI fix/reboot [Iteration 4]

    Moved from #23

    Creating current issue as separate one, because of many separate work to do, with many commits...

    https://github.com/phalcon/phalcon-api/blob/master/scrutinizer.yml

    enhancement 
    opened by Jeckerson 0
  • Github Actions integration

    Github Actions integration

    Moved from #23

    Creating current issue as separate one, because of many separate work to do, with many commits...

    • https://github.com/niden/cardoe/blob/master/.scrutinizer.yml
    • https://github.com/niden/cardoe/blob/master/.github/workflows/php.yml
    enhancement 
    opened by Jeckerson 0
Releases(v5.0.0)
  • v5.0.0(Sep 25, 2022)

  • v2.0.0(Dec 26, 2019)

  • v1.1.1(Aug 3, 2018)

    • Fixed code and tests to use "?includes" for included data
    • Corrected README
    • Fixed cache provider (lazy loading)
    • Fixed issue with unused code; Corrected logic for unknown include
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Aug 3, 2018)

    • Get for Companies
    • Get for Individuals
    • Get for Individual Types
    • Get for Products
    • Get for Product Types
    • Parsing of relationships
    • Followed the JSON API standard more closely correcting links
    • Issue 404 when records not found
    • Added more tests for edge cases
    • 100% code coverage and Rating 10 on Scrutinizer
    • Refactored and reused code in base controllers
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jul 18, 2018)

Owner
The Phalcon PHP Framework
High performance, full-stack PHP framework delivered as a C extension.
The Phalcon PHP Framework
A Phalcon paginator adapter for Phalcon Collections

Phalcon Collection Paginator A Phalcon paginator adapter for Phalcon Collections Why create this? Being familiar with the various Pagination data adap

Angel S. Moreno 2 Oct 7, 2022
Invo - Sample application for the Phalcon PHP Framework

INVO Application Phalcon is a web framework delivered as a C extension providing high performance and lower resource consumption. This is a sample app

The Phalcon PHP Framework 344 Dec 14, 2022
Album-o-rama - Sample application for the Phalcon PHP Framework.

Album O'Rama Phalcon PHP is a web framework delivered as a C extension providing high performance and lower resource consumption. This is a sample app

The Phalcon PHP Framework 84 Oct 7, 2022
This repository demonstrates exemplary implementation of chat using HTTP and Websocket servers in PHP using Kraken Framework components.

This repository demonstrates exemplary implementation of chat using HTTP and Websocket servers in PHP using Kraken Framework components.

Kraken 48 Aug 11, 2021
Phalcon Demo Application

Phalcon Demo Application We use modified Phalcon INVO Application to demonstrate basics of Codeception testing. We expect to implement as many feature

Codeception Testing Framework 42 Oct 7, 2022
Easy Repository pattern for PHP Phalcon framework.

Phalcon Repositories Introduction Phalcon Repositories lets you easily build repositories for your Phalcon models, for both SQL and Mongo drivers. PHP

Michele Angioni 18 Oct 7, 2022
Incubator adapters/functionality for the Phalcon PHP Framework

Phalcon Incubator This is a repository to publish/share/experiment with new adapters, prototypes or functionality that can potentially be incorporated

The Phalcon PHP Framework 735 Dec 27, 2022
A powerful debug and profilers tool for the Phalcon Framework

Phalcon Debugbar Integrates PHP Debug Bar with Phalcon Framework. 中文说明 Features Normal request capturing Ajax request capturing Redirect request chain

Yajie Zhu 162 Oct 7, 2022
CMS based on Phalcon PHP Framework with modular structure

Yona CMS Yona CMS - open source content management system (CMS). Written in Phalcon PHP Framework (version 3.x supported) Has a convenient modular str

Alexander Torosh 369 Dec 27, 2022
A composer package designed to help you create a JSON:API in Phalcon

phalcon-json-api-package A composer package designed to help you create a JSON:API in Phalcon What happens when a PHP developer wants to create an API

Jim 36 Oct 7, 2022
Phalcon Mooc an example API + Front End with automated tests

NovaMooc - a Phalcon project A Mooc project developed with Phalcon, a PHP framework. Key Features • How To Use • Contributing • Credits • License Key

Les Enovateurs 19 Dec 4, 2022
Phalcon official Forum

Phosphorum 3 Phosphorum is an engine for building flexible, clear and fast forums. You can adapt it to your own needs or improve it if you want. Pleas

The Phalcon PHP Framework 361 Dec 27, 2022
Phalcon PHP Meta tags Service

About Phalcon meta tags plugin for PhalconPHP. This plugin allows you to easily and flexibly customize the meta tags of your view. If this plugin help

null 12 Oct 7, 2022
Setupify is a Phalcon provisioning and development tool.

Setupify Provisioning Tool WARNING: Setupify is currently in a state of experimentation. Use tag release. Setupify is a collection of bash scripts for

Perch Labs 3 Oct 7, 2022
RedisPlugin for Phalcon

RedisPlugin for Phalcon (The correspondence of MySQL sharding.) Composer { "require": { "ienaga/phalcon-redis-plugin": "3.*" } } Versio

Toshiyuki Ienaga 16 Oct 7, 2022
Phalcon devtools

Yarak yarak - (Falconry) a state of prime fitness in a falcon Laravel inspired Phalcon devtools Database migrations that rollback step-by-step, reset

Zach Leigh 27 Oct 7, 2022
PHP Profiler & Developer Toolbar (built for Phalcon)

Prophiler - A PHP Profiler & Developer Toolbar built for Phalcon Demo The demo website has been moved to a separate repository: https://github.com/fab

Fabian Fuelling 444 Dec 27, 2022
Phalcon 3.x BB Debugger Strong and easy install.

Phalcon BB Debugger Phalcon Version: 3.x BB Debugger Version: 1.0.3 Change Log See ChangeLog What is BB Debugger ? The bb debugger, written for the ph

İsmail 6 Oct 7, 2022
Time registration tool build with Phalcon

PhalconTime Application PhalconTime is a timekeeping tool that helps you track hours spend on clients and projects. Please write me if you have any fe

null 6 Oct 7, 2022