This is a very broad topic but this may give you some ideas. I am assuming you are using MySQL as a database for this example.
Two database tables:
categories: id (auto_increment primary key), name, description
articles: id (auto_increment primary key), categoryid, title, content
Two web forms:
category edit: textbox "name", textbox "description" (this will allow the user to create categories)
article edit: textbox "title," textarea "content", drop-down "category". Populate the category drop-down with "SELECT * FROM categories ORDER BY title".
When you add the article to the database, include the categoryid in the article record:
$category = mysql_real_escape_string($_POST['category']);
$title = mysql_real_escape_string($_POST['title']);
$content = mysql_real_escape_string($_POST['content']);
mysql_query("INSERT articles (categoryid, title, content) VALUES '{$category}','{$title}','{$content}'");
You can create a menu of categories with something like:
[[menu.php]]
$result = mysql_query("SELECT * FROM categories");
while($row = mysql_fetch_assoc($result))
{
echo "<div class='menuitem'><a href='category.php&id={$row['id']}'>$row['name']</a></div>";
}
To get all of the articles in a particular category:
[[category.php]]
$catid = mysql_real_escape_string($_GET['id']);
$result = mysql_query("SELECT * FROM articles WHERE categoryid = {$catid}");
while($row = mysql_fetch_assoc($result))
{
echo "<p class='articlelink'><a href='article.php&id={$row['id']}>$row['title']</a></p>";
}
The mysql_real_escape_string is there to prevent sql injection attacks when using user input in database queries. I will leave it to you to determine the CSS classes for menuitem and articlelink.