ক্ষেত্রের সংগ্রহ কীভাবে সঠিকভাবে মুছবেন?


9

ড্রুপাল সংস্করণ: 7.21
ক্ষেত্র সংগ্রহের মডিউল সংস্করণ: 7.x-1.0-বিটা 5

সংক্ষিপ্ত ব্যাখ্যা : আমি ফিল্ড সংগ্রহগুলি প্রোগ্রামগতভাবে আমদানির চেষ্টাতে ব্যস্ত আছি তবে তাদের কিছু মুছার সময় সবসময় কিছু 'বোগাস' ফিল্ড সংগ্রহ বাকী থাকে।

দীর্ঘ ব্যাখ্যা : আমার ব্যবহারকারীদের প্রোফাইলে একটি ক্ষেত্র সংগ্রহের ক্ষেত্র রয়েছে। এই ক্ষেত্রের সংগ্রহে 3 টি পাঠ্য ক্ষেত্র রয়েছে। আমি ব্যবহারকারীর ক্ষেত্র সংগ্রহের জন্য একটি কাস্টম এসকিএল ডাটাবেস থেকে ডেটা আমদানি করতে চাই। এই ক্ষেত্র সংগ্রহের একাধিক মান থাকতে পারে। যখন আমি প্রথমবার ডেটা আমদানি করি যখন সবকিছু ঠিকঠাক হয়, আমি ক্ষেত্র সংগ্রহের ক্ষেত্রগুলিতে ডেটা দেখি। গ্রেট।

তবে এখানে আসে জটিল অংশ। ধরা যাক আমি কাস্টম ডেটাবেস থেকে একটি নির্দিষ্ট ব্যবহারকারীর জন্য 5 টি সারি আমদানি করি। তারা মাঠের সংগ্রহে যোগ হয়, সুতরাং এই ক্ষেত্র সংগ্রহে প্রতিটি 3 টি ক্ষেত্র সমেত 5 টি আইটেম রয়েছে। তারপরে আমি আমার কাস্টম ডাটাবেস থেকে কয়েকটি সারি মুছলাম যাতে এই ব্যবহারকারীর জন্য আমার কাছে কেবল 3 টি সারি থাকে। আমি ফিল্ড সংগ্রহের প্রথম 3 টি আইটেম আপডেট করে আবার আমদানি চালাই, তবে তারপরে আমি পূর্ববর্তী আমদানি থেকে 2 টি আইটেম রেখেছি। সেগুলি মুছে ফেলা উচিত কারণ আমার কাছে কেবল 3 টি আমদানি করা সারি রয়েছে তবে 5 টি ক্ষেত্র সংগ্রহের আইটেম রয়েছে।

সুতরাং আমি এই ক্ষেত্র সংগ্রহ আইটেমগুলি মুছে ফেলার চেষ্টা করেছি, কিন্তু সবসময় এক বা একাধিক আইটেম বাকি আছে। ক্ষেত্রগুলি শূন্য হয় যখন আমি ব্যবহারকারীর প্রোফাইল দেখি তবে এখনও সেখানে কিছু আছে। এই মুহুর্তে বলি আমি আমার কাস্টম ডাটাবেসে ব্যবহারকারীর জন্য 5 টি নতুন সারি যুক্ত করি, সুতরাং এই ব্যবহারকারীর জন্য আমার কাছে মোট 8 টি সারি রয়েছে। তারপরে আমি আবার আমদানি চালাই। প্রথম 3 টি আইটেম আপডেট হয়, তবে তারপরে আমি যখন চতুর্থ সারি যুক্ত করার চেষ্টা করি তখনও এটি 4 তম ক্ষেত্রের সংগ্রহ আইটেমটির সত্তা আইডি পায়, এটি আপডেট করার চেষ্টা করে তবে ব্যর্থ হয় এবং এই ত্রুটিটি ফিরিয়ে দেয়:

 Fatal error: Call to undefined method stdClass::save()

আমি নীচের এই প্রতিটি পদ্ধতির সাথে ফিল্ড সংগ্রহ আইটেমগুলি মুছতে চেষ্টা করেছি:

// Method 1
entity_delete_multiple('field_collection_item', array($fc_id));

// Method 2
$field_collection_item = field_collection_item_load($fc_id);
$field_collection_item->delete();

// Method 3
$field_collection_item = field_collection_item_load($fc_id);
$field_collection_item->deleteRevision();

এটি আমার সম্পূর্ণ কোড:

function import_user_field_collection(&$user, $old_user_id) {

  // I do a query to get the rows I want to import for this specific user.
  db_set_active('custom_sql_database');
  $result = db_query("SELECT * FROM {users} WHERE user_id = :user_id", array(':user_id' => $old_user_id));

  db_set_active('default');
  $i = 0; // Keep count of how many rows I imported.
  foreach($result as $row) {
    // Check if the field collection item already exists.
    if(!empty($user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'])) {
      // If it does exists, update this particular field collection item.
      $fc_id = $user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'];
      $field_collection_item = entity_load('field_collection_item', array($fc_id));
      // These 3 text fields are children of the field collection field.
      $field_collection_item[$fc_id]->field_profile_diploma_instituut[LANGUAGE_NONE][0]['value'] = $row->instituut;
      $field_collection_item[$fc_id]->field_profile_diploma_vakgebied[LANGUAGE_NONE][0]['value'] = $row->vakgebied;
      $field_collection_item[$fc_id]->field_profile_diploma_jaar[LANGUAGE_NONE][0]['value'] = $row->jaar_diploma;
      $field_collection_item[$fc_id]->save(TRUE);
    } else {
      // If the field collection item doesn't exist I want to create a new field collection item.
      $field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_profile_diploma_opleiding'));
      $field_collection_item->setHostEntity('user', $user);
      $field_collection_item->field_profile_diploma_instituut[LANGUAGE_NONE][0]['value'] = $row->instituut;
      $field_collection_item->field_profile_diploma_vakgebied[LANGUAGE_NONE][0]['value'] = $row->vakgebied;
      $field_collection_item->field_profile_diploma_jaar[LANGUAGE_NONE][0]['value'] = $row->jaar_diploma;
      $field_collection_item->save(TRUE);
    }
    $i++;
  }

  $fc_fields = field_get_items('user', $user, 'field_profile_diploma_opleiding');

  // Check if there are more field collection items than imported rows
  if(count($fc_fields) > $i) {
    for($i; $i <= count($fc_fields); $i++) {
      // Run through each field collection item that's left from the previous import and delete it.
      if(!empty($user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'])) {
        // Method 1
        $fc_id = $user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'];
        entity_delete_multiple('field_collection_item', array($fc_id));

        // Method 2
        //$field_collection_item = field_collection_item_load($fc_id);
        //$field_collection_item->delete();

        // Method 3
        //$field_collection_item = field_collection_item_load($fc_id);
        //$field_collection_item->deleteRevision();
      }
    }
  }
}

সুতরাং আমার প্রশ্নটি হল: আমি ক্ষেত্রের সংগ্রহের আইটেমগুলি কীভাবে মুছব যাতে তারা আসলে চলে যায়?


2
entity_delete_multipleএটি করার 100% স্পষ্টতই সঠিক উপায় - field_collection_field_deleteফাংশনটি দেখুন, যা ক্ষেত্র সংগ্রহ যখন রেফারেন্সযুক্ত ক্ষেত্রটি সরানো হয় তখন আইটেমগুলি পরিষ্কার করতে নিজেই ব্যবহার করে
ক্লাইভ

আপনার প্রতিক্রিয়া জন্য অনেক ধন্যবাদ, আমি এটি প্রশংসা করি। ফিল্ড_কলেশন_ফিল্ড_ডিলিটের সাথে আমার কী যুক্তি সরবরাহ করা উচিত তা কি আপনি জানতে পেরেছেন? আমি স্বাক্ষরটি ফিল্ড_কলেকশন_ফিল্ড_ডিলেট ($ সত্তা_প্রকার, $ সত্তা, $ ক্ষেত্র, $ উদাহরণস্বরূপ, $ ল্যাঙ্ককোড, এবং $ আইটেম) দেখছি তবে কী মান লিখতে হবে তা আমি সত্যিই জানি না: $ সত্তা (এটি কি ব্যবহারকারী বা ক্ষেত্রের সংগ্রহ) ?), $ ক্ষেত্র (ক্ষেত্রের_পরিবর্তন_ইটেম_লোডের ফেরত মান?), $ উদাহরণস্বরূপ, $ ল্যাংকোড (আনড?) এবং $ আইটেম।
স্মোস

1
সেই নির্দিষ্ট ফাংশনটি হুক বাস্তবায়ন, মূলত যখন কোনও ক্ষেত্র মুছে ফেলা হয় তখন ক্ষেত্রের নামটি সেই ফাংশনে প্রেরণ করা হয় এবং ক্ষেত্রের উদাহরণের সাথে কোনও এফসি সত্তা যুক্ত আছে কিনা তা ক্ষেত্র সংগ্রহটি পরীক্ষা করে। যদি এটি থাকে তবে এটি এটি ব্যবহার করে মুছে ফেলবে entity_delete_multiple()। ক্ষেত্রগুলি মুছে ফেলার পরে আপনার কয়েকবার ক্রোন চালানোর প্রয়োজন হতে পারে (ক্ষেত্রের ডেটা একটি সময়সূচিতে মুছে ফেলা হয় যাতে সমস্ত পৃষ্ঠাতে প্রক্রিয়াজাতকরণের সাথে একটি পৃষ্ঠার বোঝা বোঝা না হয়)
ক্লাইভ

আমি আবার সত্তা_প্রেমী_ বহুগুণ ব্যবহার করার চেষ্টা করেছি এবং আমি লক্ষ্য করেছি যে আইটেমগুলি টেবিল ক্ষেত্রে_ মোছা_পরিচয়_ইটমে মুছে ফেলা হয় তবে ক্ষেত্রগুলি এখনও টেবিলের ক্ষেত্র_ডাটা_ফিল্ড_কলেকশন_নামে বিদ্যমান। আমি মনে করি এটি মারাত্মক ত্রুটির কারণ হিসাবে অনির্ধারিত পদ্ধতিতে কল করুন stdClass :: save () কারণ তারা ক্ষেত্র হওয়ার কথা তবে তাদের সাথে কোনও ক্ষেত্র সংগ্রহের আইটেম লিঙ্ক করা নেই। আমি যখন $ ফিল্ড_কলেকশন_টাইম-> মুছে ফেলুন ব্যবহার করি তখন এটি উভয় টেবিলের ডেটা মুছে ফেলা হয় তবে আমি যখন ব্যবহারকারীকে সংরক্ষণ করি তখন একটি সারি টেবিলের সাথে ফিল্ড_ডেটা_ফিল্ড_কলেকশন_নামে যুক্ত হয় এবং এটি ফাঁকা ক্ষেত্র সংগ্রহ আইটেম।
স্মোস

@ স্মোস: আরে বন্ধু, আপনি কি আমাকে অনুরূপ ইস্যুতে সহায়তা করতে পারেন ( drupal.stackexchange.com/Qestions/239784/… )? আমি আপনার কোডের প্রাসঙ্গিক বিট চেষ্টা করেছি কিন্তু আমি এটি কাজ করতে পারি না।
সিসকো

উত্তর:


13

আমি অনুরূপ ব্যবহারের ক্ষেত্রে ছড়িয়ে পড়েছি যেখানে আমি hook_feeds_presave () এর সময় ক্ষেত্রের সংগ্রহের জন্য কিছু ডেটা ম্যাপ করতে চেয়েছিলাম যেহেতু ফিডসের জন্য উত্সের কাঠামো খুব জটিল। আমি দেখতে পেলাম যে সত্তা_প্রেমী_একটি বহু () ক্ষেত্র সংগ্রহের আইটেমগুলি সরিয়ে নিয়েছে, কিন্তু যখন আমি নোডটি সম্পাদনা করেছি, সেখানে এখনও খালি মাঠ সংগ্রহের একটি গুচ্ছ ছিল। আনসেট করা এবং মোছার কৌশলটি আমি এখানে পেয়েছি: https://drupal.stackexchange.com/a/31820/2762

যদি ফিডের উত্স পরিবর্তন হয়ে থাকে তবে আমি সমস্ত ক্ষেত্র সংগ্রহের আইটেমগুলি মুছুন এবং পুনরায় তৈরি করুন। আশা করি এটি সহায়ক।

foreach ($node->field_international_activity[LANGUAGE_NONE] as $key => $value) {
  // Build array of field collection values.
  $field_collection_item_values[] = $value['value'];

  // Unset them.  
  unset($node->field_international_activity[LANGUAGE_NONE][$key]);
}

// Delete field collection items.
entity_delete_multiple('field_collection_item', $field_collection_item_values);

এই 2 ধাপের পদ্ধতির একমাত্র উপায় যা আফাইক কাজ করে। node_save($node)আপনার নোড ভুলবেন না ।
বার্নহার্ড ফার্স্ট

@ বার্নহার্ড node_save($node)DrupalEntityController
ফার্স্ট

8

এখনই এটি করার সর্বোত্তম উপায় হ'ল কল $field_collection->delete()এবং এটি সবকিছু পরিচালনা করবে।

 <?php
    /**
     * Deletes the field collection item and the reference in the host entity.
     */
    public function delete() {
      parent::delete();
      $this->deleteHostEntityReference();
    }

    /**
     * Deletes the host entity's reference of the field collection item.
     */
    protected function deleteHostEntityReference() {
      $delta = $this->delta();
      if ($this->item_id && isset($delta)) {
        unset($this->hostEntity->{$this->field_name}[$this->langcode][$delta]);
        entity_save($this->hostEntityType, $this->hostEntity);
      }
    }
 ?>

0

উপরের উত্তরগুলি সর্বোত্তম উপায় নয়, অন্য সমস্ত আইটেম আনসেট না করে ক্ষেত্রের সংগ্রহ সংগ্রহ করে, এবং অন্যভাবে ->delete()সত্তা মডিউলটি দিয়ে একটি বাগ নিক্ষেপ করে।

সঠিক পথ. আমি যা করেছি তা হ'ল:

আমার ক্ষেত্রে আমি ফিল্ড সংগ্রহের মধ্যে শেষ আইটেমটি মুছতে চেয়েছিলাম

এই কোডটি একবার দেখুন, (নতুনদের জন্য: "মনে রাখবেন আপনার অবশ্যই ইতিমধ্যে $ সত্তা লোড হওয়া উচিত")

// Remove the field value
unset($entity->field_salida_mercanc_a[LANGUAGE_NONE][count($entity->field_salida_mercanc_a[LANGUAGE_NONE])-1]);

// Reset the array to zero-based sequential keys
$entity->field_salida_mercanc_a[LANGUAGE_NONE] = array_values($entity->field_salida_mercanc_a[LANGUAGE_NONE]);

// Save the entity
entity_save($entity_type, $entity);

এখানেই শেষ! অন্য উপায় হয়

//Get the node wapper
$wrapper = entity_metadata_wrapper($entity_type, $entity);
//Get the last position of the array items, thanks to the ->value() statement you can get the complete Array properties.
$field_collection_item_value = $wrapper->field_collection_mine[count($wrapper->field_collection_mine->value())-1]->value();
//Do not use 'unset' to delete the item due to is not the correct way, I use the entity_delete_multiple provided by the entity API
entity_delete_multiple('field_collection_item', array($field_collection_item_value->item_id));

উপরের উপায়টি entity_metadata_wrapperফাংশনটি ব্যবহার করে ভাল তবে সেই সাথে এখানে একটি জটিল ত্রুটি রয়েছে যা আমি কীভাবে এটি সমাধান করতে জানি না, আপনি এটি https://drupal.org/node/1880312 এ পরীক্ষা করতে পারেন এবং # 9 তে প্যাচ প্রয়োগ করার পরে আপনি পরবর্তী সমস্যাটি পেয়েছেন, এটি এখানে দেখুন https://drupal.org/node/2186689 এই বাগটি আপনি যদি ->delete()ফাংশন ব্যবহার করেন তবে তাও ।

আশা করি এটি কাউকে সাহায্য করবে।


0

ক্ষেত্রের সংগ্রহ আইটেমগুলি মুছতে vbo ব্যবহার করে। এটি ফিল্ড সংগ্রহ আইটেম হোস্ট সত্তার সাথে ক্ষেত্রের সম্পর্কটি স্বয়ংক্রিয়ভাবে সরিয়ে ফেলবে।


0

আমার অনুরূপ সমস্যা ছিল, যেখানে আমি কোনও ফিড থেকে একটি এফসি আইটেমে ডেটা আমদানি করি। যখন কোনও হোস্ট সত্তার আপডেট ফিড থেকে করা হয়, এবং আমি এই পরিবর্তনগুলি আমদানি করি, তখন আমি তা নিশ্চিত করতে চেয়েছিলাম যে ফিড উত্স থেকে বিদ্যমান যে কোনও বিদ্যমান এফসি আইটেমগুলি অপসারণ করা হয়েছে।

আমার সমাধান:

// Load host entity that I'm updating.
$host_entity = node_load($nid);
$host_entity_wrapper = entity_metadata_wrapper('node', $host_entity);

// Clear out the references to the existing FC items so that I have a fresh start.
$host_entity_wrapper->field_my_fc_items->set(NULL);

// Re-create the FC items from the source feed data.
foreach ($feed_data->items as $feed_item) {
  $fc = entity_create('field_collection_item', array('field_name' => 'field_my_fc_items'));
  $fc->setHostEntity($host_entity);
  // Some some fields on the FC item from the feed data.
  $fc_wrapper = entity_metadata_wrapper('field_collection_item', $fc);
  $fc_wrapper->field_some_fc_item_field->set($feed_item->data);
}

// Sync other field info onto host entity.
...

$host_entity_wrapper->save();

এবং এটাই. ফিল্ড সংগ্রহের হুক_ফিল্ড_আপডেট ( field_collection_field_update) ডি-রেফারেন্সযুক্ত এমন কোনও বিদ্যমান এফসি আইটেম মুছে ফেলার বিষয়ে যত্ন নেবে।

এর একমাত্র নেতিবাচকতা হ'ল যদি এফসি ডেটাতে কোনও পরিবর্তন না ঘটে, এটি মুছে ফেলা হয় এবং যাইহোক পুনরায় তৈরি করা হয়েছে। তবে এটা আমার পক্ষে বড় কথা নয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.