[development] node_load using cck fields

Lluís Forns enboig at gmail.com
Thu Mar 24 09:57:44 UTC 2011


Searching more I found http://drupal.org/node/360541 which was nearly
what I was looking for. I changed that function because it was
returning a "node"; so now it returns an array of nids and then I can
use node_load() to load them (in my case just one). It also uses
db_rewrite_sql() to ensure you can only load nodes accessible to you.

The final function is:

function _content_node_loads($param = NULL) {
  if (!is_array($param)) {
    return FALSE;
  }
  $arguments = array();
  $cck_tables = array();
  $cck_cond = array();
  $cond = array();
  $i = 1;
  foreach ($param as $key => $value) {
    if (substr($key, 0, 6) != 'field_') {
      $cond[] = 'n.'. db_escape_table($key) ." = '%s'";
      $arguments[] = $value;
    }
    else{
      $db_info = content_database_info(content_fields($key));
      // If the field is from another table, increment sequence
      if(!isset($cck_tables[$db_info['table']])){
        $cck_tables[$db_info['table']] = 'cck'. $i;
      }
      $i++;
      if($db_info['columns']['nid']){
        // For nodereference fields
        $cck_cond[] = $cck_tables[$db_info['table']] .'.'.
db_escape_table($db_info['columns']['nid']['column']) ." = '%s'";
      } else if ($db_info['columns']['value']) {
        $cck_cond[] = $cck_tables[$db_info['table']] .'.'.
db_escape_table($db_info['columns']['value']['column']) ." = '%s'";
      } else if ($db_info['columns']['uid']) {
        $cck_cond[] = $cck_tables[$db_info['table']] .'.'.
db_escape_table($db_info['columns']['uid']['column']) ." = '%s'";
      }else if ($db_info['columns'][$key]['column']) {
        $cck_cond[] = $cck_tables[$db_info['table']] .'.'.
db_escape_table($db_info['columns'][$key]['column']) ." = '%s'";
      }
      $arguments[] = $value;
    }
  }
  $cond = (!empty($cond) ? implode(' AND ', $cond) : '' );
  if (!empty($cck_cond)) {
    $cond .= (!empty($cond) ? ' AND ' : ''). implode(' AND ', $cck_cond);
    foreach ($cck_tables as $table => $nick) {
      $cck_join .= ' INNER JOIN {'. $table .'} '. $nick .' ON '. $nick
.'.nid = n.nid';
    }
  }
  $sql = "SELECT n.nid FROM {node} n ".$cck_join." WHERE ".$cond;
  $res = db_query(db_rewrite_sql($sql), $param);
  $nids = array();
  while ($nid = db_result($res)) {
    $nids[$nid] = $nid;
  }
  return (empty($nids) ? FALSE : $nids);
}


2011/3/23 Lluís Forns <enboig at gmail.com>:
> I finished my function, I just added support for nodereference fields
> because this is what I want; maybe when I need more support I will add
> it. I post the code here, any comment is wellcome.
>
> function node_load_cck($param = array()) {
>  if (is_numeric($param)) {
>    return node_load($param);
>  }
>  $select = "SELECT n.nid FROM {node} n ";
>  $join = '';
>  $where = ' WHERE 1 ';
>  $data = array();
>  //contains array( 'table' => 'alias');
>  $tables = array();
>  $i = 0;
>  foreach($param as $field_code => $field_value) {
>    $data[] = $field_value;
>    if (substr($field_code, 0, 6) == 'field_') {
>      $field = content_fields($field_code);
>      switch ($field['type']) {
>        case 'nodereference':
>          $db_info = content_database_info($field);
>          if (!in_array($db_info['table'], $tables)) {
>            $tables[$db_info['table']] = 't'.$i;
>            $join .= ' LEFT JOIN {'.$db_info['table'].'} '.'t'.$i.' ON
> n.vid = '.'t'.$i.'.'.vid.' ';
>          }
>          $where .= " AND
> ".$tables[$db_info['table']].'.'.$db_info['columns']['nid']['column']."
> = '%s' ";
>        break;
>        default:
>          //TODO
>      }
>    }
>    else {
>      $where .= " AND n.".$field_code." = '%s' ";
>    }
>    $i++;
>  }
>  $sql = $select . ' ' . $join . ' ' . $where;
>  $nid = db_result(db_query($sql, $data));
>  $node = node_load($nid);
>  return $node;
> }
>
> 2011/3/23 Lluís Forns <enboig at gmail.com>:
>> Sorry, I didn't explain myself. I have read the article and I am
>> writing a "query builder" that loads a node matching received $params.
>>
>> My concert right now is that following the example
>> content_database_info should return something like:
>> array(2) {
>>  ["table"]=>
>>  string(17) "content_type_date"
>>  ["columns"]=>
>>  array(2) {
>>    ["value"]=>
>>    array(6) {
>>      ["type"]=>
>>      string(7) "varchar"
>>      ["length"]=>
>>      int(20)
>>      ["not null"]=>
>>      bool(false)
>>      ["sortable"]=>
>>      bool(true)
>>      ["views"]=>
>>      bool(true)
>>      ["column"]=>
>>      string(16) "field_date_value"
>>    }
>>    ["value2"]=>
>>    array(6) {
>>      ["type"]=>
>>      string(7) "varchar"
>>      ["length"]=>
>>      int(20)
>>      ["not null"]=>
>>      bool(false)
>>      ["sortable"]=>
>>      bool(true)
>>      ["views"]=>
>>      bool(false)
>>      ["column"]=>
>>      string(17) "field_date_value2"
>>    }
>>  }
>> }
>>
>>
>> but in my case it returns:
>> field_alumne => Array
>> (
>>    [table] => content_field_alumne
>>    [columns] => Array
>>        (
>>            [nid] => Array
>>                (
>>                    [type] => int
>>                    [unsigned] => 1
>>                    [not null] =>
>>                    [index] => 1
>>                    [column] => field_alumne_nid
>>                )
>>
>>        )
>>
>> )
>>
>> I assume the difference is because I access a related node and not data itself.
>>
>> 2011/3/22 Michael Prasuhn <mike at mikeyp.net>:
>>> It's pretty clear that you did not read the linked article. It is perfectly
>>> safe to use CCKs API to find out what tables a field's data is stored in.
>>> How do you think that Views is able to get at the correct table?
>>>
>>> -Mike
>>>
>>> Guillaume ! wrote:
>>>>
>>>> That will work in most cases, but if you ever re-use one of the fields
>>>> of the date content type with another content type, the field will be
>>>> moved to its own table (content_field_date). The safe way is really of
>>>> using views, or node_load, but there are obvious scalability issues
>>>> with foreach($a = node_load($nid++)), because they are really
>>>> independant of the content_type current structure. See
>>>> http://groups.drupal.org/node/10129 for more details.
>>>>
>>>> On 11-03-22 09:47 AM, Steve Edwards wrote:
>>>>>
>>>>> Here is the magic incantation:
>>>>>
>>>>>
>>>>> http://drewish.com/content/2010/06/correctly_accessing_cck_fields_in_sql_queries
>>>>>
>>>
>>> --
>>> __________________
>>> Michael Prasuhn
>>> 503.512.0822 office
>>> mike at mikeyp.net
>>> http://mikeyp.net
>>>
>>
>>
>>
>> --
>> *Les normes hi són perquè hi pensis abans de saltar-te-les
>> *La vida és com una taronja, què esperes a exprimir-la?
>> *Si creus que l'educació és cara, prova la ignorància.
>> *La vida és com una moneda, la pots gastar en el que vulguis però
>> només una vegada.
>> *Abans d'imprimir aquest missatge, pensa en el medi ambient.
>>
>
>
>
> --
> *Les normes hi són perquè hi pensis abans de saltar-te-les
> *La vida és com una taronja, què esperes a exprimir-la?
> *Si creus que l'educació és cara, prova la ignorància.
> *La vida és com una moneda, la pots gastar en el que vulguis però
> només una vegada.
> *Abans d'imprimir aquest missatge, pensa en el medi ambient.
>



-- 
*Les normes hi són perquè hi pensis abans de saltar-te-les
*La vida és com una taronja, què esperes a exprimir-la?
*Si creus que l'educació és cara, prova la ignorància.
*La vida és com una moneda, la pots gastar en el que vulguis però
només una vegada.
*Abans d'imprimir aquest missatge, pensa en el medi ambient.


More information about the development mailing list