Symfony/Doctrine - Denormalize UPDATE with relations - symfony

I am using the Symfony serializer to denormalize JSON data and create an entity with relations.
For example:
$data = [
'first' => 'John',
'last' => 'Smith',
'addresses' => [
[
'street' => 'Street',
'city' => 'City',
'state' => 'State'
]
]
];
$person = $this->serializer->denormalize($data, Person::class);
This works GREAT. However, when I need to update person, I am sending the same data, with the object_to_populate flag set:
$data = [
'first' => 'John',
'last' => 'Smith',
'addresses' => [
[
'street' => 'Street',
'city' => 'City',
'state' => 'State'
]
]
];
$entity = $this->serializer->denormalize($data, Person::class, ['object_to_populate' => $person]);
This causes a duplicate key error (I have a unique key set for street+city+state). How can I have Doctrine UPDATE the relations as well, instead of trying to insert new relations?

There exists a bundle to make your life easier. It is called JMSSerializerBundle. It handle Doctrine relations out of the box.

Related

Symfony ChoiceType with array containing unique keys and duplicate values

It's not uncommon to have an array:
$array['hh2643ggwy'] = 'John';
$array['baddeyud'] = 'Jane';
$array['cceuv6vv'] = 'John';
Symfony ChoiceType (as a select), for reasons I'll never understand, uses the values as the select option keys!!!!
So with the array above, only one 'John' will be in the select.
Does anyone know of a solution to populate the select per the given array structure?
Two days later...
I live in central US and wanted to go to New York. So I went the California route:
$builder
->add('user_id', ChoiceType::class, [
'label' => 'Select user',
'required' => true,
'choice_label' => function ($choice, $key, $value) use ($array) {
return $array[$choice];
},
'choice_value' => function ($choice) {
return $choice;
},
'choices' => array_keys($array),
'mapped' => false,
]);
There's got to be a better solution...

WpGraphQL: Creating Extensions - Having Issues

Maybe I'm in over my head but I'm trying to create an extension for WpGraphQL to just gather the YITH WooCommerce Product Add-Ons info for each product but I've gotten to the point of banging my head against the desk in frustration. Is there a fairly easy way to just output the array into nodes? The following is what I have so far, currently I'm only getting one product with a set ID (later, hopefully it will get the one associated with that query). I can get a simple string output but I can't get it to output the array into nodes? What am I doing wrong? I commented out ideas I had for an output but it just usually results in an error or null. I do see the graphql_debug working and outputting $fields as an array though? Thanks!
register_graphql_object_type('MyNewType', [
'description' => __('Describe the Type and what it represents', 'replace-me'),
'fields' => [
'nodes' => [
'type' => 'String',
'description' => __('Describe what this field should be used for', 'replace-me'),
'fields' => [
'form_type' => [
'type' => 'String',
'description' => __('Describe what this field should be used for', 'replace-me'),
],
],
],
],
]);
register_graphql_field(
'Product',
'YITH_fields',
[
'type' => 'MyNewType',
'description' => __('Example field added to the Post Type', 'replace-with-your-textdomain'),
'resolve' => function (\WPGraphQL\Model\Post $post) {
global $wpdb;
$sql = "SELECT wp_live_yith_wapo_types.type, wp_live_yith_wapo_types.options FROM wp_live_yith_wapo_groups JOIN wp_live_yith_wapo_types on wp_live_yith_wapo_groups.id = wp_live_yith_wapo_types.group_id WHERE FIND_IN_SET(13, products_id)";
$results = $wpdb->get_results($sql);
if ($results) {
$array = array('nodes');
//$array = array();
foreach ($results as $result) {
$type = array('form_type' => $result->type);
$options = maybe_unserialize($result->options);
$result = array_merge($type, $options);
$array[] = $result;
}
//$array = wp_json_encode($array);
$fields = !empty($array) ? $array : null;
} else {
$fields = null;
}
graphql_debug($fields, ['type' => 'ARGS_BREAKPOINT']);
//return $fields['nodes'];
return $fields;
}
]
);
Probably it's good enough to return an array of Info 'records' (without embedding into nodes subfield - it would require some, own 'InfoList' type def.), then you need a type for single Info, like:
register_graphql_object_type('MyInfoItem', [
'description' => __('Describe the Type and what it represents', 'replace-me'),
'fields' => [
'form_type' => [
'type' => 'String',
'description' => __('Describe what this field should be used for', 'replace-me'),
],
// options field - list of some scalar or custom type
'options' => [
'type' => [ 'list_of' => 'String' ],
'description' => __('Describe what this field should be used for', 'replace-me'),
],
],
]);
extend Product with:
register_graphql_field(
'Product',
'YITH_fields',
[
'type' => [ 'list_of' => 'MyInfoItem' ],
'description' => __('Example field added to the Post Type', 'replace-with-your-textdomain'),
'resolve' => function (\WPGraphQL\Model\Post $post) {
// ...
return [
['form_type' => 'some_value'],
[
'form_type' => 'other_value',
'options' => ['opt_1', 'opt_2'],
],
];
Any, not trivial data 'nesting level' requires a separate type definition.
For more complex options 'records' you need to register another type - e.g. ids required for optional option selection.
If you don't want to explicitely express these [unknown/dynamic] structures, you can use custom JSON scalar type.

Symfony forms; Insert new relation instead of update; collection

So I have following:
$builder
->add('name')
->add('address', AddressType::class, [
'property_path' => 'address'
])
// TODO: Refactor to create new entities that are without ID
->add('person', CollectionType::class, [
'entry_type' => PersonType::class,
'allow_add' => true,
'property_path' => 'persons'
])
;
I run my functional test as follows with given parameters and everything works as expected. The entity is getting populated with new address relation & 2 new persons inside:
'entity' => [
'name' => 'Test',
'person' => [
[
'firstname' => 'one', 'lastname' => 'two'
], [
'firstname' => 'three', 'lastname' => 'four'
]
],
'address' => [
'street' => 'test str.',
]
]
Now if I run update on the same formtype with following params:
'entity' => [
'id' => 1,
'name' => 'Test upd',
'person' => [
[
'id' => 1, 'lastname' => 'update'
], [
'firstname' => 'new', 'lastname' => 'person'
]
]
]
What it does is: it correctly updates person with id 1. The problem is with the second one with firstname 'new' - instead of creating a new person and updating relationship it just looks for the remaining relation in 'entity' and updates the person with id 2.
Please help me find a way to properly configure this.
UPDATE: I can see the point in what's happening, most probably It is because the inverse side of relation of "entity" is not defined in PersonType. What would be the proper way to set up this relation field in PersonType, so it won't be recursive?

Woocommerce REST API how send custom meta?

Woocommerce not send meta with custom plug-ins in format .json.
What should I add to the file functions.php?
How to forcibly compel him to send some meta?
Sorry for such a simple question, but I have not found a solution for spaces google
Send the following payload to the API:
$data = [
'name' => 'Product Name',
'type' => 'simple',
'regular_price' => '19.95',
'description' => 'Simple Product,
'categories' => [
['id' => 1]
],
'virtual' => true,
'reviews_allowed' => false,
'meta_data' => [
[
'key' => '_custom_meta_1',
'value' => 'value1'
],
[
'key' => '_custom_meta_2',
'value' => 'value2'
]
]
];
the "meta_data" field, should be an array, containing arrays with "key" and "value" attributes.

Symfony 2.6 checked by default checkboxes

How I can make checkboxes checked by default based on data from database?
Now my form looks like:
...
->add(
"role", "entity", [
"class" => "AppDefaultBundle:OptionRole",
"required" => false,
"label" => "Roles for user: ",
"property" => "name",
"expanded" => true,
"multiple" => true
]
)
...
And I want to select defaults for this checkboxes based on data from other table.
You should probably add the choices property: http://symfony.com/doc/current/reference/forms/types/choice.html#choices
In your case you should have an array with all OptionRoles relevant for the (User ?) entity you are working on (the one you create the form for).
Assuming the doctrine User model knows it's OptionRoles (most likely a ManyToMany association) the form should automatically check the checkboxes of the Users OptionRoles.
Here is one example:
[
'label' => 'Select Modules',
'class' => 'Foo\BarBundle\Entity\Module',
'choices' => $this->availableModules(),
'property' => 'name',
'multiple' => true,
'expanded' => true
]
...
public function availableModules()
{
return $this->get('doctrine')
->getManager()
->getRepository('Foo\BarBundle\Entity\Module')
->findAll();
}

Resources