<p>When trying to figure out how to do something the core does programmatically, a good place to start is the core itself. In particular, you want to look at <a href="https://github.com/craftcms/cms/tree/develop/src/controllers" rel="nofollow noreferrer">Craft's controllers</a> which handle all interactions with the UI and <a href="https://github.com/craftcms/cms/tree/develop/src/services" rel="nofollow noreferrer">Craft's services</a> which provide a lot of methods for common tasks.</p>
<p>In this case, you're looking for <a href="https://github.com/craftcms/cms/blob/3.7/src/controllers/SectionsController.php#L111-L189" rel="nofollow noreferrer">craft\controllers\SectionsController::actionSaveSection</a> and <a href="https://github.com/craftcms/cms/blob/3.7/src/services/Sections.php#L409-L557" rel="nofollow noreferrer">craft\services\Sections::saveSection</a> (note for posterity: those links go directly to the 3.7 branch, make sure to look up the corresponding methods in the current version of Craft).</p>
<p>Looking through the controller method, you can figure out how to create a new section and save it:</p>
<pre class="lang-php prettyprint-override"><code>use craft\models\Section;

$sectionsService = Craft::$app-&gt;getSections();

$section = new Section();
$section-&gt;name = 'My new section';
$section-&gt;handle = 'my_new_section';
$section-&gt;type = Section::TYPE_CHANNEL;
$section-&gt;enableVersioning = true;
$section-&gt;propagationMethod = Section::PROPAGATION_METHOD_ALL;
$section-&gt;previewTargets = [];

// set other properties and options …

$success = $sectionsService-&gt;saveSection($section);
if (!$success) {
    // saving the section failed, display or handle errors
}
</code></pre>
<p>Look through the source code linked above to find all the properties that are available or required.</p>
<hr />
<p>As a sidenote, if you create a new section in a plugin – for example, in the install handler – you'll want to make sure your plugin plays nicely with the <a href="https://craftcms.com/docs/3.x/project-config.html" rel="nofollow noreferrer">project config</a>. As far as I can tell, Craft handles this automatically, but make sure to properly test if your new section and all its properties end up in the project config so your plugin will still work when propagating the config to different installations / environments.</p>

CC BY-SA 4.0
2021-09-23T10:03:37.343Z
Two million thanks. Still a bit lost in craft concepts. Really appreciate your help.
Álvaro Franz
CC BY-SA 4.0
2021-09-23T10:45:49.733Z
@ÁlvaroFranz You're welcome! Yeah I know the feeling, Craft's documentation is a bit lacking when it comes to extending the core. Digging through the core's controllers and services is a gold-mine in information that isn't covered in the documentation ^^
MoritzLost
CC BY-SA 4.0
2021-09-23T09:56:30.490Z
2021-09-23T09:56:30.490Z
MoritzLost
<p>I am diving into Craft plugin development and there is one thing that I want to achieve, but I didn't find any documentation.</p>
<p>I managed to save specific new entries into a channel using <a href="https://docs.craftcms.com/api/v3/craft-services-elements.html#public-methods" rel="nofollow noreferrer">saveElement()</a>, but I have no clue about how I can create a new channel.</p>
<p>The idea is to build a plugin that uses a specific channel (for example a &quot;ToDo list items&quot;) and I want that channel to be created once the plugin is installed.</p>
<blockquote>
<p>Just as a matter of clarifying, for people who know about WordPress. The idea is to <strong>&quot;register a Custom Post Type&quot;</strong>.</p>
</blockquote>
<p>I am not providing any &quot;what did you try?&quot; code because I don't even know if this is possible. And of course I am not looking for &quot;the code&quot;, but rather for &quot;the concept&quot; :)</p>
<p><strong>UPDATE</strong></p>
<p>Thanks to <a href="https://craftcms.stackexchange.com/a/38378/12483">MortizLost's great answer</a>, I managed to achieve what I want. Leaving it here in case it helps someone sometime:</p>
<pre><code>$section_exists = Craft::$app-&gt;sections-&gt;getSectionByHandle('news');

if($section_exists){
    echo 'Section news already exists';
}else{

    $section = new Section([
        'name' =&gt; 'News',
        'handle' =&gt; 'news',
        'type' =&gt; Section::TYPE_CHANNEL,
        'siteSettings' =&gt; [
            new Section_SiteSettings([
                'siteId' =&gt; Craft::$app-&gt;sites-&gt;getPrimarySite()-&gt;id,
                'enabledByDefault' =&gt; true,
                'hasUrls' =&gt; true,
                'uriFormat' =&gt; 'news/{slug}',
                'template' =&gt; 'news/_entry',
            ]),
        ]
    ]);

    $section_was_created = Craft::$app-&gt;sections-&gt;saveSection($section);

    if($section_was_created){
        echo 'Section news has been created';
    }else{
        echo 'An error occurred while trying to create the news section';
    }

}
</code></pre>

<plugin-development><channels>
Create a channel programmatically
# Create a channel programmatically

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

I am diving into Craft plugin development and there is one thing that I want to achieve, but I didn't find any documentation.
I managed to save specific new entries into a channel using saveElement(), but I have no clue about how I can create a new channel.
The idea is to build a plugin that uses a specific channel (for example a "ToDo list items") and I want that channel to be created once the plugin is installed.

Just as a matter of clarifying, for people who know about WordPress. The idea is to "register a Custom Post Type".

I am not providing any "what did you try?" code because I don't even know if this is possible. And of course I am not looking for "the code", but rather for "the concept" :)
UPDATE
Thanks to MortizLost's great answer, I managed to achieve what I want. Leaving it here in case it helps someone sometime:
$section_exists = Craft::$app->sections->getSectionByHandle('news');

if($section_exists){
    echo 'Section news already exists';
}else{

    $section = new Section([
        'name' => 'News',
        'handle' => 'news',
        'type' => Section::TYPE_CHANNEL,
        'siteSettings' => [
            new Section_SiteSettings([
                'siteId' => Craft::$app->sites->getPrimarySite()->id,
                'enabledByDefault' => true,
                'hasUrls' => true,
                'uriFormat' => 'news/{slug}',
                'template' => 'news/_entry',
            ]),
        ]
    ]);

    $section_was_created = Craft::$app->sections->saveSection($section);

    if($section_was_created){
        echo 'Section news has been created';
    }else{
        echo 'An error occurred while trying to create the news section';
    }

}

**Tags:** plugin-development, channels


---

## 1 answers

### Answer by username_1 on 2021-09-23. Score: 3 | Accepted answer

When trying to figure out how to do something the core does programmatically, a good place to start is the core itself. In particular, you want to look at Craft's controllers which handle all interactions with the UI and Craft's services which provide a lot of methods for common tasks.
In this case, you're looking for craft\controllers\SectionsController::actionSaveSection and craft\services\Sections::saveSection (note for posterity: those links go directly to the 3.7 branch, make sure to look up the corresponding methods in the current version of Craft).
Looking through the controller method, you can figure out how to create a new section and save it:
use craft\models\Section;

$sectionsService = Craft::$app->getSections();

$section = new Section();
$section->name = 'My new section';
$section->handle = 'my_new_section';
$section->type = Section::TYPE_CHANNEL;
$section->enableVersioning = true;
$section->propagationMethod = Section::PROPAGATION_METHOD_ALL;
$section->previewTargets = [];

// set other properties and options …

$success = $sectionsService->saveSection($section);
if (!$success) {
    // saving the section failed, display or handle errors
}

Look through the source code linked above to find all the properties that are available or required.

As a sidenote, if you create a new section in a plugin – for example, in the install handler – you'll want to make sure your plugin plays nicely with the project config. As far as I can tell, Craft handles this automatically, but make sure to properly test if your new section and all its properties end up in the project config so your plugin will still work when propagating the config to different installations / environments.

> **Comments:**
> **username_0**: Two million thanks. Still a bit lost in craft concepts. Really appreciate your help.  
> **username_1**: @ÁlvaroFranz You're welcome! Yeah I know the feeling, Craft's documentation is a bit lacking when it comes to extending the core. Digging through the core's controllers and services is a gold-mine in information that isn't covered in the documentation ^^  

---

