Use NID as node title
gavin_s - November 21, 2007 - 16:13
| Project: | Automatic Nodetitles |
| Version: | 6.x-1.2 |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs review |
Description
I need to set the node title to the nid. I assume I need some php code to do this? Or is it not possible as the node will not have an nid until it is saved?
Thank you

#1
hmm...similar thing happens with [author-name] on first registration:
cannot assign title because user name is not saved yet...any thought on this much apreciated!
thx
#2
You're right (node-based) tokens are not available to use in autonodetitle when you create a new node, because, well, the node which they reference doesn't exist yet... however, you can reference the values which have been submitted in the form itself though.
To get the author's name, edit your content type settings for Automatic title generation to make sure that 'evaluate PHP in pattern' is checked, and then try this:
<?phpglobal $form_values;
$title = 'This is a new node written by '. $form_values['name'];
return $title;
?>
#3
As already said, It's not possible.
#4
Automatically closed -- issue fixed for two weeks with no activity.
#5
download:
http://drupal.org/project/auto_nodetitle
set "Automatically generate the title if the title field is left empty" and in "Pattern for the title:" write:
<?php$name = db_prefix_tables('{node}_nid');
$id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
return $id;
?>
#6
this is great, i added some code to get a random number
<?php$name = db_prefix_tables('{node}_nid');
$random = (rand()%1025);
$id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + $random * 3;
srand(time());
return $id;
?>
don't forget to check "Evaluate PHP in pattern"
#7
The problem with adding a random number is that you are not guaranteed a unique number for your title.
You could retrieve an ID of 50, for example, and add the randomly generated number 2 - producing 52; then, the next time you create content of that type, you could retrieve an ID of 51 and if the random number generated is 1, you end up with 52 again! That's why adding 1 every time will work better (you will have a unique number).
#8
I agree with you, but you can solve that with a bigger range of random numbers, if you generate a random number between 1 and 9, you will get the same numbers a lot, but if you generate a random number between 10,000 and 99,999, the possibility of getting the same number it's smaller (just math).
But that's not the biggest problem, after I submitted the last comment, I started to use a lot that code, and even when I only use the sequence query (without adding a random number), if I edit the node the Node Title changes because it's getting another value from the sequence table.
I have no idea of how to solve this.
Luis
#9
I've used this successfully in the past for getting around the [nid] issue:
<?php
//wrap [nid] in quotes or else we'll get a parse error
$token = '[nid]';
if (!empty($token)) {
// this node is not new
return [author-uid] . '-' . [type] . '-' . $token;
}
else {
// this node is new
$nid = db_next_id('{node}_nid');
return [author-uid] . '-' . [type] . '-' . $nid;
}
?>
#10
comment #5 will work but not when editing a node. If you edit an old node you will see that the node title is changed to the next sequential nid.
For the person commenting on #9, be careful if you use the function db_next_id() because this will increment the nid as well. You may not want this. And this will also not work if you edit an old node.
I have altered the code and found the following code to work and takes care of the case for editing old nodes as well:
<?php$token_nid = '[nid]';
$token_type = '[type]';
if (!empty($token_nid)) {
// this node is not new
return $token_type . ' - ' . $token_nid;
}
$name = db_prefix_tables('{node}_nid');
$id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
return $token_type . ' - ' . $id;
?>
#11
How would i do this if i wanted to use a taxonomy term which was only just chosen as the title for the node?
#12
Hmm, not sure but I am guessing that the tax. term will be stored in some variable at the time you submit (maybe $node). But do you really want to do this in the first place? what would happen if two users created a node with the same taxonomy term? That would mean two nodes with the same title.
Also what happens if a user chooses more than 1 tax. term?
#13
Yes, i do want to do this. Two users won't choose the same taxonomy term in this case. Only a few users will have the access to use this. It will be for "online instructors" to create a course title. They will not have any need to choose more than 1 tax term and i will set it so that this is not possible.
It works fine if the user saves the node and then goes into edit and saves again and i can live with this if need be, but if there is a way to get around this, it would make things much less complicated.
#14
#9's solution worked for me, adding +1 to the node ID when this is a new one.
<?php
//Define your Prefix:
$prefix='My-[type]-';
//wrap [nid] in quotes or else we'll get a parse error
$token = '[nid]';
if (!empty($token)) { // this node is not new:
return ("$prefix-$token");
}
else { // this node is new:
$nid = db_next_id('{node}_nid') +1;
return ("$prefix-$nid");
}
?>
#15
If your using MySQL here's the code that Drupal 5 uses for db_next_id():
<?php
function db_next_id($name) {
$name = db_prefix_tables($name);
db_query('LOCK TABLES {sequences} WRITE');
$id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
db_query("REPLACE INTO {sequences} VALUES ('%s', %d)", $name, $id);
db_query('UNLOCK TABLES');
return $id;
}
?>
If your using postgreSQL, it does the same thing, but uses the postgreSQL function nextval() to calculate the sequence.
So long as you have an else statement following the check for the existence of nid, you can safely use db_next_id() and not have to worry about incrementing anything, because you will definitely be dealing with new node, and your essentially assigning the nid the same way Drupal does.
#16
Same issue. I don't like the offered solutions; In a heavy duty website titles may not actually correspond to the nid. That is, if many requests are made at the same time, db_next_id could return the same id for multiple nodes, unless i am mistaken.
On creation of a new node the nid doesn't exist. So why not make the system automatically edit the node after it has been safed?
Just a thought.
#17
I am sorry to reopen this issue. I am however desperately in need of a solid solution here. As in my previous post, I am concerned that the offered solution may not provide the actual nid. In a heavy duty website with thousands of users, if many people are adding posts in the same time, I am concerned that #14 might provide the same number for multiple nodes. So I have a theoretical solution in mind, and i hope that someone could give me some thought on it.
When I think about using Token, I think about Pathauto. Using the nid in Pathauto seems to work fine. I think this is because pathauto writes the path to the database after the node has been saved, thus having no problem using the nid. As far as I can tell Automatic Nodetitles alters the Title of a node before saving the node, therefore making the use of nid for the creation of nodes impossible. This in my opinion is in conflict with what Automatic Nodetitles should be able to do, it's not really logical that it can use Token, but not nid, author and perhaps other Tokens. So I think the module should be changed to save the node title in a similar way that Pathauto does; just a simple "UPDATE" SQL after the node has been saved and all data is available from Token.
Any comments on this? Thanks.
#18
Hi again.
I hacked a possible solution. I don't know how to create a patch, so i am posting the code here. It is a nodeapi function, and it will only be called on creation of a new node. So basically a new node is saved 2 times. I put the code after auto_nodetitle_set_title, on line 74. Try it out and give me some feedback please!
/*** Implementation of hook_nodeapi().
* Needed for newly saved nodes
*/
function auto_nodetitle_nodeapi(&$node, $op, $teaser, $page) {
// First check if this nodetype is auto_nodetitle enabled
$setting = auto_nodetitle_get_setting($node->type);
if ($setting == AUTO_NODETITLE_ENABLED || ($setting == AUTO_NODETITLE_OPTIONAL && empty($form_state['values']['title']))) {
switch ($op) {
// We only need to do this for new nodes. It will save the node again after creating the title
case 'insert':
$types = node_get_types();
$pattern = variable_get('ant_pattern_'. $node->type, '');
if (trim($pattern)) {
$node->changed = time();
$node->title = _auto_nodetitle_patternprocessor($pattern, $node);
}
else if ($node->nid) {
$node->title = t('@type @node-id', array('@type' => $types[$node->type]->name, '@node-id' => $node->nid));
}
else {
$node->title = t('@type', array('@type' => $types[$node->type]->name));
}
node_save($node);
break;
default:
break;
}
}
}
#19
I revised my code a little bit. Now it will put the title in AFTER the node is being saved, regardless whether its new or updated. The code should go in auto_nodetitle.module around line 74. This should work for drupal 5, but this is untested. I am using drupal 6.4.
/*** Implementation of hook_nodeapi().
* Needed for newly saved nodes
*/
function auto_nodetitle_nodeapi(&$node, $op, $teaser, $page) {
// First check if this nodetype is auto_nodetitle enabled
$setting = auto_nodetitle_get_setting($node->type);
if ($setting == AUTO_NODETITLE_ENABLED || ($setting == AUTO_NODETITLE_OPTIONAL && empty($form_state['values']['title']))) {
switch ($op) {
// Now works for insert and update. Title is stored in database with db_query instead of node_save
case 'insert':
case 'update':
$types = node_get_types();
$pattern = variable_get('ant_pattern_'. $node->type, '');
if (trim($pattern)) {
$node->changed = time();
$node->title = _auto_nodetitle_patternprocessor($pattern, $node);
}
else if ($node->nid) {
$node->title = t('@type @node-id', array('@type' => $types[$node->type]->name, '@node-id' => $node->nid));
}
else {
$node->title = t('@type', array('@type' => $types[$node->type]->name));
}
drupal_set_message($node->title . t(' has been generated. Node id is ') . $node->nid);
db_query("UPDATE {node} SET title = '%s' WHERE nid = %d", $node->title, $node->nid);
db_query("UPDATE {node_revisions} SET title = '%s' WHERE nid = %d AND vid = %d", $node->title, $node->nid, $node->vid);
break;
default:
break;
}
}
}
#20
subscribing.
#21
subscribing
#22
this code seems to be working fine for me. no problems (yet). thank you for this.
#23
for Drupal 5 works ok.
#24
This code won't get into the official module - so I change the status.
#25
Does #2 work in six? I can't seem to get it working. I need to get the value of the publish_on field from the scheduler module into the title.
Tried
<?phpglobal $form_values;
return $form_values['publish_on'];
?>
without any luck?
#26
Great job Dagomar, thank you very much
quick question, how would I modify the code on #19 to remove the nodetype in front of the nid to get a title resembling "1234" instead of "Story 1234"
Thank you
#27
I would imagine this can be done with the pattern you select?
For instance, i wanted the title of the node to be the nid, so i just used [nid] as title. This can be done on
"/admin/content/types/yourcontenttype" and then 'Automatic title generation'. I chose "Automatically generate the title and hide the title field" and as pattern "[nid]", like a said. If u have problems just PM me.
#28
Is everyone using #19 as a solution for this or has there been anything else available that we can use to get the [nid] as the Title during creation in D6?
Susbscribing
#29
There's a lot of comments with code in this issue, most of them work. I know the logic way to do this would be just to add the token [nid] but that won't work without a patch, instead you have to use some php code, I usually use #14 without a problem.
#30
There's a simple workaround using the Rules (or Workflow-ng) module
See http://drupal.org/node/360359#comment-1460918
#31
If the patch in #19 works, what still needs work here? Not clear on why it can't be rolled into the module. I think dagomar's reasoning makes alot of sense.
#32
takinola you are a legend... thanks for your solution. I agree with Aharown07 why hasn't this rolled into the module already?
#33
I'll add that I've been using patch19 for a few days now in test environment and have not seen any problems. (I don't really want to install Rules since I have no other use for it and it looks a bit heavy... that and I can't seem to understand how to make it work :) )
#34
subscribe
#35
Updating issue.
#36
Just create a rule. Similar to the suggested solution in http://drupal.org/node/360359#comment-1460918, I use the following in the custom PHP code option for actions on "add a node":
$node->title = $node->nid;
This does not require automatic nodetitles.
#37
This is not working with the latest dev version, and I can't seem to get the code from #19 to work.
Is someone working on adding this to the module? Or could someone please tell me where to add the above mentioned code in either version? Thanks in advance.
#38
#19 is still working fine for me. You put it in auto_nodetitle.module. I don't remember now if I just added the code or replaced what was there but in my file it starts around line 61 and ends around 94.
I think it basically replaces the whole hook_nodeapi implementation part.
No idea why it hasn't been rolled into the module or made avail as an admin option or something.
#39
Thanks aharown07, I just replaced the hook_nodeapi part with the code, and it's working well.
#40
Good... now we both know! :) (... and I thought I'd documented all my hacks so well)
#41
Ok I applied #19. However if I set "Automatically generate the title if the title field is left empty" and enter or type a value or something in the Title field it ignores it and enters the content type an node id no. Or am I not understanding something? I thought it's supposed to use the entered value first?
#42
Just used a simple workaround to create an automatic node title based on the nid
<?phpif ($node->title) {
echo $node->title;
}
else {
$sql = "SELECT COUNT(*) FROM {node} WHERE type = 'contenttype' AND status = 1";
$total = db_result(db_query($sql))+1;
echo $total;
}
?>
#43
ok, #42 - this good way, but title != global nid...
i'm not sure, but this code work for me:
<?php$ts_row = mysql_fetch_array(mysql_query(SHOW TABLE STATUS LIKE 'node'));
echo $ts_row[‘Auto_increment’] ;
?>
(sorry my english)
#44
one moment... if "Automatic title generation" set to "generate the title and hide the title field", code
if ($node->title) {echo $node->title;
} else {...
for use "Automatically generate the title and hide the title field" I add node_load (maybe exist best way?):
<?php$n = node_load($node->nid);
if ($n->title) {
echo $n->title;
} else {
$ts_row = mysql_fetch_array(mysql_query("SHOW TABLE STATUS LIKE 'node'"));
echo $ts_row['Auto_increment'] ;
}
?>
#45
Just setting status to "active" as there is no real patch here. But let's keep that issue open so that interested users can find it.
#46
Rolled dagomar's change from comment #19 into a patch (patch is against version 1.1). That is attached. IMO, this should become part of the module.
#47
#19 works with version 1.2 as well. I second @attheshow: this should become part of the module.
#48
I'm not sure the patch in #46 is quite right - the path isn't correct. Attached patch should work for 1.1 and 1.2 (and possibly earlier).
#50
I have an 'item ID' that is unique for each record and needs to be generated (auto-incremented) and used as the node title as well as a CCK field upon CCK form save, so I presume I can simply replace NID in patch #48 with any other DB variable I may be using, like 'item ID' in this case, and add some code to populate the CCK field at the same time, right?
Where can I find info on what code is needed to populate the CCK field? I'm not a developer but could probably hack my way through it if pointed in the right direction. I do have a copy of "Pro Drupal Development".
Is there anything else unique to using NID in the patch that I need to change?
I think it might be worth writing a module to generalize this feature for use not only with the NID and title field but other auto-increment fields and CCK fields in general, or just generalize the design of this module and rename it appropriately.
#51
I applied the patch above and I still get the node title of 'ant'.
•ant has been generated. Node id is 3148•Contacts ant has been created.
#52
Is this a general issue for all the on save features like Author Name , Node creation year etc? If so shouldn't the documentation on Replacement patterns mention it? Or is that down to Token?
Also I was curious why there are no Node creation time replacement patterns? or is that Token too?
Found http://drupal.org/node/207768#comment-1329294 which appears to have a Token patch which might mean this patch wasn't needed?
#53
Patch in #48 works for me. The patch needs some tweaks to match Drupal code style (spacing, doc formatting, else if should be elseif), and it should be rolled within the module dir (http://drupal.org/patch/create ).
#54
Patch #48 work great, Thanks jim0203
#55
#56
I try the #30 and it work but geocode from a field don't work any more :(
I open an issue #574894: Geocode don't work with rules with triger "after the node is saved "
EDIT: work great with patch #48 Thanks!
#57
Patch #48 works perfectly, I think it's the right solution! When it'll be ported to dev version?
#58
#59
I added the code from #19 into auto_nodetitle.module after row 75 and I immediately get a nasty php error:
Fatal error: Cannot redeclare auto_nodetitle_nodeapi() (previously declared in /home/xxx/domains/dannyjoris.be/public_html/yyy/sites/all/modules/auto_nodetitle/auto_nodetitle.module:64) in /home/xxx/domains/dannyjoris.be/public_html/yyy/sites/all/modules/auto_nodetitle/auto_nodetitle.module on line 109I put the code into place before I uploaded and installed it.
--Edit: it works now. Putting the code after row 75 was for version 6.x-1.0. I had version 6.x-1.2 . Replacing the function
auto_nodetitle_nodeapi()on row 64 will do the trick.#60
@fago
would this be accepted into the module if it would be written as an optional checkbox - "Run after content has been saved", hence exposing all node tokens and closing off any issues relating to this? what would be the performance issues related to checking that checkbox?
#61
A check box is not realy cool they need a DB request...
But we can certainly improve performance because nid never change:
So we can use "insert" with the code of the patch and keep "presave" when the node already existe.
pseudo code:
<?php
case 'presave':
//nid is already set (node exist) OR we don't need the nid in title
if(!isset($node->nid) || "nid is not in the paterne so we don't need it"){
auto_nodetitle_set_title($node);
}
break;
case 'insert':
//we need the nid in title?
if("nid present in $paterne so we need it"){
///So we change title after insert....
}
?>
What do you think?
#62
Has anyone seen this new module for CCK unique, atomic serial numbers?
The claim is it's accomplished in the same way that NIDs are.
http://drupal.org/project/serial
#63
Hi guys, I am not sure if this will help some of you, but for us this is a working solution when we need the NID as part of title.
After trying some of the stuff for auto_nodetitle we decided to use rules like posted in #39 (http://drupal.org/node/360359#comment-1460918).
Create a rule "after saving new content", create condition "if type is one of yours with auto_nodetitle" and add an action "custom PHP code" with:
auto_nodetitle_operations_update(array($node->nid));we are using node_autotitle-6.x-1.2+
Tom
#64
my solution ...
<?php
$lastNodeID = db_result(db_query("SELECT nid FROM {node} order by nid DESC limit 1 "));
echo $lastNodeID."/".(float)microtime()*10000000;
// to start with serial based on the node id
$lastNodeID = db_result(db_query("SELECT nid FROM {node} order by nid DESC limit 1 ")) + 1;
echo $lastNodeID;
?>
quick & fast .. hope this will help u!
#65
Will the solution in 48 be committed?
#66
I write in 61 that's the patch in 48 is good but not perfect because is always search nid in presave instead of check before if we have or not already a nid (this is the case if you save after edit).
#67
use code #64 ...
#68
This is a very simple issue. Currently, Automatic Nodetitles hooks into the 'presave' operation, presumably so it can modify the title and not have to worry about saving the node (as this will subsequently done by core). Obviously, the problem with this is that the node has not been saved yet, and so we don't have access to things like NID, or in my case - the CCK Serial field.
The simple solution is to change the hook_nodeapi reference so that it triggers on the 'insert' operation rather than 'presave' AND THEN also re-saves the node. This change is only a few lines of code. To give everyone some perspective, this is how modules like Pathauto work. The only downside to this method is you are saving the node again, but this is really not resource intensive.
I've attached my patch below. I really think this should be strongly considered as a permanent addition to the module. Or, at the very least, add an administrative option that allows the selection of 'presave' or 'postsave' title generation.
#69
Updated patch from #68 -- forgot to include the 'update' operation in addition to 'insert'.
#70
#71
I just modified the patch #69 to explain my idea but it's perhaps totally wrong:
- on first insert use "insert" and resave the node
- on update use the "presave" so resave is not needed
#72
watching this issue. i need nid in my titles.
#73
applying patch at #71 I got:
File to patch: ./auto_nodetitle.module
patching file ./auto_nodetitle.module
patch: **** malformed patch at line 21:
this is against the official relase of module for 6, not dev.
#74
Please use #69 for review, not #71.
@gagarine -- if you're going to post a patch, please be sure its code you've at least tested yourself first, rather than simply editing the .patch file and re-posting. Not only is your patch not applying, but your revision is incomplete. You are missing a 'break' after your 'insert' case.
While I agree that this would be another way to approach the fix, my preference would be to keep the code as simple as possible as in #71.