Laravel 8
I have seen a few of these questions, but the answers are either msising, not for php, or some weird hack.
I have a table in the database, mariadb, with the field type of LONGTEXT - equates to JSON field.
in my model I do:
protected $casts = [
'event_data' => 'array',
];
public function setEventDataAttribute($value) {
$this->attributes['event_data'] = json_encode($value);
}
The data going into the field is:
array:12 [
"start" => "2022-08-23T00:00:00+00:00"
"end" => "2022-08-23T00:00:00+00:00"
"all_day" => false
"unassigned" => true
"draft" => true
"title" => "ggggg"
"notes" => "test"
"active" => true
"schedule_calendar_id" => null
"jobcode_id" => 122723308
"customfields" => array:2 [
1782352 => "Dirty"
1782354 => "Vacant"
]
"color" => "#888888"
]
When I run json_encode($value) where $value is the above array, I get:
{
"start": "2022-08-23T00:00:00+00:00",
"end": "2022-08-23T00:00:00+00:00",
"all_day": false,
"unassigned": true,
"draft": true,
"title": "ggggg",
"notes": "test",
"active": true,
"schedule_calendar_id": null,
"jobcode_id": 122723308,
"customfields": {
"1782352": "Dirty",
"1782354": "Vacant"
},
"color": "#888888"
}
which according to every validator out there, this is valid JSON. How ever attempting to set this as the attribute into the field throws:
Malformed UTF-8 characters, possibly incorrectly encoded
I can, above the $this->attributes['event_data'] do:
dump(json_encode($value), json_decode(json_encode($value)));
And get the json object listed above and get a stdClass class object of the decoded json.
So my question is:
If the online JSON formatters are saying this is valid JSON, php has no issue encoding and decoding it - why can't laravel insert it? Is it the dates? they must be in ISO8601 Format.
What is going on? I have done this, json encoding like this, a thousand times with no issue.
Related
I want to send request via post method with API, and when sending values, sometimes I need to send two values instead of one, and for this I need to loop it. The solution to this is, before sending the request, I save it to the array in the loop and try to complete the process by making json_encode.
My explanation may not be fully explanatory, so I will explain through the codes.
The request I want to throw is normally like this:
CURLOPT_POSTFIELDS =>'
[
{
"items":
[
{
"name":"string",
"sku":"string",
}
],
}
]'
But some times the items value needs to have two instead of one. For example:
CURLOPT_POSTFIELDS =>'
[
{
"items":
[
{
"name":"string",
"sku":"string",
},
{
"name":"string",
"sku":"string",
}
],
}
]'
So before i make this request i am saving these values to array in a foreach loop.
$data =array();
foreach ($request->orderItems as $orderItemId) {
$order_item = OrderItem::where('orderItemId',$orderItemId)->first();
$data[] = array(
"sku"=> $order_item->sku,
"name"=> $order_item->name,
)
}
And if I'm going to send more than one value, my final code looks like this.
CURLOPT_POSTFIELDS =>'
[
{
"items": '.json_encode($data).',
}
]'
Here is where the problem starts and when i try to send this request i get this error:
Array to string conversion
What should I do exactly? Where am I missing?
You might be missing the Content-Type header for your cURL call.
CURLOPT_HTTPHEADER => [
'Content-Type' => 'application/json',
],
Try to encode all the content in CURLOPT_POSTFIELDS like this way
$array = [
array(
"name" => "string",
"sku" => "string",
),
array(
"name" => "string",
"sku" => "string",
)
];
$final = json_encode([["items" => $array]]);
//now use this variable directly in CURLOPT_POSTFIELDS
CURLOPT_POSTFIELDS => $final
may it helps ....
I have a Wordpress website with the WPGraphQL plugin installed and running some tests with Codeception to test the GraphQL queries. For a bit more context, I am using Codeception's REST module and loading Wordpress in the tests with wp-browser.
The following test to register a user is failing:
class RegisterCest {
public function seeCanRegister( ApiTester $I ) {
$I->send( "POST", "https://example.com/graphql", [
"query" => '
mutation registerUser( $input: RegisterUserInput! ) {
registerUser( input: $input ) {
user {
username
email
addressMain
addressSec
adminArea
country
city
firstName
lastName
postalCode
}
}
}
',
"variables" => [
"input" => [
"clientMutationId" => "registerUser",
"firstName" => "John",
"lastName" => "Smith",
"username" => "user#example.com",
"email" => "user#example.com",
"password" => "example",
"addressMain" => "Fake Street",
"addressSec" => "Apt #1",
"adminArea" => "New York",
"country" => "US",
"city" => "New York",
"postalCode" => 00000,
"planSlug" => null,
"subscribeToNewsletter" => true
]
]
]);
$I->seeResponseCodeIs( 200 );
$I->dontSeeResponseJsonMatchesJsonPath( "$.errors" );
}
}
The test fails because I get the following error in the response:
Expected type Boolean at value.subscribeToNewsletter; Boolean cannot
represent a non boolean value: 1"
Basically, what seems to happen is that the boolean true set as the value for subscribeToNewsletter is transformed into the string "1" before the query is executed, which causes the query to be invalid because in the GraphQL schema it is specified that subscribeToNewsletter is expected to be a boolean.
I do not get this error when running the query in the app; it's only coming up in this test. Can anyone think of a reason why?
As suggested by Arvin Jason Cabrera in the comments, the problem was I was not setting the Content-Type to application/json. In my case, I simply had to add the following line
$I->haveHttpHeader('Content-Type', 'application/json');
before sending the request.
I'm very new in Elasticsearch, I'm implementing it inside my Laravel project with Elasticsearch Scout Driver but I've got an error while insert model object inside index.
The model is a Post, made like this:
>>> $post = App\Models\Post::first();
=> App\Models\Post {#853
id: 1,
title: "First Post",
description: "My first post",
created_at: "2017-09-13 13:31:51",
updated_at: "2018-02-16 16:23:44",
deleted_at: null,
}
Inside model class, I declare the mapping options, I report my mapping options:
// Map elements to be saved in Elasticsearch
protected $mapping = [
'properties' => [
'id' => [
'type' => 'integer',
'index' => false
],
'title' => [
'type' => 'text'
],
'description' => [
'type' => 'text'
],
'created_at' => [
'type' => 'date',
'ignore_malformed' => true,
'format' => "yyyy-MM-dd HH:mm:ss"
],
'updated_at' => [
'type' => 'date',
'ignore_malformed' => true,
'format' => "yyyy-MM-dd HH:mm:ss",
],
'deleted_at' => [
'type' => 'date',
'ignore_malformed' => true,
'format' => "yyyy-MM-dd HH:mm:ss",
]
]
];
Every time I call $post->searchable(); to put my model inside my Elasticsearch index, I've got this error:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Mapper for [deleted_at] conflicts with existing mapping in other types:\n[mapper [deleted_at] has different [format] values]"
}
],
"type": "illegal_argument_exception",
"reason": "Mapper for [deleted_at] conflicts with existing mapping in other types:\n[mapper [deleted_at] has different [format] values]"
},
"status": 400
}
I'm guessing that the problem is the null value of deleted_at property.
I need deleted_at == null because I manage soft deletion with Laravel: any another value will cause the soft deletion for Laravel framework (not retrieve element when query).
As you can see, I tried to put ignore_malformed => true but it doesn't work for me.
I tried to add another option null_value => NULL without success.
Where I am wrong?
How can I insert posts inside my Elasticsearch Index with deleted_at attribute set to null OR set to date with format yyyy-MM-dd HH:mm:ss?
Thanks
PS: I'm using Elasticsearch Version 6.1.2.
An index consists of multiple types (in version 6 this is no longer possible mainly due to this reason). The problem with different types is that they cannot store the same field name with a different mapping. This has to do with the way it is stored in Lucene.
Could it be you are inserting documents in two different types? Maybe by accident (Typo in the type while ingesting documents for instance). Then it might try to create a different field type by dynamic mapping say a string. This would cause the exception that you mention.
Below query worked fine in Studio 3T and Robomongo, But I want to convert it into PHP format,
Following is my query,
db.news.aggregate([
{
$match: { "_id" : "1" }
},
{
"$project": {
"comments": {
"$filter": {
"input": "$comments",
"as": "comment",
"cond": { "$eq": [ "$$comment.status", "active" ] }
}
}
}
}, {
"$project": {
"comments": {
"$slice": [
{
"$slice": [
"$comments",
{
"$subtract": [ { "$size": [ "$comments" ] }, 1 ]
}
]
}, -1
]
}
}
}])
I have tried below, But it giving error "Error: localhost:27017: FieldPath field names may not be empty strings."
PHP converted sample:
<?php
$commentsAggregate=array(
array('$match' => array("_id" => "1")),
array('$project' => array(
"comments" => array(
'$filter' => array(
"input" => "$comments",
"as" => "comment",
"cond" => array('$eq' => array( "$$comment.status", 'active'))
)))),
array('$project' => array(
"comments" => array(
'$slice' => array(array(
'$slice' => array("$comments",array('$subtract' => array( array( '$size' => array("$comments")),1)))
), -1)
)))
);
$cursor=$collectionNews->aggregate($commentsAggregate);
Please help me to convert above query.
The error message "FieldPath field names may not be empty strings" originates from the server. Looking at the example PHP code you've provided, I notice that you're inconsistently using single- and double-quoted strings. In particular, these two strings stand out:
"$$comment.status"
"$comment"
PHP is evaluating variable references inside double-quoted strings. Assuming the local scope does not actually have a $comment variable defined, those strings are going to resolve to "$.status" and "", respectively. As evidenced in this script and execution output on 3v4l.org, those examples should at least result in a PHP notice for an undefined variable (my local PHP configuration happens to report this at the "error" level). If you have no record of that error message, I would suggest the following:
Check your error_reporting configuration.
Ideally, you should report everything (E_ALL) in a development environment. Full reporting is also advisable for production, although there you would likely want to disable display_errors (for security) and instead ensure everything is logged properly.
If it turns out the error was logged, look into how it was missed while debugging this issue.
As for fixing the root cause, you should be mindful to use single-quoted strings when writing MongoDB queries/commands in PHP. There is a note about this in the MongoCollection::find() documentation, but it's not something we repeat on every page, as PHP's double-quoted string evaluation is outside the control of the driver.
When you receive a request, your fulfillment must return a response
I have a HTTPS endpoint which receives commands sent thru the google assistant(My Fulfilment URL). But i want to return a text to the user for every request made
Eg:
USER REQUEST : "Tell, 'app name' to do blah blah"
ASSISTANT RESPONSE : "Okay, sure"
As documented in this article --> https://developers.google.com/actions/components/fulfillment (RESPONSE FORMAT) , I have coded the json file according to the format said in the above link
But it says your fulfillment must return a response
RESPONSE.JSON
"finalResponse": {
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "sure thing",
"displayText": "Sure, thing!"
}
]
}
}
In my Fulfilment end point i did the above.
fulfilment.php
$file = [
"expectUserResponse" => false,
"finalResponse" => [
"richResponse" => [
"items" => [
[
"simpleResponse" => [
"textToSpeech" => "Sure thing!",
"displayText" => "Sure, thing?"
]
]
]
]
]
];
echo json_encode($file);
header('Content-Type: application/json');
How do i return this file in php back to google assistant?
I am using PHP :)
For starters - that isn't valid JSON. Valid JSON would look something like this:
{
"finalResponse": {
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "sure thing",
"displayText": "Sure, thing!"
}
}]
}
}
}
Notice the opening and closing brackets to designate that this is a JSON object. What you're sending is a string that has been encoded as a JSON string. Using PHP, the easiest way to create valid JSON is to use json_encode and pass it a nested associative array. So something like this would generate it.
<?php
header('Content-Type: application/json');
$a = [
"finalResponse" => [
"richResponse" => [
"items" => [
[
"simpleResponse" => [
"textToSpeech" => "Sure thing!",
"displayText" => "Sure, thing?"
]
]
]
]
]
];
echo json_encode($a);
Note that the header() must come before anything, even a blank line, has been sent.
However... that might not be your only problem.
This doesn't look like it has all the fields that you should reply. If you're only sending a finalResponse, then you probably also need to set expectUserResponse to false.
(And are you sure that you want to end the conversation every time?)