I have 2 content types: videos and products. I'm using Entity Reference to link the products with associated videos. I'm working on automating the addition of videos and products from an outside source (using JSON). I can insert them just fine, but now I need to check to see if their exist. I'm starting with products, since I'm entering a unique product id for each, I figure I just need to see if it exists, and if not add it, if it does, then I need to link it to the new video.

Here's the code I'm using to select the entity_id:

$result = db_select('field_data_field_product_id')
 ->fields('entity_id')
 ->condition('field_product_id_value', $prodID,'=')
 ->execute()
 ->fetchAssoc();

DB Table: field_data_field_product_id
DB Column: entity_id
DB Condition: if column "field_product_id_value" is equal to the variable $prodID (which is set before the query)

Do I have things in the right place? Something out of order?

Comments

jmm42’s picture

You should research 'EntityFieldQuery'. That is specifically designed to pull 'entities' out of the database without respect to 'SQL data-store' -- meaning, it's flexible across various systems:

http://drupal.org/node/1901220

cfox612’s picture

Found another thread on EntityFieldQuery: http://drupal.org/node/1343708

Which has a good description, but doesn't help in how to correctly create the query... If I was writing straight mySQL I could have this done, going through Drupal operators (which I clearly have limited knowledge) is proving far more difficult. I think in my case it makes more sense to use db_select since I'll be writing similar queries elsewhere in the code.

DanZ’s picture

See also the EntityFieldQuery documentation.

I'm not sure exactly what you're trying for, and I don't know all the nuances of fieldCondition(), but you'll want something like this, which produces a list of Node IDs for nodes that have an attached field 'field_product_id with the value in $prodID:

    $efq = new EntityFieldQuery();
    $result = $efq->entityCondition('entity_type', 'node')
      ->fieldCondition('field_product_id', 'value', $prodID, '=')
      ->execute();
    if (!empty($result['node'])) {
      $nids = array_keys($result['node']);
      // Do something with the Node IDs here.
    }

You can narrow it down further to a particular entity bundle type, etc. EntityFieldQuery lets you attach lots of conditions.

--
www.ztwistbooks.com. Math books that are actually fun.

cfox612’s picture

Okay I think that's closer to what I'm looking for. Each productID is unique so the result will either return nothing (product doesn't exist) or one item.

Thanks!

cfox612’s picture

Alright follow up question. Now that I have the entity_id, I need to add an node reference for the newly created node (video), and the entity_id of the product. I tried:

$node = new stdClass();
$node->type = 'product';
node_object_prepare($node);
$node->field_video['und'][0]['nid'] = $nids[0];
node_save($node);

But since I'm technically not creating a new node I don't think this is correct. With the content type I've allowed multiple references, which works just fine, I just don't know how to do it in code. Should I just do a db_insert? Is there a "better" (ie "best practice") way?


I've also tried db_insert, and while this doesn't throw an error, it also doesn't insert anything into the DB.

$nid = db_insert('field_data_field_video') 
->fields(array(
        $node->uid=1,
	'entity_type' => 'node',
	'bundle' => 'product',
	'deleted' => 0,
	'entity_id' => $nids[0],
	'revision_id' => $nids[0],
	'language' => 'und',
	'delta' => 0,
	'field_video_target_id' => $node_id
	))
->execute();

Okay I think I'm on the right path now. I think I need to load the product node, and edit it to include another reference. I would have to include all previous references and add new ones. I want to make sure I'm not overriding what's already there. Any tips on using "node_load" or similar would be greatly appreciated!

cfox612’s picture

Post was getting a bit long...

Okay so here's the general gist: I have 2 content types, video and product. Each video has products associated with it through node reference. A product can be joined to multiple videos. Upon import it saves the initial product just fine, but I want to check to see if the product exists upon upload, and if it does, then I need to add another node reference instead of adding an additional product. The code to select the product works great, however the node update code doesn't work. It doesn't throw any errors, but it doesn't add another reference, it copies over the initial reference (what I was trying to avoid). What am I missing?

$result = $efq->entityCondition('entity_type', 'node')
  ->fieldCondition('field_product_id', 'value', $prodID, '=')
  ->execute();
if (!empty($result['node'])) {
	$nids = array_keys($result['node']);
	$node = node_load($nids[0]);
	$node->field_video['und'][0]['target_id'] = $node_id;
	node_save($node);
}
else
{
  Add product node
}
DanZ’s picture

I don't have time to analyze what you're doing right now, but I'll leave you with these links to documentation for functions that will help you. Have a read: node_load() and node_save().

Also, fields can be of a list type, and I see a [0] in your code. Maybe that's part of a list? I don't know much about Fields, but https://drupal.org/node/1879542 might help you.

Good luck!

--
www.ztwistbooks.com. Math books that are actually fun.

cfox612’s picture

I'm using node_load and node_save, which work fine, the issue is I'm saving over the node reference in place instead of adding another.

The "0" is from the array returned, which only has one result (as I said above, each product ID is unique).


For anyone else who needs it, the solution can be found here.

itsnadeem’s picture

Add below condition

->entityCondition('bundle', 'your_conten_ type')