GithubHelp home page GithubHelp logo

tuupola / slim-api-skeleton Goto Github PK

View Code? Open in Web Editor NEW
312.0 24.0 62.0 239 KB

Slim 3 API skeleton project for Composer

License: MIT License

PHP 98.49% Makefile 1.36% Shell 0.14%
rest php api slim3 skeleton

slim-api-skeleton's Introduction

Slim 3 API skeleton

Software License Build Status Coverage

This is Slim 3 API skeleton project for Composer. Project uses Zend Table Gateway and Phinx for database operations, Monolog for logging, and Fractal as a serializer. Vagrant virtualmachine config and Paw project files are included for easy development. The skeleton tries to follow DDD principles.

Install

Install the latest version using composer.

$ composer create-project --no-interaction --stability=dev tuupola/slim-api-skeleton app

Usage

If you have Vagrant installed start the virtual machine.

$ cd app
$ vagrant up

Now you can access the api at https://192.168.50.52/todos

Get a token

$ curl "https://192.168.50.52/token" \
    --request POST \
    --include \
    --insecure \
    --header "Content-Type: application/json" \
    --data '["todo.all"]' \
    --user test:test

HTTP/1.1 201 Created
Content-Type: application/json

{
    "token": "XXXXXXXXXX",
    "expires": 1491030210
}
$ export TOKEN=XXXXXXXXXX

Create a new todo

$ curl "https://192.168.50.52/todos" \
    --request POST \
    --include \
    --insecure \
    --header "Authorization: Bearer $TOKEN" \
    --header "Content-Type: application/json" \
    --data '{ "title": "Test the API", "order": 10 }'

HTTP/1.1 201 Created
ETag: "c39de417d4d1f5fe22d19cad68d672d8"
Last-Modified: Sat, 16 Apr 2016 10:21:50 GMT
Location: /todos/12Cf2ZjVvyu3A
Content-Type: application/json

{
    "data": {
        "uid": "12Cf2ZjVvyu3A",
        "order": 10,
        "title": "Test the API",
        "completed": false,
        "links": {
            "self": "/todos/12Cf2ZjVvyu3A"
        }
    }
}

Get an existing todo

$ curl "https://192.168.50.52/todos/12Cf2ZjVvyu3A" \
    --include \
    --insecure \
    --header "Authorization: Bearer $TOKEN"

HTTP/1.1 200 OK
ETag: "c39de417d4d1f5fe22d19cad68d672d8"
Last-Modified: Sat, 16 Apr 2016 10:21:50 GMT
Content-Type: application/json

{
    "data": {
        "uid": "12Cf2ZjVvyu3A",
        "order": 10,
        "title": "Test the API",
        "completed": false,
        "links": {
            "self": "/todos/12Cf2ZjVvyu3A"
        }
    }
}

Update part of an existing todo

$ curl "https://192.168.50.52/todos/12Cf2ZjVvyu3A" \
    --request PATCH \
    --include \
    --insecure \
    --header "Authorization: Bearer $TOKEN" \
    --header "Content-Type: application/json" \
    --header 'If-Match: "c39de417d4d1f5fe22d19cad68d672d8"' \
    --data '{ "order": 27 }'

HTTP/1.1 200 OK
ETag: "ab6070930158fc8323aa4550aff438b7"
Last-Modified: Sat, 16 Apr 2016 10:27:16 GMT
Content-Type: application/json

{
    "data": {
        "uid": "12Cf2ZjVvyu3A",
        "order": 27,
        "title": "Test the API",
        "completed": false,
        "links": {
            "self": "/todos/12Cf2ZjVvyu3A"
        }
    }
}

Fully update an existing todo

$ curl "https://192.168.50.52/todos/12Cf2ZjVvyu3A" \
    --request PUT \
    --include \
    --insecure \
    --header "Authorization: Bearer $TOKEN" \
    --header "Content-Type: application/json" \
    --header 'If-Match: "ab6070930158fc8323aa4550aff438b7"' \
    --data '{ "title": "Full update", "order": 66, "completed": true }'

HTTP/1.1 200 OK
ETag: "451665ea7769851880f411750bbd873c"
Last-Modified: Sat, 16 Apr 2016 10:28:45 GMT
Content-Type: application/json

{
    "data": {
        "uid": "12Cf2ZjVvyu3A",
        "order": 66,
        "title": "Full update",
        "completed": true,
        "links": {
            "self": "/todos/12Cf2ZjVvyu3A"
        }
    }
}

Delete an existing todo

$ curl "https://192.168.50.52/todos/12Cf2ZjVvyu3A" \
    --request DELETE \
    --include \
    --insecure \
    --header "Authorization: Bearer $TOKEN"

HTTP/1.1 204 No Content

License

The MIT License (MIT). Please see License File for more information.

slim-api-skeleton's People

Contributors

misi avatar mrailton avatar pdrappo avatar tuupola avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slim-api-skeleton's Issues

Question: How to deal with insert queries and table joins?

In let's say to Todo class, I need to add a property from another table via JOIN. This works well through the hydrator, transformer classes etc. However how do I deal with the CreateQuery and CreateHandler classes? It's required to pass the joined property which obviously doesn't exist in the table.

I was able to unset the property in the ZendRepo but this somehow doesn't feel elegant. Is there any way you recommend to approach this?

Uncaught TypeError: Argument 3 passed to Slim\\Handlers\\ApiError

When some exceptions are throwed by Slim the ApiError handler can't handle it because the passed parameters are wrong.

Uncaught TypeError: Argument 3 passed to Slim\Handlers\ApiError::__invoke() must be an instance of Slim\Handlers\Exception, instance of UnexpectedValueException given in /home/ieasrl/intranet/src/Slim/Handlers/ApiError.php:19

For example if i upload the project to the server, create a virtualHost and i forgot to give 777 cmod permission to log folder this could happend.

I can't understand what is really wrong or if ApiError must work different. So i have to comment handlers to see the error in apache log.

Other error when handler.php is not commented is:
[Thu Aug 10 10:16:44.159886 2017] [:error] [pid 14888] [client 10.0.2.247:51490] PHP Notice: Array to string conversion in /home/ieasrl/intranet/vendor/tuupola/dbal-psr3-logger/src/Psr3Logger.php on line 40

Not using the latest version of psr/http-server-middleware?

I'm getting the following error:


Fatal error: Declaration of Tuupola\Middleware\CorsMiddleware::process(Psr\Http\Message\ServerRequestInterface $request, Interop\Http\Server\RequestHandlerInterface $handler): Psr\Http\Message\ResponseInterface must be compatible with Psr\Http\Server\MiddlewareInterface::process(Psr\Http\Message\ServerRequestInterface $request, Psr\Http\Server\RequestHandlerInterface $handler): Psr\Http\Message\ResponseInterface in F:\xampp\htdocs\app\vendor\tuupola\cors-middleware\src\CorsMiddleware.php on line 33

Is it because starting January 22nd, 2018 http-interop is officially deprecated in favor of PSR-15?

Please respond. Require immediate assistance.

Token not found

I use the postman with auth basic authorization and user in headers test and password test with post method and in body of request like scope[] = todo.all and scope[] = todo.list, I received the answer statos => ok and the token. But in other request like /dump or /todos i received the answer "token not found".

Response NS

Hi Mika
I'm working with Slim3 and in your example I see an interesting model of design pattern to handle Response PSR-7 as a separated NS (ie /src/response/NotFoundResponse.php). In API apps a lot of controllers run same function with the same response (ie Item, Collection, bad validation, db errors etc.. - Don't Repeat Yourself) and I want to use a global class/trait to handle responses from controllers and I found something in this API skeleton. But I don't understand how to handle Response $response outsite controller. Is it the right way ?

Finally, in your Response NS, all __construct call parent with

$headers = (new Headers)->set("Content-type", "application/problem+json");

but the Http Headers is null; I try to separate it like this

$headers = new Headers();
$headers->set("Content-type", "application/problem+json");

and Http Headers are set correctly. It's a mistake ?
Thank you so much!

Syntax error, malformed JSON

I am getting

Syntax error, malformed JSON

my request:

curl "http://localhost:8888/api/public/todos" --request POST --include --insecure --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/json" --data '{ "title": "Test the API", "order": 10 }'
response:

HTTP/1.1 401 Unauthorized
Date: Fri, 23 Jun 2017 20:46:26 GMT
Server: Apache
X-Powered-By: PHP/7.1.1
Content-Length: 93
Content-Type: application/problem+json

{
    "title": "Syntax error, malformed JSON",
    "type": "about:blank",
    "status": 401

How to pass "--user test:test" in curl options in php

I know this is not a bug, but really seek your help. i am trying to call this api to generate token. so i wrote php function to perform the call. something like:

ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch); 

but i get authentication failed. this i think because the user/pass should be passed in the form of:
--user test:test.
can you please help

Missing information on readme file

I received error by function not found: gmp_strval, looking in the internet, for use this function is necessayr install php5-gmp extension and enable it. Please update the readme file, can help others users.

Dotenv Class not Found

Uncaught Error: Class 'Dotenv\Dotenv' not found in /var/www/html/slim-api-skeleton-master/app.php:21
Stack trace:

This is the Error When i try to call the localhost/todo API just for testing

Token not found

I have just cloned your skelton and test it in my laptop and that works fine. i uploaded the skeleton to my cloud with no code modifications but i am getting:

{
    "title": "Token not found",
    "type": "about:blank",
    "status": 401
} 

when i send post request to create todos. my request is:
curl "http://mydomain.com/tstapi/public/todos" --request POST --include --insecure --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/json" --data '{ "title": "Test the API", "order": 10 }'

can u please help?

PHP Strict standards error

Mika,

Got another PHP error:

PHP Strict standards: Declaration of Slim\Handlers\NotAllowed::__invoke() should be compatible with Slim\Handlers\Error::__invoke(Psr\Http\Message\ServerRequestInterface $request, Psr\Http\Message\ResponseInterface $response, Exception $exception) in [...]\slim-api-skeleton-master\src\Slim\Handlers\NotAllowed.php on line 10

With Slim 3.8.1 and PHP 5.6

Same context as test that generated a PHP Warning (#21) , but after applied the code patch (I've proposed).

curl request sent is

curl "http://localhost:7000/token" 
-H "Host: localhost:7000" 
-H "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0" 
-H "Accept: */*" 
-H "Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3" 
--compressed 
-H "Authorization: Basic dGVzdDp0ZXN0" 
-H "Connection: keep-alive"

through this plugin https://addons.mozilla.org/fr/firefox/addon/rest-easy/

Laurent

How to disable cache?

In my app I need to be able to enable/disable cache in order to check the results.
How can I disable?

[QUESTION] How to add MySQL ORDER BY

I'm looking at the zend-db documentation and they indicate that ORDER BY is achieved with something like:

$select = new Select;
$select->order('id DESC'); // produces 'id' DESC

Your ZendTodoRepository all function seems to always expect an array. Was your framework set up with ORDER BY in mind? How can we achieve this?

How set dynamic database host names

Current below is my settings.php

[ 'displayErrorDetails' => true, // set to false in production 'addContentLengthHeader' => false, // Allow the web server to send the content-length header // Renderer settings 'renderer' => [ 'template_path' => __DIR__ . '/../templates/', ], // Monolog settings 'logger' => [ 'name' => 'slim-app', 'path' => isset($_ENV['docker']) ? 'php://stdout' : __DIR__ . '/../logs/app.log', 'level' => \Monolog\Logger::DEBUG, ], "db" => [ "host" => "localhost", "dbname" => "***", "user" => "***1", "pass" => "***" ], ], ]; With this settings it works perfectly in the route when I called this e.g. $selectQueryResult1 = $this->db->prepare($selectQuery1) The issue now I will want to have many different database e.g. db1, db2; when I set new settings in the settings file I always get this error /var/www/html/apiv1/vendor/slim/slim/Slim/Container.php(172): Slim\Container->get('db1') How can I set and call those extra database settings?

New version not working after installation ?

Hi Tuupola,
I was trying out composer create-project --no-interaction --stability=dev tuupola/slim-api-skeleton app. Then when I tried to run I got this output

<?php

require __DIR__ . "/../app.php";

What else settings can I run to enable it properly? Secondly where should I put the route file now in this new version because in my older version I had everything in src folder both the middleware and routes file?

Probably a typo error

Mika,

In file slim-api-skeleton-master\routes\todos.php,

throw new PreconditionFailedException("Todo has been modified", 412);

As precondition failed, I suppose that the reason should be spelled "Todo has not been modified"

Laurent

Too few arguments to function Skeleton\\Domain\\Token:

If I run any of the examples for example:

curl "https://192.168.50.52/todos" \
    --request POST \
    --include \
    --insecure \
    --header "Authorization: Bearer INSERT-JWT-TOKEN-HERE" \
    --header "Content-Type: application/json" \
    --data '{ "title": "Test the API", "order": 10 }'

Then I get this response

{
  "title": "Too few arguments to function Skeleton\\Domain\\Token::__construct(), 0 passed in .../app/config/middleware.php on line 41 and exactly 1 expected",
  "type": "about:blank",
  "status": 500
}

I'm not sure what I'm doing wrong. I've tried everything including creating the database and adding tables and data for the todo's app.
Thanks

Insecure use of middleware over HTTP denied by configuration

I am sending post request like:
> curl "http://localhost:8888/api/public/token" --include --insecure --header "Content-Type: application/json" --data '["todo.create", "tod.read"]' --user test:test

but i am getting:

ate: Fri, 23 Jun 2017 20:02:50 GMT
Server: Apache
X-Powered-By: PHP/7.1.1
Content-Length: 126
Connection: close
Content-Type: application/problem+json

{
    "title": "Insecure use of middleware over HTTP denied by configuration.",
    "type": "about:blank",
    "status": 500

Missing vendor folder?

I'm getting this error
[20-Jan-2018 07:48:02 UTC] PHP Warning: require(/home/avytoqau/api4/vendor/autoload.php): failed to open stream: No such file or directory in /home/avytoqau/api4/app.php on line 20
[20-Jan-2018 07:48:02 UTC] PHP Warning: require(/home/avytoqau/api4/vendor/autoload.php): failed to open stream: No such file or directory in /home/avytoqau/api4/app.php on line 20
[20-Jan-2018 07:48:02 UTC] PHP Fatal error: require(): Failed opening required '/home/avytoqau/api4/vendor/autoload.php' (include_path='.:/opt/alt/php55/usr/share/pear:/opt/alt/php55/usr/share/php') in /home/avytoqau/api4/app.php on line 20

Missing vendor folder?

Cache

Hi @tuupola! Does it make sense to add psr6 handler (ie redis or memcache) to the psr7 already implemented? The ETAG don't reduce connection .. or I'm wrong? I lost my way ... I think I need to reduce db conns and I think I need to add cache handler into api? Otherwise I still use psr6 for single application with misaligned data! How can I continue in the right way?

Understanding the Dev environment

I have used Vagrant earlier for building Wordpress sites using VVV or VIP Quickstart. So, I understand the advantages of using vagrant.

But, in this Slim project I am facing some issues understanding my system:

  • How and where is my database created and hosted respectively? Like if I want to access local DB, how to do I do that. One addition to this setup will be to add phpMyAdmin to view database.
  • I am building a Microservices framework, where I want to clone multiple instances of this project to create various services. Now these services will talk to each other as well. Here comes the second need, it should be very easy to have different urls for different services. Vagrant Hostsupdater comes to my mind. Have you thought of integrating that?
  • It's great that you have already integrated other necessary dependencies required like logging, but if I want to debug using php error logs, where do I access those?

I will really appreciate if you can shed some light on the above.

P.S. your thoughts on building microservices architecture using this framework are welcome.

Read Query Handler returns null

Hi there,

Great work on the Skeleton API!

I'm new to Slim API and have been playing around and have duplicated the 'todos' table with an 'entries' table. The GET routing is working fine but I can't POST anything. I get the error 'Call to a member function getTimestamp() on null'.

Debugging this leads me to $entry ($todo in your case) returning null in the following block of code (note that all handlers have been added to the dependencies file:

$command = new CreateEntryCommand($data);
$this->commandBus->handle($command);

$query = new ReadEntryQuery($data);
$entry = $this->commandBus->handle($query); // $entry returns NULL

/* Add Last-Modified and ETag headers to response. */
$response = $this->cache->withEtag($response, $entry->etag());
$response = $this->cache->withLastModified($response, $entry->timestamp());

Here's how the objects look like:

$query:
object(Skeleton\Application\Entry\ReadEntryQuery)#316 (1) {
  ["uid":"Skeleton\Application\Entry\ReadEntryQuery":private]=>
  string(13) "1E3HbNm2aHG7A"
}

$entry:
object(Skeleton\Domain\Entry)#334 (6) {
  ["uid":"Skeleton\Domain\Entry":private]=>
  NULL
  ["order":"Skeleton\Domain\Entry":private]=>
  NULL
  ["completed":"Skeleton\Domain\Entry":private]=>
  bool(false)
  ["title":"Skeleton\Domain\Entry":private]=>
  NULL
  ["createdAt":"Skeleton\Domain\Entry":private]=>
  NULL
  ["updatedAt":"Skeleton\Domain\Entry":private]=>
  NULL
}

$data:
array(3) {
  ["title"]=>
  string(25) "Testtttttttttttty the API"
  ["order"]=>
  int(10)
  ["uid"]=>
  string(13) "1E3HbNm2aHG7A"
}

When I print the $todo object in the todo POST route, I'm successfully getting data instead of NULL.

Do you have any idea why this could be the case?

Cors information is not at the response header's when i throw an exception

Hi, i dont know if this is an issue or not. May be i'm doing something wrong, but for example, when i try to login and get a token if the credentials are wrong i throw an exception like NotFoundException and this is passed to \Slim\Handlers\Error\ApiError who handle the exception and gives response with a json object. The problem is that Cors information is not at the response header's when this path is taked in the code. How can i fix this. Thanks.

$credentials = $request->getParsedBody();
$mapper = $this->spot->mapper("App\Entities\Auth\User");

      // Selecciono el usuario
       $result = $mapper->where([
           'username' => $credentials['username'],
           'password' => md5($credentials['password'])
           ])->with('perms')->first();

       if(!$result){
         $data = array("status" => "error", "msg" => "");
         if($mapper->where(['username' => $credentials['username']])->first()){
                $alert = ["type" => "danger", "message" => "La contraseña es incorrecta"];
           }else{
                $alert = ["type" => "danger", "message" => "El usuario ingresado no existe."];
           }

throw new NotFoundException($alert['message'], 401);

vagrant time too long

hi,when I run vagrant The program stopped at "default: Waiting for machine to boot. This may take a few minutes..." .And this step has been going on for hours

vagrant

JWT support

can you add JWT support and URL like
URL/login
URL/register
URL/status //will get all the status only if he is authenticated or 403 error will be thrown

array_filter - a little warning

Hello Mika,

I've just tested your very nice skeleton.

First thanks to share it !

Second, I've found a little warning raised by PHP that could be catch easily.

When you don't give the scope on curl request you get

PHP Warning: array_filter() expects parameter 1 to be array, null given in [...]\slim-api-skeleton-master\routes\token.php on line 34

Easy FIX will be to add, just after routes\token.php, line 21 ( $requested_scopes = $request->getParsedBody();)

    if ($requested_scopes === null) {
        $requested_scopes = [];
    }

Laurent

Validating

Hi,

Reviewing your package for a possible project. What would you recommend in implementing ORM Model data validation for your package?

Fractal inside dependencies.php is not used

File ./config/dependencies.php import Fractal module, but it's not used.

use League\Fractal\Manager as FractalManager;
use League\Fractal\Resource\Item as FractalItem;
use League\Fractal\Serializer\DataArraySerializer;

It is used by TransformTodoService and TransformTodoCollectionService, in their own file.

Zend TableGateway can't execute 2 consecutive query

Hi Guys,

Firtsly, I'm sorry if I miss placed the question. After weeks learning the framework with this skeleton, I just desperate facing this issue.

It seems I can't run 2 consecutive query using TableGateway. It's always produce (not just UPDATE):

"Statement couldn't be produced with sql: UPDATE `users` SET `last_access` = NOW() WHERE `id` = ?"

Here's the code inside ZendUserRepository:

...
    public function footprint(int $id): void {
        $data = ['last_access' => new Predicate\Expression('NOW()')];
        $where = ['id' => $id];
        $this->table->update($data, $where);
    }
    
    public function authenticate(string $username, string $password): bool {
        $where = [
            'username' => $username,
            new Predicate\IsNotNull('roles')
        ];
        $rowset = $this->table->select($where);
        if (null === $row = $rowset->current()) {
            return false;
        }
        $data = (array) $row;
        if(password_verify($password, $data['password'])) {
            $this->footprint($data['id']);
            return true;
        }
        return false;
    }
...

Please, kindly help this newbie here.

Best Regards,
Adit

PostMan

Hi
Haw can i test this with PostMan.
I dont anderstand what do you meen by this:
"--data '["todo.all"]'
--user test:test"

Update to Slim 4?

Thank you for this awesome skeleton-project.

Have you planned to do an update to make it slim 4 compatible and with the (new) best practices ?

I would be highly interested by it.

error due to php version

I got the following error

Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' in //vendor/slim/slim/Slim/Container.php on line 149

i googled the error and it could be due to php version. the php version installed in my host is 5.4.

what modification i need to make my api compatible with v. 5.4?

HttpBasicAuthentication

An additional argument needs to be added to line 211 in /vendor/tuupola/slim-basic-auth/src/HttpBasicAuthentication.php

To reproduce the error, try to use the wrong username and password in the example curl:
$ curl "https://192.168.50.52/token"
--request POST
--include
--insecure
--header "Content-Type: application/json"
--data '["todo.all"]'
--user NOT_TEST:NOT_TEST

The response is:
"Too few arguments to function {closure}(), 2 passed in /opt/lampp/htdocs/payment/vendor/tuupola/slim-basic-auth/src/HttpBasicAuthentication.php on line 211 and exactly 3 expected"

I was able to "fix" this error by changing line 211 to:
$handler_response = $this->options["error"]('ADDITIONAL ARGUMENT', $response, $arguments);

Of course, based on line 144 the response should be:
"title": "Authentication failed", "type": "about:blank", "status": 401

Spot2 Relations?

First, I would like to say how much I am loving this! I have used this to spin up like 3 APIs now in the blink of an eye. The latest one I am using requires me to have relationships built into my entities and I was wondering if that was possible with this setup? I did it just like it is in the Spot docs....here is my entity class:

namespace App;
use Spot\EntityInterface;
use Spot\MapperInterface;
use Spot\EventEmitter;
use Tuupola\Base62;
use Ramsey\Uuid\Uuid;
use Psr\Log\LogLevel;

class Chat extends \Spot\Entity
{
protected static $table = "chats";
public static function fields()
{
return [
"chat_id" => ["type" => "integer", "unsigned" => true, "primary" => true, "autoincrement" => true],
"chat_event_id" => ["type" => "integer", "unsigned" => true],
"chat_expires_at" => ["type" => "string", "length" => 100],
"chat_created_at" => ["type" => "datetime", "value" => new \DateTime()],
"chat_updated_at" => ["type" => "datetime", "value" => new \DateTime()]
];
}
public static function events(EventEmitter $emitter)
{
$emitter->on("beforeUpdate", function (EntityInterface $entity, MapperInterface $mapper) {
$entity->chat_updated_at = new \DateTime();
});
}
public static function relations(MapperInterface $mapper, EntityInterface $entity)
{
return [
'messages' => $mapper->hasMany($entity, 'App\ChatMessage', 'chat_message_chat_id')->order(['chat_message_created_at' => 'ASC']),
];
}
public function timestamp()
{
return $this->chat_updated_at->getTimestamp();
}
}

and here is my Transformer class for Fractal:

namespace App;
use App\Chat;
use League\Fractal;
class ChatTransformer extends Fractal\TransformerAbstract
{
public function transform(Chat $chat)
{
return [
"chat_event_id" => (integer)$chat->chat_event_id ?: 0,
"chat_expires_at" => (string)$chat->chat_expires_at ?: null,
"chat_messages" => $chat->messages
];
}
}

Everything else is pretty much setup like you do in your examples. When I run this, I only get a blank for the 'chat_messages' return even though I know there should be something in there so I was just wondering if I was missing something.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.