0

I'm working on an input format filter that should work as following. I have a content-type called glossary, the user can fill in a word (title) and description (body). Then there is a content-type article. When a word in the article matches a word in the glossary it should wrap that word with a span. Something like word. I already did a quick and dirty tryout and that worked fine. I already did a speed test and it worked out fine only a delay of 0.2s max. But now I try to make it as it should and I got stuck.

The way I think this could work is to have an array with all words and descriptions from the glossary content-type in a array. And then search through the text.

So I created a Plugin/Filter/Filtername.php file. In this file I try to load all node from the glossary content-type (as advised) via dependency injection.

What I found is a way to get all nids, via this code added in to my filter class:

class FilterName extends FilterBase {
    public function __construct(QueryFactory $entity_query)
    {
        $this->entity_query = $entity_query;
    }

    public static function create(ContainerInterface $container){
        return new static(
          $container->get('entity.query')
        );
    }

    public function process(){
        $query = $this->entity_query
        $query->condition('bundle','woordenlijst');
        $nids = $query->execute();
    }
}

So this should give me all nids of the node I'm looking for but how do I get these node loaded to get there title and body text? I found this lesson about entity loading. Which is usefull but there are some deprecated functions used and I have no idea how to combine these to to get een array of titles and body texts.

So what is currently the best method to load nodes and how can I combine this with the code I already have? And am I even on the right path or not, or is there a better/easier way to do this?

Thanks in advance.

  • There is probably a good reason why you want to do this, but I can't think of one. All I can think of is this not being a scalable approach. That said, caching does work in your favor, but that first load is going to be killer. Are you trying to produce a list of node titles and bodies that can be embedded somewhere on a particular page? – mradcliffe Nov 22 '16 at 22:47
  • I have a good reason but maybe not the right method :D. What I try to make is a glossary. So I have a content-type called glossary, the user can fill in a word (title) and description (body). Then there is a content-type article. When a word in the article matches the glossary it should wrap that word with a span. Something like <span data-text="field description">word</span>. I already did a quick and dirty tryout and that worked, but no I try to make it as it should and I got stuck. – Joost Nov 22 '16 at 22:56
2

If yau have lots of node's than its difficult load all nodes at a time and also , to get only title and body, its not fair to load complete node. Rather than load node and get values, we can use select query and fetch required values.

I am using cache concept here, once your query loaded, set it in cache untill any node values changes or any new node creates. Use node hooks to remove cache for "node_data" Below is the query:

  $nodedata = array();
  // Check cache exists
  $cache_node = \Drupal::cache()->get('node_data');
  if ($cache_node) {
    $array = $cache_node->data;
    $nodedata = json_decode($array, TRUE);
  }
  else {
    // Query for node title and body.
    $connection = \Drupal::database();
    $query = $connection->select('node', 'n');
    $query->leftJoin('node__body', 'b', 'b.entity_id = n.nid');
    $query->leftJoin('node_field_data', 't', 't.nid = n.nid');
    $query->fields('t', array('title'));
    $query->fields('b', array('body_value'));
    $query->condition('n.type', 'glossary', '=');
    $result = $query->execute()->fetchAll();
    foreach ($result as $key => $value) {
      $nodedata[] = array(
        'node_title' => $value->title,
        'node_body' => $value->body_value,
      );
    }
    // Set Cache.
    \Drupal::cache()->set('node_data', json_encode($nodedata));
  }
  dsm($nodedata);
  • That's a very fast solution! To remove the cache, you could set a cache tag. Put ['node_list'] as 4th parameter when setting the cache data. Then the cache will be invalidated automatically whenever a node is changed or created. – 4k4 Nov 23 '16 at 19:50
0

you can use entityQuery like this for load all nodes of content type.

$node_array = array();
$query = \Drupal::entityQuery('node');
$query->condition('status', 1);
$query->condition('type', 'woordenlijst');
$entity_ids = $query->execute();
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($entity_ids);
 foreach ($nodes as $node) {
  $title = $node->getTitle();
  $body = $node->get('body')->getValue();

  $node_array[] = array(
'node_title' => $title,
'node_body' => $body,
);
}

Finally you got a array with title and body.Use dpm($node_array);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.