Johan Broddfelt
/* Comments on code */
Donate $

Topics to categorize posts

I'm not only going to write about my php framework. I want to write about other things as well, but I still want it to be easy to find and follow posts on a specific topic. We have tags but they do not really do the trick. So today we are going to implement a topic to the site.
First of all we set up the database table. Which in this case is really simple.

// Add table topic
CREATE TABLE IF NOT EXISTS `topic` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=1;

// Add relation to topic in post
ALTER TABLE `post` ADD `topic_id` INT NOT NULL AFTER `title`, ADD INDEX (`topic_id`);

After adding a set of topics and inserting them into my posts I want to update the menu so that I get a filter on top where I can filter on topic when selecting posts. But first we need to create a Topic class.

// classes/Topic.php
<?php
class Topic extends Db {
    public $table = 'topic';
    
}

Now I have rewritten the post_menu.php in order to add the topic at the top of the menu.

// views/post/post_menu.php
<div>
    <div id="menu_topic">
        <div id="topic_0" class="topic_button">All</div>
        <?php
        // Show all my topics
        $topic = new Topic();
        $tList = $topic->fetchArray();
        foreach($tList as $item) {
            ?>
            <div id="topic_<?php echo $item->id; ?>" class="topic_button"><?php echo $item->name; ?></div>
            <?php 
        }
        ?>
    </div>
    <?php
    // Show all my posts
    $post = new Post();
    $pList = $post->fetchArray('WHERE publish < '' . date('Y-m-d H:i:s') . '' ORDER BY publish DESC LIMIT 20');
    foreach($pList as $item) {
        ?>
        <a href="<?php echo $item->linkTitle(); ?>-<?php echo $item->id; ?>" class="topic_<?php echo $item->topicId; ?> post_link">
            <div class="sub_menu_title"><?php echo $item->title; ?></div>
            <div class="sub_menu_info"><?php echo $item->tags; ?> - <?php echo $item->posted; ?></div>
        </a>
        <?php 
    }
    ?>
</div>

// css/main.css
#menu_topic {
  display: flex;
  flex-wrap: wrap;
  line-height: 50px;
  justify-content: flex-start;
  align-content: flex-start;
  margin: 0px !important;
  padding: 0px !important;
  margin-left: 0px !important;
  padding-left: 25px !important;
  padding-right: 25px !important;
  margin-right: 0px !important;
  padding-top: 0px !important;
  padding-bottom: 0px !important;
}
.topic_button {
  cursor: pointer;
  padding-left: 10px;
  padding-right: 10px;
}
.topic_button:hover {
  background: #GreyNormal;
}

// js/main.js
  // Topic menu
  var topicBtn = document.getElementsByClassName('topic_button');
  var i = 0;
  while (i < topicBtn.length) {
    addListener(topicBtn[i], 'click', topic_click);
    i++;
  }
  function topic_click(e) {
    // if id == 0 then show all else hide all
    var postLink = document.getElementsByClassName('post_link');
    var i = 0;
    while (i < postLink.length) {
      if (e.target.id === 'topic_0' || hasClass(postLink[i], e.target.id)) {
        postLink[i].style.display = null;
      } else {
        postLink[i].style.display = 'none';
      }
      i++;
    }
  };

As you can see the code contains a function called hasClass. So I just going to add three functions that handles classes in the top of my js Framework part.

// js/main.js
// Manage classes in html elements
function hasClass(ele,cls) {
  return !!ele.className.match(new RegExp('(s|^)'+cls+'(s|$)'));
}

function addClass(ele,cls) {
  if (!hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
  if (hasClass(ele,cls)) {
    var reg = new RegExp('(s|^)'+cls+'(s|$)');
    ele.className=ele.className.replace(reg,' ');
  }
}

I also want to make it easier to follow the posts on a specific topic. So on each post I'm going to add a link to the previous and the next post on that specific topic. First I need to write some code that actually find the related topics. Then I'll add them as links in the bottom of the post.

// classes/post.php
    function getPrev() {
        $qry = 'SELECT id, title '
             . 'FROM post '
             . 'WHERE topic_id=' . $this->topicId . ' '
             . '  AND id<' . $this->id . ' '
             . 'ORDER BY id DESC '
             . 'LIMIT 1';
        $res = Db::query($qry);
        $row = Db::fetch_array($res);
        $obj = new Post();
        $obj->id = $row['id'];
        $obj->title = $row['title'];
        return $obj;
    }
    function getNext() {
        $qry = 'SELECT id, title '
             . 'FROM post '
             . 'WHERE topic_id=' . $this->topicId  . ' '
             . '  AND id>' . $this->id . ' '
             . 'ORDER BY id '
             . 'LIMIT 1';
        $res = Db::query($qry);
        $row = Db::fetch_array($res);
        $obj = new Post();
        $obj->id = $row['id'];
        $obj->title = $row['title'];
        return $obj;
    }

Then I'll just add the links in the post item page.

// view/post/item.php
<div class="navigation">
    <?php
    $prev = $obj->getPrev();
    $next = $obj->getNext();
    ?>
  <a <?php if ((int)$prev->id > 0) { ?>
  href="<?php echo $prev->linkTitle(); ?>-<?php echo $prev->id; ?>"<?php } ?>
  ><?php if ((int)$prev->id > 0) { ?><< <?php echo $prev->title; ?><?php } ?></a>
  
  <a <?php if ((int)$next->id > 0) { ?>
  href="<?php echo $next->linkTitle(); ?>-<?php echo $next->id; ?>"<?php } ?>
  ><?php if ((int)$next->id > 0) { ?><?php echo $next->title; ?> >><?php } ?></a>
</div>

// css/main.css
.navigation {
  display: flex;
  justify-content: space-between;
  padding-left: 30px;
  padding-right: 30px;
}

- Framework, PHP, Categories

<< RSSfeed for the masses Administration pages >>

Comment

Name
Mail (Not public)
Send mail uppdates on new comments

Comments

0 post found