Drupal How to fix notice unserialize() and Undefined index? - drupal

I am getting below mention notice on /admin/reports/status page.
Notice: unserialize(): Error at offset 0 of 728 bytes in field_read_fields() (line 374 of /my_website/modules/field/field.crud.inc).
Notice: Undefined index: settings in text_field_schema() (line 17 of /my_website/modules/field/modules/text/text.install).
How to fix the notice?

The function unserialize() fails to convert a serialized value back into a PHP value because of an invalid length (or a length mismatch) in the stored representation of the data.
This means that a field record was not stored correctly in its field table.
The second notice tells us the type of the incriminated field : text_field_schema(), invoked via the hook_field_schema, exposes three field types : text, text_long, text_with_summary.
// line 392 of modules/field/field.crud.inc
$schema = (array) module_invoke($field['module'], 'field_schema', $field);
Just above, line 388, you got this :
module_invoke_all('field_read_field', $field);
By implementing this hook you should be able to point out which record is broken :
function yourmodule_field_read_field($field) {
if ($field['module'] === 'text' && !isset($field['settings'])) {
dpm($field);
}
}
Once identified, you will probably have to "repair" the field structure before saving it as usual via FieldAPI, e.g. :
$field += array(
'settings' => array(
'max_length' => $somelength
)
);
field_update_field($field);
The structure should be as defined in field_create_field().
[EDIT]
If you can't use field API, still you should be able to see which record is broken for that field.
Call field_read_field($field_name) and debug :
// line 370 of modules/field/field.crud.inc
$fields = array();
$results = $query->execute();
foreach ($results as $record) {
dpm($record); // check $record['data']
$field = unserialize($record['data']);
// ...
}
The broken record should be printed just before the first notice (if you display it).
Check the serialized value ($record['data']), and compare it with other records to see what's wrong. In the end you may have to update the field using SQL statements if you can't use field API.

Related

Drupal Commerce: Can't get variation type machine name from product variation object

I successfully receive product variation object by its id
$variation = \Drupal::entityTypeManager()->getStorage('commerce_product_variation')->load(8);
Then I successfully receive its structure like
(
[variation_id] => Array
(
[x-default] => 8
)
[type] => Array
(
[x-default] => router
)
[uuid] => Array
(
[x-default] => a44c2c31-2131-4c99-82a6-856b566d97cf
)
...
by print_r() like
echo '<pre>';
print_r($variation);
echo '</pre>';
Now if I try to get SKU through $variation->sku->value, I get it
But if I try to get variation type machine name through $variation->type->value I get nothing (and gettype($variation->type->value) returns NULL).
Still, we see it in the structure with the value router
Why and how to get the machine name ?
It's strange: the print_r() shows the way is $variation->type->value
But I've just successfully got it by
$variation->type[0]->target_id
This answer may be useful for someone who stumbles upon this post in the future
To get the machine name of the variation type from a product variation object in Drupal 9 Commerce, you can use the following code:
<?php
use Drupal\commerce\PurchasableEntityInterface;
// Load the product variation object.
$product_variation = ...;
// Ensure the object is a valid product variation.
if ($product_variation instanceof PurchasableEntityInterface) {
// Get the variation type.
$variation_type = $product_variation->getPurchasedEntity()->bundle();
// Get the variation type machine name.
$variation_type_machine_name = $variation_type->id();
// Use the variation type machine name as needed.
...
}
This code uses the PurchasableEntityInterface to ensure that the loaded object is a valid product variation. The getPurchasedEntity() method is used to get the underlying entity that represents the variation, and the bundle() method is used to get the variation type. The variation type machine name can then be obtained using the id() method.

Drupal 9 - Why is my body not saved with Node::create()

Thanks for taking the time to read my problem.
I'm trying to write a module that import content from an old version of Drupal to a new Drupal 9 website.
I managed to extract all content from the old database. It is stored in an array that I pass to a function reponsible for creating the node in the new DB. The problem I'm having is that the body of the node is not saved. Records are created in the tables node, node_field_data, node_revision, node_field_revision but nothing is created in node__body.
I tried two different methods :
1-
$node = Node::create(['type' => 'article_epingle']);
$node->langcode = $a["lang"];
$node->title = $a["title"];
// ... status, promote, ...
$node->body = array("value" => $a["body"], "format" => 'full_html');
// ... a few custom fields
$node->enforceIsNew();
$node->save();
Or
$node = Node::create(['type' => 'article_epingle']);
$node->langcode = $a["lang"];
$node->title = $a["title"];
// ... status, promote, ...
$node->body->value = $a["body"];
$node->body->format = 'full_html';
// ... a few custom fields
$node->enforceIsNew();
$node->save();
And 2 -
$node = \Drupal::entityTypeManager()
->getStorage('node')
->create(['type' => 'article_epingle',
'title' => $a["title"],
'body' => $a["body"],
// ... other fields
]);
$node->save();
The result is the same everytime, the body is not saved in DB. The save() method returns "1" and the newly created node appears in /admin/content but can't be displayed. The following error is returned if I try to display the node :
Error: Call to a member function displaySubmitted() on null in template_preprocess_node() (line 528 of core/modules/node/node.module).
Does anyone already had the same problem ?
Thanks in advance for your input !
I solved my problem.
I guess I did something wrong while installing Drupal because my code works fine after installing everything again.

Modifying a field collection programmatically missing hostEntity fields

I am trying to modify a field collection in a node that already exists so I can change an image on the first element in an array of 3. The problem is, the hostEntity info is not set when I do a entity_load or entity_load_single so when I do a:
$field_collection_item->save(true); // with or without the true
// OR
$fc_wrapper->save(true); // with or without the true
I get the following error:
Exception: Unable to save a field collection item without a valid reference to a host entity. in FieldCollectionItemEntity->save()
When i print_r the field collection entity the hostEntity:protected fields are indeed empty. My field collection is setup as follows:
field_home_experts
Expert Image <--- Want to change this data only and keep the rest below
field_expert_image
Image
Expert Name
field_expert_name
Text
Expert Title
field_expert_title
Text
Here is the code I am trying to use to modify the existing nodes field collection:
$node = getNode(1352); // Get the node I want to modify
// There can be up to 3 experts, and I want to modify the image of the first expert
$updateItem = $node->field_home_experts[LANGUAGE_NONE][0];
if ($updateItem) { // Updating
// Grab the field collection that currently exists in the 0 spot
$fc_item = reset(entity_load('field_collection_item', array($updateItem)));
// Wrap the field collection entity in the field API wrapper
$fc_wrapper = entity_metadata_wrapper('field_collection_item', $fc_item);
// Set the new image in place of the current
$fc_wrapper->field_expert_image->set((array)file_load(4316));
// Save the field collection
$fc_wrapper->save(true);
// Save the node with the new field collection (not sure this is needed)
node_save($node);
}
Any help would be greatly appreciated, I am still quite new to Drupal as a whole (end-user or developer)
Alright so I think I have figured this out, I wrote up a function that will set a field collection values:
// $node: (obj) node object returned from node_load()
// $collection: (string) can be found in drupal admin interface:
// structure > field collections > field name
// $fields: (array) see usage below
// $index: (int) the index to the element you wish to edit
function updateFieldCollection($node, $collection, $fields = Array(), $index = 0) {
if ($node && $collection && !empty($fields)) {
// Get the field collection ID
$eid = $node->{$collection}[LANGUAGE_NONE][$index]['value'];
// Load the field collection with the ID from above
$entity = entity_load_single('field_collection_item', array($eid));
// Wrap the loaded field collection which makes setting/getting much easier
$node_wrapper = entity_metadata_wrapper('field_collection_item', $entity);
// Loop through our fields and set the values
foreach ($fields as $field => $data) {
$node_wrapper->{$field}->set($data);
}
// Once we have added all the values we wish to change then we need to
// save. This will modify the node and does not require node_save() so
// at this point be sure it is all correct as this will save directly
// to a published node
$node_wrapper->save(true);
}
}
USAGE:
// id of the node you wish to modify
$node = node_load(123);
// Call our function with the node to modify, the field collection machine name
// and an array setup as collection_field_name => value_you_want_to_set
// collection_field_name can be found in the admin interface:
// structure > field collections > manage fields
updateFieldCollection(
$node,
'field_home_experts',
array (
'field_expert_image' => (array)file_load(582), // Loads up an existing image
'field_expert_name' => 'Some Guy',
'field_expert_title' => 'Some Title',
)
);
Hope this helps someone else as I spent a whole day trying to get this to work (hopefully I won't be a noob forever in Drupal7). There may be an issue getting formatted text to set() properly but I am not sure what that is at this time, so just keep that in mind (if you have a field that has a format of filtered_html for example, not sure that will set correctly without doing something else).
Good luck!
Jake
I was still getting the error, mentioned in the question, after using the above function.
This is what worked for me:
function updateFieldCollection($node, $collection, $fields = Array(), $index = 0) {
$eid = $node->{$collection}[LANGUAGE_NONE][$index]['value'];
$fc_item = entity_load('field_collection_item', array($eid));
foreach ($fields as $field => $data) {
$fc_item[$eid]->{$field}[LANGUAGE_NONE][0]['value'] = $data;
}
$fc_item[$eid]->save(TRUE);
}
I hope this helps someone as it took me quite some time to get this working.

Drupal 7 : change nid after node load

I have a very strange case in new developpement of an site web. I had made a block (with a custom module) and I make a node_load. Here all is ok, the node is load, the block is display. But for if I change nid of node (by exemple set null) and do nothing else (no node_save, no function call, NOTHING with this object), I have some notice of different module (like 3 or 4 modules). I know it's just notice, but I would understand why the simply fact of change variables wich is never uses, trigger some error..... Exemple :
$tmp = node_load(arg(1));
$tmp->nid=null;
=> error (lot of "Trying to get property of non-object in..." in diffrent name function)
$tmp = node_load(arg(1));
$node=$tmp;
$node->nid=null;
=> error (lot of "Trying to get property of non-object in..." in diffrent name function)
$tmp = node_load(arg(1));
$node = new stdClass();
//Copy via une boucle sinon on a des erreurs.
foreach ($tmp as $key => $value) {
if ($key != 'nid') $node->{$key} = $value;
}
=> all is ok
Ok finally it the comportement of references object php, we must applicate method Clone php on an object to make an copy, or the object will be refeerences

Illegal offset type in isset or empty in EntityChoiceList.php line 273

Within my Symfony2 project I've attempted to dynamically generate the entities used within my form type, by-passing the use of query builder etc.
To he entity choices property I am supplying an array of entities to be used. On page load everything seems fine and the correct content is displayed. However on form submission I get
Illegal offset type in isset or empty in EntityChoiceList.php line 273
at ErrorHandler ->handle ('2', 'Illegal offset type in isset or empty',
'..../Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php', '273', array('key' => object(myEntity))) in ..../Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php at line 273
.....
return isset($entities[$key]) ? $entities[$key] : null;
.....
What has me stumped is if I add var_dump(isset($this->entities[$key]));exit; above this line I am returned 'bool(true)' which to me means the key does exist.
As background I have attempted to extend the EntityType, for ease within my project and added:
public function getDefaultOptions(array $options)
{
$defaultOptions = array(
'em' => null,
'class' => 'Acme\TestBundle\Entity\myEntity',
'property' => null,
'query_builder' => null,
'choices' => $this->myEntityArray,
);
$options = array_replace($defaultOptions, $options);
$defaults = parent::getDefaultOptions($options);
return $defaults;
}
Has any one any ideas why I getting this error, or am I going about my issue all wrong anyway, with trying to pass an array of entities to choices?
If you're getting this while trying to remove an element from an ArrayCollection it's probably because you've typed:
$list->remove($item) instead of $list->removeElement($item)
I'm guessing you already solved this some other way, and this isn't a real answer either.
But I'm guessing either $entities isn't an array on that point, or $key isn't a scalar value.
For debugging you should use:
<?php
if (!is_array($entities) || !is_scalar($key)) {
var_dump($key, $entities));exit;
}
How you now tested this, it would stop on the first pass in that function. Symfony Forms use quit a lot of recursion, so an exit in any function usually doesn't help you.

Resources