<p>I've now worked out how to do this.</p>

<p>As I have a copy of the entry that I want to save the file to, I can work out what the name of the dynamic folder will be called.</p>

<pre><code>// Generate target folder name
$targetFolderName = $entry-&gt;slug; // or whatever you want
</code></pre>

<p>Next, I see if the folder has already been created:</p>

<pre><code>// See if target folder exists
// I'm searching on the name of the folder, plus the id of the parent folder
// (see question above for how to find this)
$targetFolder = craft()-&gt;assets-&gt;findFolder(array(
    'name' =&gt; $targetFolderName,
    'parent' =&gt; $parentFolder-&gt;id
));

if (!$targetFolder) {
    // target folder doesn't exist so we must create it
    $targetFolder = craft()-&gt;assets-&gt;createFolder($parentFolder-&gt;id, $targetFolderName);

    if ($targetFolder-&gt;status == 'success') {
        $targetFolderId = $targetFolder-&gt;getDataItem('folderId');
    } else {
        throw new Exception(Craft::t("Failed to create new folder."));
    }

} else {
    $targetFolderId = $targetFolder-&gt;id;
}

// Now I can move the PDF from its temporary location into out new assets folder
$response = craft()-&gt;assets-&gt;insertFileByLocalPath(
    $localFilePath, 
    $filename, 
    $targetFolderId, 
    AssetConflictResolution::KeepBoth
);
</code></pre>

<p>From here I followed the same code as in the question to add the asset to the asset field in <code>$entry</code>.</p>

CC BY-SA 3.0
2016-05-05T19:34:09.480Z
2016-05-05T19:34:09.480Z
Steve Rowling
<p>I've got a plugin that creates PDFs using Michael Rog’s Printmaker plugin. I'm able to successfully save these to a local folder and, using <code>insertFileByLocalPath()</code>, add them to an asset source. Then, by finding the <code>id</code> of the newly created asset, I can save the PDF to an entry.</p>

<p>My problem is that the asset field in the entry is setup to use dynamically-created subfolders, which I want to use to keep the assets for each entry separate from each other.</p>

<p>However, because the dynamically-created subfolder doesn’t exist until an asset is added to the entry, I am adding the PDF to the parent folder using <code>insertFileByLocalPath()</code>.</p>

<p>I thought that when I added the asset to the entry and saved it, Craft would dynamically create the subfolder and move the asset into it, but it doesn’t do this. Instead, it just leaves the assets in the parent folder.</p>

<p>Here’s a simplified version of the code I’m using at the moment:</p>

<pre><code>// Create PDF with $vars and $settings
$pdf = craft()-&gt;printmaker_pdf-&gt;pdfFromTemplate($template, $vars, $settings);

// Save PDF and get URL
$pdfUrl = $pdf-&gt;url();

// Get assets parent folder
$folder = craft()-&gt;assets-&gt;findFolder(array(
    'name' =&gt; 'parent-folder'
));

...

$response = craft()-&gt;assets-&gt;insertFileByLocalPath(
    $localFilePath, 
    $filename, 
    $folder-&gt;id, 
    AssetConflictResolution::KeepBoth
);

// Get id of pdf (newly created Asset)
$pdfId = craft()-&gt;assets-&gt;findFile(array(
    'filename' =&gt; $settings['filename'].'.pdf'
))-&gt;id;

// Add PDF to entry
$entry-&gt;setContentFromPost(array(
    'myAssetField' =&gt; array($pdfId)
));

if (craft()-&gt;entries-&gt;saveEntry($entry)) {
    // Yay! PDF successfully saved to myAssetField
}
</code></pre>

<p>And here’s what the asset folder layout looks like:</p>

<pre><code>parent-folder/new.pdf
</code></pre>

<p>Whereas what I want to achieve is this:</p>

<pre><code>parent-folder/entry-slug/new.pdf
</code></pre>

<p>Where <code>entry-slug</code> is a dynamically created subfolder for each entry.</p>

<p>Any ideas how I can achieve this, or if it is even possible?</p>

<plugin-development><assets>
How do I add a local file to an asset field with a dynamically generated sub-folder?
# How do I add a local file to an asset field with a dynamically generated sub-folder?

(Asked by: username_0 on 2016-05-05)

I've got a plugin that creates PDFs using Michael Rog’s Printmaker plugin. I'm able to successfully save these to a local folder and, using insertFileByLocalPath(), add them to an asset source. Then, by finding the id of the newly created asset, I can save the PDF to an entry.
My problem is that the asset field in the entry is setup to use dynamically-created subfolders, which I want to use to keep the assets for each entry separate from each other.
However, because the dynamically-created subfolder doesn’t exist until an asset is added to the entry, I am adding the PDF to the parent folder using insertFileByLocalPath().
I thought that when I added the asset to the entry and saved it, Craft would dynamically create the subfolder and move the asset into it, but it doesn’t do this. Instead, it just leaves the assets in the parent folder.
Here’s a simplified version of the code I’m using at the moment:
// Create PDF with $vars and $settings
$pdf = craft()->printmaker_pdf->pdfFromTemplate($template, $vars, $settings);

// Save PDF and get URL
$pdfUrl = $pdf->url();

// Get assets parent folder
$folder = craft()->assets->findFolder(array(
    'name' => 'parent-folder'
));

...

$response = craft()->assets->insertFileByLocalPath(
    $localFilePath, 
    $filename, 
    $folder->id, 
    AssetConflictResolution::KeepBoth
);

// Get id of pdf (newly created Asset)
$pdfId = craft()->assets->findFile(array(
    'filename' => $settings['filename'].'.pdf'
))->id;

// Add PDF to entry
$entry->setContentFromPost(array(
    'myAssetField' => array($pdfId)
));

if (craft()->entries->saveEntry($entry)) {
    // Yay! PDF successfully saved to myAssetField
}

And here’s what the asset folder layout looks like:
parent-folder/new.pdf

Whereas what I want to achieve is this:
parent-folder/entry-slug/new.pdf

Where entry-slug is a dynamically created subfolder for each entry.
Any ideas how I can achieve this, or if it is even possible?

**Tags:** plugin-development, assets

---

## 1 answers

### Answer by username_0 on 2016-05-05. Score: 3 | Accepted answer

I've now worked out how to do this.
As I have a copy of the entry that I want to save the file to, I can work out what the name of the dynamic folder will be called.
// Generate target folder name
$targetFolderName = $entry->slug; // or whatever you want

Next, I see if the folder has already been created:
// See if target folder exists
// I'm searching on the name of the folder, plus the id of the parent folder
// (see question above for how to find this)
$targetFolder = craft()->assets->findFolder(array(
    'name' => $targetFolderName,
    'parent' => $parentFolder->id
));

if (!$targetFolder) {
    // target folder doesn't exist so we must create it
    $targetFolder = craft()->assets->createFolder($parentFolder->id, $targetFolderName);

    if ($targetFolder->status == 'success') {
        $targetFolderId = $targetFolder->getDataItem('folderId');
    } else {
        throw new Exception(Craft::t("Failed to create new folder."));
    }

} else {
    $targetFolderId = $targetFolder->id;
}

// Now I can move the PDF from its temporary location into out new assets folder
$response = craft()->assets->insertFileByLocalPath(
    $localFilePath, 
    $filename, 
    $targetFolderId, 
    AssetConflictResolution::KeepBoth
);

From here I followed the same code as in the question to add the asset to the asset field in $entry.


---

