Of course! Let's dive deep into dede:channel and its runphp attribute. This is a powerful and frequently used feature in DedeCMS for creating custom navigation menus and dynamic channel lists.

What is dede:channel?
First, dede:channel is a DedeCMS tag used to display a list of channels (also called categories or sections). By default, it simply lists the names of the top-level channels in your site.
Basic Example:
{dede:channel}
<a href='[field:typelink/]'>[field:typename/]</a>
{/dede:channel}
This would output something like:
<a href='/company/'>关于我们</a> <a href='/news/'>新闻中心</a> <a href='/products/'>产品展示</a>
What is the runphp attribute?
The runphp='yes' attribute fundamentally changes how the dede:channel tag works. Instead of just outputting the channel data directly, it tells DedeCMS to execute a block of PHP code for each channel in the list.

This allows you to perform complex logic, such as:
- Checking if the current page matches the channel.
- Dynamically adding CSS classes (e.g.,
current,active,menu-item-has-children). - Generating different HTML for different channels.
- Checking if a channel has child channels (sub-categories).
When runphp='yes' is used, the content between {dede:channel} and {/dede:channel} is treated as PHP code. The channel's data (like id, typename, typelink, etc.) is made available as PHP variables, which you can then manipulate.
How to Use runphp: A Step-by-Step Guide
Let's go through the most common use case: creating a navigation menu where the "current" channel is highlighted with a CSS class.
Step 1: The Basic Channel Tag Structure
Start with your basic channel list. We'll use an unordered list (<ul>) for good practice.

<ul id="nav">
{dede:channel type='top'}
<li><a href="[field:typelink/]">[field:typename/]</a></li>
{/dede:channel}
</ul>
type='top': This tells DedeCMS to only show the top-level channels. You can omit this to show all channels.
Step 2: Add runphp='yes'
Now, add the runphp attribute to the opening tag. We'll also wrap the <li> in <?php ... ?> to make our PHP code clear.
<ul id="nav">
{dede:channel type='top' runphp='yes'}
<?php
// PHP code will go here
?>
{/dede:channel}
</ul>
Step 3: Access Channel Data in PHP
When runphp is active, the field data from each channel is automatically available as PHP variables. The variable names are prefixed with $this->.
- Channel ID:
$this->Fields['id'] - Channel Name:
$this->Fields['typename'] - Channel Link:
$this->Fields['typelink'] - Channel Type ID:
$this->Fields['typeid'](useful for comparison)
You can also use the shorthand $fields array, which is often more convenient:
$fields['id']$fields['typename']$fields['typelink']
Step 4: Write the PHP Logic
Here is the complete PHP code to check if the current page is the channel page and apply a class="current" if it is.
<ul id="nav">
{dede:channel type='top' runphp='yes'}
<?php
// Get the current channel's ID from the PHP variable
$currentTypeId = $this->Fields['typeid'];
// Get the ID of the channel being viewed on the page.
// This is a global DedeCMS variable.
$globalTypeId = $GLOBALS['typeid'];
// Initialize a variable to hold our class name
$liClass = '';
// Compare the two IDs
if ($currentTypeId == $globalTypeId) {
// If they match, it's the current channel
$liClass = ' class="current"';
}
// Construct the final HTML for the list item
// We use @me to output the result
@me = "<li{$liClass}><a href=\"" . $this->Fields['typelink'] . "\">" . $this->Fields['typename'] . "</a></li>";
?>
{/dede:channel}
</ul>
Explanation:
$this->Fields['typeid']: Gets the ID of the channel we are currently looping through.$GLOBALS['typeid']: This is a special DedeCMS variable that holds the ID of the channel or article being displayed on the page.if ($currentTypeId == $globalTypeId): This is the core logic. It checks if the channel in our loop is the same as the one being viewed.$liClass = ' class="current"': If the condition is true, we set the$liClassvariable to our desired CSS class.@me = "...": This is the most important part. Inrunphpblocks, you must assign your final output string to the special variable@me. Whatever is in@mewill be rendered on the page.
More Advanced Examples
Example 1: Creating a Dropdown Menu (Checking for Sub-Channels)
This example checks if a channel has children and adds a has-children class. It also uses another DedeCMS tag, dede:sonchannel, inside the PHP block to list the sub-channels.
{dede:channel type='top' runphp='yes'}
<?php
$typeid = $this->Fields['id'];
$typename = $this->Fields['typename'];
$typelink = $this->Fields['typelink'];
$hasChildren = false;
$subChannelsHtml = '';
// Use the global object to query for sub-channels
$dsql = new DedeSql(false);
$dsql->SetQuery("SELECT id,typename,typedir FROM `#@__arctype` WHERE reid = $typeid AND ishidden<>1 ORDER BY sortrank");
$dsql->Execute('t');
if ($dsql->GetTotalRow() > 0) {
$hasChildren = true;
$subChannelsHtml = '<ul class="sub-menu">';
while ($row = $dsql->GetArray('t')) {
$subChannelsHtml .= "<li><a href='{$row['typedir']}'>{$row['typename']}</a></li>";
}
$subChannelsHtml .= '</ul>';
}
$dsql->Close();
$liClass = ($hasChildren) ? ' class="menu-item-has-children"' : '';
@me = "<li{$liClass}>"
. "<a href=\"{$typelink}\">{$typename}</a>"
. $subChannelsHtml
. "</li>";
?>
{/dede:channel}
Example 2: Applying Different Logic Based on Channel ID
You can use a switch statement to create completely different HTML for specific channels.
{dede:channel type='top' runphp='yes'}
<?php
$typeid = $this->Fields['id'];
$typename = $this->Fields['typename'];
$typelink = $this->Fields['typelink'];
switch ($typeid) {
case 1: // ID 1 is the "Home" page
@me = "<li><a href='/'>首页</a></li>";
break;
case 5: // ID 5 is the "Contact Us" page
@me = "<li class='contact-link'><a href='{$typelink}'>联系我们</a></li>";
break;
default: // All other channels
@me = "<li><a href='{$typelink}'>{$typename}</a></li>";
break;
}
?>
{/dede:channel}
Key Takeaways
- Enable PHP: Use
runphp='yes'on the{dede:channel}tag. - Use PHP Tags: Wrap your logic in
<?php ... ?>. - Access Data: Use
$this->Fields['fieldname']or$fields['fieldname']to get channel information. - Use Global Variables: Use
$GLOBALS['typeid']to get the ID of the current page. - Output with
@me: Always assign your final HTML string to the@mevariable to make it visible on the page. - Debugging: If your code doesn't work, check for PHP syntax errors. You can also temporarily use
echo $this->Fields['typename'];inside therunphpblock to see if it's looping correctly.
