<p>mmikkel got me very close and pointed in the right direction. Here is what I ultimately did to get the info I needed. This seems like jumping through hoops but it does work.</p>

<pre><code>$contentType = $this-&gt;element-&gt;elementType;
$matrixBlockId = null;
$matrixFieldId = null;

if ($contentType === 'MatrixBlock') {
    $contentPath = explode('.', $this-&gt;contentPostLocation);

    $matrixField = craft()-&gt;fields-&gt;getFieldByHandle($contentPath[1]);

    $matrixBlockId = $contentPath[2];

    $matrixFieldHandle = $contentPath[4];

    $matrixService = new MatrixService();

    $matrixBlock = $matrixService-&gt;getBlockById($matrixBlockId);

    foreach ($matrixBlock-&gt;getFieldLayout()-&gt;getFields() as $thisField) {
        $thisFieldId = $thisField-&gt;getAttribute('fieldId');

        $field = craft()-&gt;fields-&gt;getFieldById($thisFieldId);

        if ($field-&gt;getAttribute('handle') === $matrixFieldHandle) {
            $matrixFieldId = $thisFieldId;

            break;
        }
    }
}
</code></pre>

CC BY-SA 3.0
2015-09-24T02:28:09.523Z
2015-09-24T02:28:09.523Z
TJ Draper
<p>I have done something similar to this where I needed a custom FieldType that saves its data to its own table and works inside (and outside) a Matrix Field.
The other answers with contentPostLocation might work but seem complicated to get the ids and/or data you need.</p>

<p>When your FieldType is used inside a Matrix Field a different ElementType will be returned. You can check this in <code>$this-&gt;element-&gt;elementType</code> and your check for MatrixBlock works nicely.</p>

<p>Now when inside the matrix .. ;)
<code>$this-&gt;element-&gt;id</code> will be the id of the MatrixBlockElement, so your BlockId.
<code>$this-&gt;element-&gt;fieldId</code> will be your fieldId (the matrix's field id)</p>

<p>And if you need the actual element where this block belongs to (as I did) you can use <code>$this-&gt;element-&gt;ownerId</code> to get the owner element (parent element?).
You can look at MatrixBlockElementType for more clues.</p>

<p>Saving your data in onAfterElementSave() will be the same, e.g. the following will get you the data for your Block and also when its not used as a Block (note this works because its getting the data for the Element so it doesn't care about any differences)</p>

<p><code>$fieldHandle = $this-&gt;model-&gt;handle;
$content = $this-&gt;element-&gt;getContent();
$data = $content-&gt;getAttribute($fieldHandle);
</code></p>

CC BY-SA 3.0
2015-11-04T21:37:52.073Z
I think this answer should be accepted over mine – this is obviously a better approach :)
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2015-10-30T09:59:31.320Z
2015-10-30T09:59:31.320Z
Wytse van der Velde
<p>The <a href="https://buildwithcraft.com/classreference/fieldtypes/BaseFieldType" rel="nofollow">BaseFieldType</a> class (which all FieldTypes extend) has a <a href="https://buildwithcraft.com/classreference/fieldtypes/BaseFieldType#contentPostLocation-detail" rel="nofollow"><code>contentPostLocation</code></a> property, which will give you the "path" to the field inside the entry model. The value is returned as a string, e.g. <code>fields.myCustomFieldTypeHandle</code>.</p>

<p>If your field is inside a Matrix block, the contentPostLocation path will include the Matrix field's handle – as well as the block ID – e.g. </p>

<p><code>fields.matrixFieldHandle.12.fields.myCustomFieldTypeHandle</code></p>

<p>Based on this, by exploding the <code>contentPostLocation</code> string and testing its length, you can figure out if the field is "standalone" or embedded in a Matrix block:</p>

<pre><code>$contentPath = explode('.', $this-&gt;contentPostLocation);
if (count($contentPath) &gt; 2) {
    // Not standalone (i.e. probably inside a Matrix block)
}
</code></pre>

<p>The Matrix' field's handle will be the second segment in the path. You can use the <a href="https://buildwithcraft.com/classreference/services/FieldsService#getFieldByHandle-detail" rel="nofollow">FieldsService</a> to pull the actual field, in order to get its ID. <em>It's probably also a good idea to confirm that it is indeed a Matrix field, which is easily done by checking its fieldtype's <code>classHandle</code> property</em>:</p>

<pre><code>$matrixFieldHandle = $path[1];
$matrixField = craft()-&gt;fields-&gt;getFieldByHandle($matrixFieldHandle);
if ($matrixField &amp;&amp; $matrixField-&gt;fieldType-&gt;classHandle === 'Matrix')
{
    // Yup, it's a Matrix field!
    $matrixFieldId = $matrixField-&gt;id;
}
</code></pre>

<p>Finally, the block ID would be the next segment in the <code>contentPostLocation</code> path, i.e. <code>$matrixBlockId = (int) $contentPath[2];</code></p>

<p>Putting it all together, something like this should do the trick:</p>

<pre><code>public function onAfterElementSave()
{
    $contentPath = explode('.', $this-&gt;contentPostLocation);
    if (count($contentPath) &gt; 2)
    {
        $matrixFieldHandle = $contentPath[1];
        $matrixField = craft()-&gt;fields-&gt;getFieldByHandle($matrixFieldHandle);
        if ($matrixField &amp;&amp; $matrixField-&gt;fieldType-&gt;classHandle === 'Matrix')
        {
            $matrixFieldId = $matrixField-&gt;id;
            $matrixBlockId = (int) $contentPath[2];
        }
    }
}
</code></pre>

CC BY-SA 3.0
2015-09-24T02:26:14.533Z
This got me pointed in the right direction. It still feels like I’m jumping through a lot of hoops. I modified had to get a little bit more info than what was available here though. I’ll post another answer as well so I can do a code demonstration.
TJ Draper
CC BY-SA 3.0
2015-09-23T23:10:34.700Z
2015-09-23T23:10:34.700Z
Mats Mikkel Rummelhoff
<p>I have a custom field that will be saving data to its own table. So if my field is in a Matrix field, I need to save the Matrix Field ID and Matrix Block ID to my table so I know what the data belongs to. I’m having a hard time figuring out how to get that data in my fieldtype. I’m using the <code>onAfterElementSave</code> method. I’ve been looking for attributes and types and whatnot on <code>$this</code>, <code>$this-&gt;element-&gt;getType()</code>, <code>$this-&gt;element-&gt;getType()-&gt;getAttributes()</code> and so far I’m just not having any luck finding this information. Can anyone point me in the right direction here?</p>

<matrix><custom-fieldtype>
Getting Matrix field ID and Block ID for my Custom Field
# Getting Matrix field ID and Block ID for my Custom Field

(Asked by: username_0 on 2015-09-23)

I have a custom field that will be saving data to its own table. So if my field is in a Matrix field, I need to save the Matrix Field ID and Matrix Block ID to my table so I know what the data belongs to. I’m having a hard time figuring out how to get that data in my fieldtype. I’m using the `onAfterElementSave` method. I’ve been looking for attributes and types and whatnot on `$this`, `$this->element->getType()`, `$this->element->getType()->getAttributes()` and so far I’m just not having any luck finding this information. Can anyone point me in the right direction here?

**Tags:** matrix, custom-fieldtype

---

## 3 answers

### Answer by username_2 on 2015-09-23. Score: 4 | Accepted answer

The BaseFieldType class (which all FieldTypes extend) has a contentPostLocation property, which will give you the "path" to the field inside the entry model. The value is returned as a string, e.g. fields.myCustomFieldTypeHandle.
If your field is inside a Matrix block, the contentPostLocation path will include the Matrix field's handle – as well as the block ID – e.g. 
fields.matrixFieldHandle.12.fields.myCustomFieldTypeHandle
Based on this, by exploding the contentPostLocation string and testing its length, you can figure out if the field is "standalone" or embedded in a Matrix block:
$contentPath = explode('.', $this->contentPostLocation);
if (count($contentPath) > 2) {
    // Not standalone (i.e. probably inside a Matrix block)
}

The Matrix' field's handle will be the second segment in the path. You can use the FieldsService to pull the actual field, in order to get its ID. It's probably also a good idea to confirm that it is indeed a Matrix field, which is easily done by checking its fieldtype's classHandle property:
$matrixFieldHandle = $path[1];
$matrixField = craft()->fields->getFieldByHandle($matrixFieldHandle);
if ($matrixField && $matrixField->fieldType->classHandle === 'Matrix')
{
    // Yup, it's a Matrix field!
    $matrixFieldId = $matrixField->id;
}

Finally, the block ID would be the next segment in the contentPostLocation path, i.e. $matrixBlockId = (int) $contentPath[2];
Putting it all together, something like this should do the trick:
public function onAfterElementSave()
{
    $contentPath = explode('.', $this->contentPostLocation);
    if (count($contentPath) > 2)
    {
        $matrixFieldHandle = $contentPath[1];
        $matrixField = craft()->fields->getFieldByHandle($matrixFieldHandle);
        if ($matrixField && $matrixField->fieldType->classHandle === 'Matrix')
        {
            $matrixFieldId = $matrixField->id;
            $matrixBlockId = (int) $contentPath[2];
        }
    }
}

> **Comments:**
> **username_0**: This got me pointed in the right direction. It still feels like I’m jumping through a lot of hoops. I modified had to get a little bit more info than what was available here though. I’ll post another answer as well so I can do a code demonstration.  

---

### Answer by username_0 on 2015-09-24. Score: 2

mmikkel got me very close and pointed in the right direction. Here is what I ultimately did to get the info I needed. This seems like jumping through hoops but it does work.
$contentType = $this->element->elementType;
$matrixBlockId = null;
$matrixFieldId = null;

if ($contentType === 'MatrixBlock') {
    $contentPath = explode('.', $this->contentPostLocation);

    $matrixField = craft()->fields->getFieldByHandle($contentPath[1]);

    $matrixBlockId = $contentPath[2];

    $matrixFieldHandle = $contentPath[4];

    $matrixService = new MatrixService();

    $matrixBlock = $matrixService->getBlockById($matrixBlockId);

    foreach ($matrixBlock->getFieldLayout()->getFields() as $thisField) {
        $thisFieldId = $thisField->getAttribute('fieldId');

        $field = craft()->fields->getFieldById($thisFieldId);

        if ($field->getAttribute('handle') === $matrixFieldHandle) {
            $matrixFieldId = $thisFieldId;

            break;
        }
    }
}


---

### Answer by username_1 on 2015-10-30. Score: 2

I have done something similar to this where I needed a custom FieldType that saves its data to its own table and works inside (and outside) a Matrix Field.
The other answers with contentPostLocation might work but seem complicated to get the ids and/or data you need.

When your FieldType is used inside a Matrix Field a different ElementType will be returned. You can check this in `$this->element->elementType` and your check for MatrixBlock works nicely.

Now when inside the matrix .. ;)
`$this->element->id` will be the id of the MatrixBlockElement, so your BlockId.
`$this->element->fieldId` will be your fieldId (the matrix's field id)

And if you need the actual element where this block belongs to (as I did) you can use `$this->element->ownerId` to get the owner element (parent element?).
You can look at MatrixBlockElementType for more clues.

Saving your data in onAfterElementSave() will be the same, e.g. the following will get you the data for your Block and also when its not used as a Block (note this works because its getting the data for the Element so it doesn't care about any differences)

`$fieldHandle = $this->model->handle;
$content = $this->element->getContent();
$data = $content->getAttribute($fieldHandle);`

> **Comments:**
> **username_2**: I think this answer should be accepted over mine – this is obviously a better approach :)  

---

