This is Part II of “Building a Resource Manager in React and GraphQL”.   Read Part I, Building a Resource Manager in React and GraphQL.

Now that we have some behavior from the GraphQL server, we can start building out the rest of the data models.  As described in Part I, we need to add Eloquent models for resources, assignments and allocations.

Table definitions

Note: I don’t typically use Laravel Migrations for creating the database tables, preferring to enter the table definitions in phpMyAdmin or Sequel Pro.  Here are my MySQL table definitions:

CREATE TABLE `allocations` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `project_id` int(11) unsigned NOT NULL,
  `resource_id` int(11) NOT NULL,
  `startdate` date NOT NULL,
  `note` varchar(255) DEFAULT NULL,
  `hours` int(11) DEFAULT NULL,
  `updated_at` date DEFAULT NULL,
  `created_at` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4

CREATE TABLE `assignments` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `project_id` int(11) unsigned NOT NULL,
  `resource_id` int(11) unsigned NOT NULL,
  `updated_at` date DEFAULT NULL,
  `created_at` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4

CREATE TABLE `projects` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `technology` varchar(255) DEFAULT NULL,
  `updated_at` date DEFAULT NULL,
  `created_at` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4

CREATE TABLE `resources` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  `title` varchar(255) NOT NULL DEFAULT '',
  `active` tinyint(1) DEFAULT NULL,
  `updated_at` date DEFAULT NULL,
  `created_at` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4

Relations

Recognizing that we need to capture the relationships between these models, let’s add these relationship methods to the Project model:

    public function resources() {
        return $this->belongsToMany('App\Resource', 'assignments');
    }

    public function allocations() {
        return $this->hasMany('App\Allocation' );
    }

Now, from a Project, we can find the assigned resources through the belongsToMany relation, and find the allocations.

Similarly on the Resource, we like to add

public function projects() {
    return $this->belongsToMany('App\Project', 'assignments);
}

public function allocations() {
    return $this->hasMany('App\Allocation');
}

to be able to find the related projects and allocations.

Now we must capture these relationships in the GraphQL server code.  We’ll need to update the \GraphQL\Type\ProjectType.php class to represent and resolve the new relationships:

<?PHP 

namespace App\GraphQL\Type;

use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as GraphQLType;
use GraphQL;

class ProjectType extends GraphQLType
{
    protected $attributes = [
        'name' => 'Name',
        'active' => 'Active',
	    'technology' => 'Technology'
    ];

    /*
    * Uncomment following line to make the type input object.
    * http://graphql.org/learn/schema/#input-types
    */
    // protected $inputObject = true;

    public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The id of the project',
            ],
            'name' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The name of the project',
            ],
            'active' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'Flag indicating whether the project is active',
            ],
            'technology' => [
                'type' => Type::string(),
                'description' => 'The technology the project is built in',
            ],
            
            'resources' => [
                'args' => [
                    'id' => [
                        'type'        => Type::string(),
                        'description' => 'id of the project',
                    ],
                ],
                'type' => Type::listOf(GraphQL::type('Resource')),
                'description' => 'List of resources for the project',
            ],
            'allocations' => [
                'args' => [
                    'id' => [
                        'type'        => Type::string(),
                        'description' => 'id of the project',
                    ],
                ],
                'type' => Type::listOf(GraphQL::type('Allocation')),
                'description' => 'List of allocations for the project',
            ]            
        ];
    }


    public function resolveResourcesField($root, $args)
    {
        if (isset($args['id'])) {
            return  $root->resources->where("id", $args["id"]);
        }
        return $root->resources;
    }
    public function resolveAllocationsField($root, $args)
    {
        if (isset($args['id'])) {
            return  $root->allocations->where("id", $args["id"]);
        }
        return $root->allocations;
    }

}

Note that in the fields method, I’ve added a key for ‘resources’ and ‘description’ and defined them as Type::listOf() the appropriate type.  Also, there are two new resolvers, resolveResourcesField and resolveAllocationsField, which will fetch one or all of the related models, depending on whether an id parameter is supplied in the GraphQL query.

Testing

Let’s try this out:

Now we can fetch data from the Eloquent relationships.  In Part III, we’ll look at how we can update data in our Laravel GraphQL server using Mutations.