Changes to Input::json() function between Laravel 4 beta3 and beta4 - laravel

When I was developing in Laravel4 Beta3, I used to get JSON POST data from a service using Input::json() function, But when I updated to Laravel4 Beta4, I am getting following error:
Notice: Undefined property: Symfony\Component\HttpFoundation\ParameterBag::$productName in /Applications/MAMP/htdocs/commonDBAPI/app/controllers/UserController.php line 47
Does any one have any idea, what could be the reason.
Thanks,

You can access just the JSON using Input::json()->all().
JSON input is also merged into Input::all() (and Input::get('key', 'default')) so you can use the same interface to get Query string data, Form data and a JSON payload.
The documentation does not yet reflect all changes because Laravel 4 is still in beta and the focus is on getting the code right, the documentation will be updated ready for the public release.
How is JSON merged with Input::all()?
Consider the following JSON:
{
'name': 'Phill Sparks',
'location': 'England',
'skills': [
'PHP',
'MySQL',
'Laravel'
],
'jobs': [
{
'org': 'Laravel',
'role': 'Quality Team',
'since': 2012
}
]
}
When merged into Laravel's input the JSON is decoded, and the top-level keys become top-level keys in the input. For example:
Input::get('name'); // string
Input::get('skills'); // array
Input::get('jobs.0'); // object
Input::all(); // Full structure of JSON, plus other input

Yup they changed it to return a ParameterBag object switch your code to Input::json()->all()

For :
{
"name":"Olivier",
"title":"Just a try"
}
Try this :
$input = Input::json()->all();
return $input['name'];

Related

Formats to use on a response with fast-json-stringify

What I want to do is add validation to the schema response from a fastify route.
Following the documentation from Fastify here we can see this
Ajv for the validation of a request
fast-json-stringify for the serialization of a response's body
Related to improve and add validations for a response, what I want to do is check the schema when I send a response.
fast-json-stringify support different options, included format, but if you read the documentation, they said that they support JSON schema. Jsonschema has support for email format, that you can see here as a built-in format but when I try to use it on Fastify, like this:
{
response: {
200: {
type: 'object',
required: ['email'],
properties: {
email: {
type: 'string',
format: 'email',
}
}
}
}
}
And try to return ad response this
reply.code(200).send({ email: 'test' })
The only validation that I can do is when I set the type to integer and try to return a string.
Did you know if it's possible to use ajv-formats with fast-json-stringify to add validation to the response schema and use the formats from ajv and add new ones?
Many thanks in advance!
fast-json-stringify does the serialization, not the validation.
The json schema provided to it will be used to serialize only the properties declared and some type checking like integer or arrays.
the enum keyword is not supported
the format keyword is supported only for the dates as documented:
To reach your goal, you should use this plugin: fastify-response-validation that will add a validation step of your response body before the serialization process.

Get complete GraphQL response using POST without specify field name in request [duplicate]

Assume you have a GraphQL type and it includes many fields.
How to query all the fields without writing down a long query that includes the names of all the fields?
For example, If I have these fields :
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the user'
],
'username' => [
'type' => Type::string(),
'description' => 'The email of user'
],
'count' => [
'type' => Type::int(),
'description' => 'login count for the user'
]
];
}
To query all the fields usually the query is something like this:
FetchUsers{users(id:"2"){id,username,count}}
But I want a way to have the same results without writing all the fields, something like this:
FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}
Is there a way to do this in GraphQL ??
I'm using Folkloreatelier/laravel-graphql library.
Unfortunately what you'd like to do is not possible. GraphQL requires you to be explicit about specifying which fields you would like returned from your query.
Yes, you can do this using introspection. Make a GraphQL query like (for type UserType)
{
__type(name:"UserType") {
fields {
name
description
}
}
}
and you'll get a response like (actual field names will depend on your actual schema/type definition)
{
"data": {
"__type": {
"fields": [
{
"name": "id",
"description": ""
},
{
"name": "username",
"description": "Required. 150 characters or fewer. Letters, digits, and #/./+/-/_ only."
},
{
"name": "firstName",
"description": ""
},
{
"name": "lastName",
"description": ""
},
{
"name": "email",
"description": ""
},
( etc. etc. ...)
]
}
}
}
You can then read this list of fields in your client and dynamically build a second GraphQL query to get the values of these fields.
This relies on you knowing the name of the type that you want to get the fields for -- if you don't know the type, you could get all the types and fields together using introspection like
{
__schema {
types {
name
fields {
name
description
}
}
}
}
NOTE: This is the over-the-wire GraphQL data -- you're on your own to figure out how to read and write with your actual client. Your GraphQL javascript library may already employ introspection in some capacity. For example, the apollo codegen command uses introspection to generate types.
2022 Update
Since this answer was originally written, it is now a recommended security practice to TURN OFF introspection in production. Reference: Why you should disable GraphQL introspection in production.
For an environment where introspection is off in production, you could use it in development as a way to assist in creating a static query that was used in production; you wouldn't actually be able to create a query dynamically in production.
I guess the only way to do this is by utilizing reusable fragments:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
I faced this same issue when I needed to load location data that I had serialized into the database from the google places API. Generally I would want the whole thing so it works with maps but I didn't want to have to specify all of the fields every time.
I was working in Ruby so I can't give you the PHP implementation but the principle should be the same.
I defined a custom scalar type called JSON which just returns a literal JSON object.
The ruby implementation was like so (using graphql-ruby)
module Graph
module Types
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { x }
coerce_result -> (x) { x }
end
end
end
Then I used it for our objects like so
field :location, Types::JsonType
I would use this very sparingly though, using it only where you know you always need the whole JSON object (as I did in my case). Otherwise it is defeating the object of GraphQL more generally speaking.
GraphQL query format was designed in order to allow:
Both query and result shape be exactly the same.
The server knows exactly the requested fields, thus the client downloads only essential data.
However, according to GraphQL documentation, you may create fragments in order to make selection sets more reusable:
# Only most used selection properties
fragment UserDetails on User {
id,
username
}
Then you could query all user details by:
FetchUsers {
users() {
...UserDetails
}
}
You can also add additional fields alongside your fragment:
FetchUserById($id: ID!) {
users(id: $id) {
...UserDetails
count
}
}
Package graphql-type-json supports custom-scalars type JSON.
Use it can show all the field of your json objects.
Here is the link of the example in ApolloGraphql Server.
https://www.apollographql.com/docs/apollo-server/schema/scalars-enums/#custom-scalars

Do a full query simply in GraphQL [duplicate]

Assume you have a GraphQL type and it includes many fields.
How to query all the fields without writing down a long query that includes the names of all the fields?
For example, If I have these fields :
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the user'
],
'username' => [
'type' => Type::string(),
'description' => 'The email of user'
],
'count' => [
'type' => Type::int(),
'description' => 'login count for the user'
]
];
}
To query all the fields usually the query is something like this:
FetchUsers{users(id:"2"){id,username,count}}
But I want a way to have the same results without writing all the fields, something like this:
FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}
Is there a way to do this in GraphQL ??
I'm using Folkloreatelier/laravel-graphql library.
Unfortunately what you'd like to do is not possible. GraphQL requires you to be explicit about specifying which fields you would like returned from your query.
Yes, you can do this using introspection. Make a GraphQL query like (for type UserType)
{
__type(name:"UserType") {
fields {
name
description
}
}
}
and you'll get a response like (actual field names will depend on your actual schema/type definition)
{
"data": {
"__type": {
"fields": [
{
"name": "id",
"description": ""
},
{
"name": "username",
"description": "Required. 150 characters or fewer. Letters, digits, and #/./+/-/_ only."
},
{
"name": "firstName",
"description": ""
},
{
"name": "lastName",
"description": ""
},
{
"name": "email",
"description": ""
},
( etc. etc. ...)
]
}
}
}
You can then read this list of fields in your client and dynamically build a second GraphQL query to get the values of these fields.
This relies on you knowing the name of the type that you want to get the fields for -- if you don't know the type, you could get all the types and fields together using introspection like
{
__schema {
types {
name
fields {
name
description
}
}
}
}
NOTE: This is the over-the-wire GraphQL data -- you're on your own to figure out how to read and write with your actual client. Your GraphQL javascript library may already employ introspection in some capacity. For example, the apollo codegen command uses introspection to generate types.
2022 Update
Since this answer was originally written, it is now a recommended security practice to TURN OFF introspection in production. Reference: Why you should disable GraphQL introspection in production.
For an environment where introspection is off in production, you could use it in development as a way to assist in creating a static query that was used in production; you wouldn't actually be able to create a query dynamically in production.
I guess the only way to do this is by utilizing reusable fragments:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
I faced this same issue when I needed to load location data that I had serialized into the database from the google places API. Generally I would want the whole thing so it works with maps but I didn't want to have to specify all of the fields every time.
I was working in Ruby so I can't give you the PHP implementation but the principle should be the same.
I defined a custom scalar type called JSON which just returns a literal JSON object.
The ruby implementation was like so (using graphql-ruby)
module Graph
module Types
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { x }
coerce_result -> (x) { x }
end
end
end
Then I used it for our objects like so
field :location, Types::JsonType
I would use this very sparingly though, using it only where you know you always need the whole JSON object (as I did in my case). Otherwise it is defeating the object of GraphQL more generally speaking.
GraphQL query format was designed in order to allow:
Both query and result shape be exactly the same.
The server knows exactly the requested fields, thus the client downloads only essential data.
However, according to GraphQL documentation, you may create fragments in order to make selection sets more reusable:
# Only most used selection properties
fragment UserDetails on User {
id,
username
}
Then you could query all user details by:
FetchUsers {
users() {
...UserDetails
}
}
You can also add additional fields alongside your fragment:
FetchUserById($id: ID!) {
users(id: $id) {
...UserDetails
count
}
}
Package graphql-type-json supports custom-scalars type JSON.
Use it can show all the field of your json objects.
Here is the link of the example in ApolloGraphql Server.
https://www.apollographql.com/docs/apollo-server/schema/scalars-enums/#custom-scalars

Using map on returned graphql query is making known members undefined

I'm using Gatsbyjs to build a blog and I can't use the onCreatePage API to pass data from my graphql query into page templates.
My query grabs data from Kentico Cloud and it looks like this.
{
allKenticoCloudTypeBlogPost{
edges{
node{
contentItems{
elements{
url_slug{
value
}
}
}
}
}
}
}
This is a valid query and it returns data that looks like this.
The problem comes in my gatsby-node.js file where I want to utilize this query to build out pages using my predefined template.
Specifically in the createPage method which looks like this.
result.data.allKenticoCloudTypeBlogPost.edges.map(({node}) => {
createPage({
path: `${node.contentItems.elements.url_slug.value}`,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
slug: node.contentItems.elements.url_slug.value,
}
})
});
The error that displays is the following.
TypeError: Cannot read property 'url_slug' of undefined
gatsby-node.js:31 result.data.allKenticoCloudTypeBlogPost.edges.map
C:/Users/xxxx/Desktop/Marketing Repos/xxxx/gatsby-node.js:31:57
I decided to investigate doing a console.table on node.contentItems, as it appears as though the elements part is where it gets tripped up.
The result of console.table(node.contentItems) just before the createPage method is this.
It appears that node.contentItems has a member called url_slug rather than the elements member that I expected.
I thought I could then solve my problem by updating my createPage method call like so.
result.data.allKenticoCloudTypeBlogPost.edges.map(({node}) => {
console.table(node.contentItems);
createPage({
path: `${node.contentItems.url_slug.value}`,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
slug: node.contentItems.url_slug.value,
}
})
});
But then I get an error saying
TypeError: Cannot read property 'value' of undefined.
I truly don't understand how I can do a table log and see the url_slug member, but then when I try to access it, it says that it's undefined. All while I know that my query is correct because I can run it in graphiQL and get back the exact data I expect.
Any help would be appreciated. Thank you.
In your query result, node.contentItems is an array, even though you're trying to access it as if it's an object:
path: `${node.contentItems.elements.url_slug.value}`,
^^^^^^^^
console.log(contentItems) // [ { elements: {...} }, { elements: {...} }, ... ]
I think your confusion probably stems from the way console.table display data. It's confusing if you don't already know the shape of your data. Your screenshot says, this object has 4 properties with index 0 -> 3 (so likely an array), each has one property called elements (listed on table header), which is an object with the only property url_slug.
I'm not familiar with KenticoCloud, but maybe your posts are nested in contentItems, in which case you should loop over it:
result.data.allKenticoCloudTypeBlogPost.edges.map(({node}) => {
node.contentItems.forEach(({ elements }) => {
createPage({
path: elements.url_slug.value,
context: { slug: elements.url_slug.value },
component: ...
})
})
});
Is there a reason you are wrapping node with curly brackets in your map argument?
You might have already tried this, but my first intuition would be to do this instead:
result.data.allKenticoCloudTypeBlogPost.edges.map(node => {
console.log(node.contentItems)
createPage({
path: `${node.contentItems.elements.url_slug.value}`,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
slug: node.contentItems.elements.url_slug.value,
}
})
});

Why is an Array in my payload being flattened in Sinatra / Rack::Test?

I'm trying to test a small Sinatra app using rspec. I want to pass a rather complex payload and am running into issues i do not understand: my payload contains an array of hashes. When I run the actual application this will work as expected, yet when I use the post helper to run my tests, the array will contain a merged hash:
post(
"/#{bot}/webhook",
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
)
In the sinatra handler I use params to access this payload:
post '/:bot/webhook' do |bot|
do_something_with(params)
end
When I now look at the structure of params when running the test suite, I will see the following structure:
[{"some" => "fixture", "name" => "generic", "parameters" => {"facebook_sender_id" => "zuck-so-cool"}}]
which I do not really understand. Is this a syntax issue (me being a ruby noob), am I using params wrong, or is this a bug?
EDIT: So i found out this is an "issue" with the way that Rack::Test will serialize the given payload when not specifying how to (i.e. as form data). If I pass JSON and pass the correct headers it will do what I expect it to do:
post(
"/#{bot}/webhook",
{
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
}.to_json,
{ 'HTTP_ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
)
Still I am unsure of this is an issue with the passed data structure not being possible to be serialized into form data or if this is a bug in the way that Rack::Test serializes data.
Looking at the relevant portion of the specs it looks like this is is expected behavior.

Resources