laravel_json_api 0.1.81
laravel_json_api: ^0.1.81 copied to clipboard
This package is a mini framework that allows us to consume the services of an JSON:API.
Laravel Json Api #
This package was created to consume an API based on the JSON:API spec made in Laravel with the help of the cloudcreativity/laravel-json-api package.
Features #
- Schemas
- Custom headers (Accept, Content-Type, Authorization, etc)
- JSON:API Formatter
- Http requests (GET, POST, PATCH, DELETE, PUT)
- Filter resources
- Get related resources
- Get relationships
- Exception handling
Installation #
Install in dart
dart pub add laravel_json_api
Install in flutter
flutter pub add laravel_json_api
Usage #
Connecting with our server #
import 'package:laravel_json_api/laravel_json_api.dart';
Adapter adapter = ApiController('www.host.com', '/api/v1');
(No need to add http or https protocol)
To use the adapter in our entire application we can wrap it in some state handler, we recommend using provider.
Headers #
By default these are the values of the following headers:
Header | Value |
---|---|
Accept | application/vnd.api+json |
Content-Type | application/vnd.api+json |
But they can be overwritten.
import 'package:laravel_json_api/laravel_json_api.dart';
ApiController controller = ApiController('www.host.com', '/api/v1');
print(controller.headers);
controller.addHeader('Authorization', 'Beaer token');
controller.addHeader('Accept', 'application/json');
controller.addHeader('Content-Type', 'application/json');
print(controller.headers);
Adapter adapter = api;
Create Schemas #
Schemas provide getters and setters that help us transform responses into objects with their own attributes, relationships, related objects and errors.
For this example we will use a simple blog:
import 'package:laravel_json_api/laravel_json_api.dart';
class Article extends Schema {
//Constructors
Article(ResourceObject resourceObject) : super(resourceObject);
Article.init(String type) : super.init(type);
//Attributes
String get title => getAttribute<String>('title');
set title(String value) => setAttribute<String>('title', value);
String get slug => getAttribute<String>('slug');
set slug(String value) => setAttribute<String>('slug', value);
String get content => getAttribute<String>('content');
set content(String value) => setAttribute<String>('content', value);
String get image => getAttribute<String>('image');
set image(String value) => setAttribute<String>('image', value);
//Relationships
String? get authorId => idFor('user');
set author(User model) => setHasOne('author', model);
Object? get relatedAuthor => includedDoc('users', 'user');
String? get categoryId => idFor('category');
set category(Category model) => setHasOne('category', model);
Object? get relatedCategory => includedDoc('categories', 'category');
}
class Category extends Schema {
//Constructors
Category(ResourceObject resourceObject) : super(resourceObject);
Category.init(String type) : super.init(type);
//Attributes
String get name => getAttribute<String>('name');
set name(String value) => setAttribute<String>('name', value);
String get slug => getAttribute<String>('slug');
set slug(String value) => setAttribute<String>('slug', value);
String get image => getAttribute<String>('image_cover');
set image(String value) => setAttribute<String>('image_cover', value);
//Relationships
Iterable<String> get articlesId => idsFor('articles');
Iterable<Object> get articles => includedDocs('articles');
}
class User extends Schema {
//Constructors
User(ResourceObject resourceObject) : super(resourceObject);
User.init(String type) : super.init(type);
//Attributes
String get firstName => getAttribute<String>('first_name');
set firstName(String value) => setAttribute<String>('first_name', value);
String get email => getAttribute<String>('email');
set email(String value) => setAttribute<String>('email', value);
//Relationships
Iterable<String> get articlesId => idsFor('articles');
Iterable<Object> get articles => includedDocs('articles');
}
All schema methods #
String? idFor(String relationshipName)
String? typeFor(String relationshipName)
Map<String, dynamic> dataForHasOne(String relationshipName)
Iterable<dynamic>? dataForHasMany(String relationshipName)
Iterable<String> idsFor(String relationshipName)
Iterable<ResourceObject> includedDocs(String type,[Iterable<String>? ids])
ResourceObject? includedDoc(String type, String relationshipName)
void clearErrorsFor(String attributeName)
bool get hasErrors
bool attributeHasErrors(String attributeName)
Iterable<String> errorsFor(String attributeName)
void clearErrors()
void addErrorFor(String attributeName, String errorMessage)
void setHasOne(String relationshipName, LaravelJsonApiModel model)
Getting data #
All of these actions are asynchronous and return a specific value.
Find One #
Future<Article> getOneArticle(String id) async {
Article article =
Article(await adapter.find('articles', id) as ResourceObject);
return article;
}
GET | https://www.host.com/api/v1/articles/1
Optionally we can send the forceReload
parameter to cache this resource,
and the queryParam
to sort or include relationships.
Future<Article> getOneArticle(String id) async {
Article article = Article(await adapter.find('articles', id,
forceReload: true,
queryParams: {'include': 'category,user'}) as ResourceObject);
return article;
}
GET | https://www.host.com/api/v1/articles/1?include=category,user
Find All
Future<Iterable<Article>> getAllArticles() async {
Iterable<Article> articles = (await adapter.findAll('articles'))
.map<Article>((article) => Article(article as ResourceObject))
.toList();
return articles;
}
GET | https://www.host.com/api/v1/articles
More getting requests #
Future<Iterable<Object>> findManyById(String endpoint, Iterable<String> ids, {Map<String, String> queryParams})
Future<Iterable<Object>> getRelated(String endpoint, String id, String relationshipName)
Future<Iterable<Object>> filter(String endpoint, String filterField, Iterable<String> values, {Map<String, String> queryParams})
Writing data #
Article article = Article.init('articles');
article.title = 'Title';
article.content = 'Content';
article.user = user;
article.category = category;
Create resource
Future saveArticle(Article article) async {
await adapter.save('articles', article.jsonApiDoc);
}
Update resource
Article article = Article(await adapter.find('articles', '1') as ResourceObject);
article.title = 'Title Update';
await adapter.save('articles', article.jsonApiDoc);
Replace relationship
Article article = Article(await adapter.find('articles', '1') as ResourceObject);
Category newCategory = Category(await adapter.find('categories', '2') as ResourceObject);
await adapter.replaceRelationship('articles', 'category', article, newCategory);
Delete resource
Article article = Article(await adapter.find('articles', '1') as ResourceObject);
await adapter.delete('articles', article);