There are many situations where programmatically creating a node is necessary. I'm sure we've all used this method at least once and each time may call for a slightly different configuration. Recently, I wrote a script to migrate a fairly small number of nodes (around 150). Along with the standard title, body, status and fields, I also had to migrate terms and attachments. Terms are fairly easy, but I've never needed to migrate attachments until now. I found a site which was very helpful with programmatically including attachments to a node. This is not to attach file to a file field, but to attach files as an attachment which uses the core Upload module. The main chunk of code is below:
foreach ($files as $file) {
$file_obj = new stdClass();
$file_obj->filename = $file->filename;
$file_obj->filepath = $file->filepath;
$file_obj->filemime = $file->filemime;
$file_obj->filesize = $file->filesize;
$file_obj->filesource = $file->filename;
// You can change this to the UID you want
$file_obj->uid = $file->uid;
$file_obj->status = $file->status;
$file_obj->timestamp = $file->timestamp;
$file_obj->list = 1;
$file_obj->new = true;
// Save file to files table
drupal_write_record('files', $file_obj);
// Attach the file object to your node
$node->files[$file_obj->fid] = $file_obj;
}
First thing we need to do is create a new file object. Fill in the file name, path, mime, size and source variables. In my case, I had these variables available from the old database, so I needed to save the new object into the new files table to get a file ID. These variables can also be retrieved by file_save_upload if you're uploading a new file. Afterwards, each file ID needs to be set as an array in the node object. Then node_save to commit the changes. Saved attachments are written into the upload table where they can reference the file ID and node ID.