Beginner in API
I have table post_tag which is posts table has relation ( many to many ) with tags table.
my controller code ( every thing is good ):
$post = Post::create($data);
$post->tag()->attach($request->tags);
return $this->apiRespone($post , 'Added Post Successfuly', null ,200);
My question is here: now I send array of tags like that! Is that the best way or the correct way to send array ( means when I give this api url to mobile developer, he will know what to do with this api url ?
My way is correct or not ?
Although your solution works, a better approach since you are building an endpoint, it would be better to switch your input to accept JSON format rather than using form-data. Make your API endpoint to accept the following payload:
{
"title": "First Post",
"desc": "Desc of Post",
"image": "image3.jpg",
"category_id": 1,
"tags": [
"one",
"two",
"three"
]
}
In Laravel, you get just grab the tags (or any other properties) with the following:
$tags = $request->input('tags');
For the image, you can allow it to be received in base64 encoded image. The image will look like a bunch of string which should be converted by the client (ios or android) e.g:
{
image:"/9j/4AAQSkZJRgABAQAAAQABAAD/7QB8UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAF8cAigAWkZCTUQyMzAwMDk2OTAxMDAwMDgxNTIwMDAwNWY2MDAwMDA3NDZmMDAwMDE2YmEwMDAwNDAxYjAxMDBmMTM0MDEwMGY4YzIwMTAwZDkxNDAyMDA1ZDRhMDIwMAD/2wBDAAcHBwcHBwwHBwwRDAwMERcRERERFx4XFxcXFx4kHh4eHh4eJCQkJCQkJCQrKysrKysyMjIyMjg4O"
}
Then in PHP, if you want to save the image on disk, just use base64_decode. See example here.
Related
In order to limit the size of my REST API answers, I want to implement the Google performance tip: using the fields query string parameter to do partial resources.
If I have a full answer GET https://myapi.com/v1/users
[
{
"id": 12,
"first_name": "Angie",
"last_name": "Smith",
"address": {
"street": "1122 Something St.",
"city": "A city"
..and so on...
}
},
... and so on
]
I will be able to filter it GET https://myapi.com/v1/users?fields=first_name
[
{
"id": 12,
"first_name": "Angie"
},
... and so on
]
The concept is pretty easy to understand, but I can't find an easy way to implement it!
My API resources are all design the same way:
use query string parameters for filtering, sorting, paging.
call a service with that parameters to do a SQL request (only the WHERE condition, the ORDER BY condition and the LIMIT are dynamic)
use a converter to format data back to JSON
But when using this new fields parameter, what do I need to do? where do I filter the data?
Do I need to filter only the JSON output? But I will make (in that example) an unwanted JOIN query on address table and fetch unwanted fields in the users table.
Do I need to make a dynamic SQL query to fetch exactly the requested fields and add the JOIN only when the end user need it? Then the converter will have to be smart to convert only the available fields in the SQL query.
In my opinion, this second solution will produce a code extremely dynamic, extremely complex and difficult to maintain.
So, how do you implement such REST API with partial resource feature? What are you best practice in that case?
(I'm a PHP developer, but I don't think it's relevant for that question)
If your backend is doing
GET https://myapi.com/v1/users
which results in SQL:
select * from users
which you then turn into JSON, can you not just do:
GET https://myapi.com/v1/users?fields=first_name,surname,email
get all the required fields (rough idea of PHP implementation):
$fields = split(",", $_GET["fields"]);
$sql = "select ";
foreach ($fields as &$field) {
// do a check to see if the field is ok first...
if (checkField($field)) {
$sql += field + "," // deal with commas
}
}
$sql += " from users";
to build SQL like:
select firstname,surname,email from users
and turn that limited dataset to JSON?
I am trying to attach a contact to campaign response.
I am using rest API for that.
https://learn.microsoft.com/en-us/dynamics365/customer-engagement/web-api/campaignresponse?view=dynamics-ce-odata-9
Post Data :
{
"firstname": "TestFirst",
"lastname": "TestLast",
"emailaddress": "test#test.com",
"telephone": "1234567890",
"prioritycode": 0,
"responsecode": 1,
"subject": "Test Subject",
"statuscode": 1,
"regardingobjectid_campaign#odata.bind": "/campaigns(xxxx90c-11ef-e811-a966-000d3ad24a0d)",
"regardingobjectid_contact#odata.bind": "/contacts(xxxxfa2e-c3b5-e811-a962-000d3ad24a0d)"
}
Here is my JSON.
I am getting Error : “Campaign as RegardingObject must be supplied”. Without contact, it works fine.
I had the same problem and the documentation is not very clear about it, I had to check all the relationships of the CampaignResponse in order to understand how to solve this.
If you want to create a CampaignResponse linked to both a Campaign and a Contact you need to do the following:
Create a CampaignResponse with the "regardingobjectid_campaign#odata.bind" in the params sent.
POST "https://some_subdomain.crm6.dynamics.com/api/data/v9.0/campaignresponses"
{
"regardingobjectid_campaign#odata.bind": "/campaigns(CAMPAIGN_ID_HERE)",
"description": "some desc",
"subject": "some subject "
}
Then find the CampaignResponse you just created to get its activityid (every CampaignResponse is an Activity)
Finally, you need to create a new ActivityParty, that will link the Contact to the CampaignResponse.
POST "https://some_subdomain.crm6.dynamics.com/api/data/v9.0/campaignresponses(CAMPAIGN_ID_HERE)/activitypointer_activity_parties"
{
"partyid_contact#odata.bind": "/contacts(CONTACT_ID_HERE)",
"participationtypemask": 11 //this is the code for customers
}
The "Regarding" lookup field can only be set to a single "regarding" record. Even though it appears that there are different Regarding fields, one for each entity type, those are "helper" fields that let you easily set the main Regarding field by setting one of those regardingobjectid_xxx fields.
You must choose to use either a campaign or a contact as your Regarding field. You can of course create other lookups, so you could use the Regarding field for your campaign and then add an additional Contact lookup field, for example.
I'm trying to implement a HATEOAS Rest Client using Spring Boot.
Right now, I'm stuck in a point where I need to convert HATEOAS into an actual API URI.
If I post a new object of type Customer like:
{
"name": "Frank",
"address": "http://localhost:8080/address/23"
}
And then I retrieved with a request to http://localhost:8080/api/customer/1`, HATEOAS gives me something like
{
"name": Frank,
"_links": {
"address": {
"href": "http://localhost:8080/api/customer/1/address"
}
}
}
Is it possible to convert a link of the form of http://localhost:8080/api/customer/1/address to an API call like http://localhost:8080/api/address/23 ?
If you see what HATEOS returns after you say,
GET: http://localhost:8080/api/customer/1
is
{
"name": Frank,
"_links": {
"address": {
"href": "http://localhost:8080/api/customer/1/address"
}
}
}
According to Understanding HATEOS,
It's possible to build more complex relationships. With HATEOAS, the output makes it
easy to glean how to interact with the service without looking up a specification or
other external document
which means,
after you have received resource details with
http://localhost:8080/api/customer/1
what other operations are possible with the received resource those will be shown for easier/click thru access to your service/application,
here in this case HATEOS could find a link http://localhost:8080/api/customer/1/address that was accessible once you have customer/1 and from there if you want then without going anywhere else customer/1 's address could be found with /customer/1/address.
Similarly if you have /customer/1's occupation details then there would be another link below address link called http://localhost:8080/api/customer/1/occupation.
So if address is dependent on customer i.e. there can be no address without customer then your API endpoint has to be /api/customer/1/address and not directly /api/address/23.
However, after understanding these standards and logic behind HATEOS's such responses if you still want to go with your own links that may not align with HATEOS's logic you can use,
Link Object provided by LinkBuilder interface of HATEOS.
Example:
With object of type Customer like:
Customer c = new Customer( /*parameters*/ );
Link link= linkTo(AnyController.class).slash("address").slash(addressId);
customer.add(link);
//considering you want to add link `http://localhost:8080/api/address/23` and `23 is your addressID`.
Also you can create a list of Links and keep adding many such links to that list and then add that list to your object.
Hope this helps you !
Good day!
Just want to ask on how to create a JSONAPISerializer for an ajax call?
From what I understand on the docs. I must first create a model before I can make a JSONAPISerializer. But I need to call a custom endpoint that is not listed as my model.
My goal is to pushPayload all the sideloaded data coming from my endpoint. but the problem is :
{
"data":[
{
"type":"promotions-verify", <----- it's not an actual model
"attributes":{
"cart-items-discount-in-cents":21900
},
"relationships":{...}, <---- sideloaded data that I want to push on ember-data
}],
"included": [] <---- sideloaded data that I want to push on ember-data
}
Is there a reason you can't make a model for promotions-verify? That would be the cleanest way to implement loading in the side-loaded data, since Ember would handle much of the serialization/pushing to the store for you.
If that isn't possible and you make an ajax request, you may need to map the relationships and included payloads to match up with one another (Lodash _.map() could work well for this). Then you can manually push that data (pushPayload) to the Ember store, while ensuring that the items you're pushing also have models and serializers.
Also, I'm not sure if this was accidental, but your example payload doesn't conform to JSON API standards – the relationships object should be nested within data. This will affect how Ember serializes the data, as it's expecting:
{
"data": [{
"id": 1,
"type": "promotions-verify",
"attributes": {},
"relationships": {}
}],
"included": []
}
I am working on an application that has messages and I want to store all the messages. But my problem is the message has a from first name and last name which could change. So if for example my JSON was
{
"subject": "Hello!",
"message": "Hello there",
"from": {
"user_id": 1,
"firstname": "George",
"lastname": "Lastgeorge"
}
}
The user could potentially change their last name or even first name. Which would require basically looping over every record in elasticsearch and updating everyone with the user_id.
Is there a better way to go about doing this?
I feel you should use parent mapping.
Keep the user info as parent with userID as key.
/index/userinfo/userID
{
"name" : "George",
"last" : "Lastgeorge"
}
Next , you need to maintain each chat as a child document and map the parent to the userindo type.
This way , whenever you want to make some change to the user information , simply make the change in userInfo type.
With this feature intact , you can search your logs based on user information , or search users based on chat records.
Link - http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/parent-child.html