Page 2 of 2

Posted: Tue Jan 09, 2007 5:35 pm
by Christopher
Hurreman wrote:All my actions inherit from a base class with the basic layout.
That is really your main or outer View but could also be considered you Response. I might suggest adding a setContent($content) method to it and registering it with the Locator. Then the your Actions composite rather than inherit, and just set the content are return. Note - It becomes a Response class if you also add redirect and headers to it.


You Home class is pretty simple, but I might split up The News class:

Code: Select all

<?php
class NewsModel
{
    private $db;
    private $user;

    public function __construct(&$locator)
    {
        $this->db = $locator->get('MySQL');
       $this->user = $locator->get('User');
    }

    public function getNews()
    {
        $stmt = $this->db->createQuery('SELECT * FROM news ORDER BY newsDate DESC, newsID DESC');
        $rs = $stmt->execute();
        $allrows = $rs->getAllRows();    // or whatever code you need here
        return $allrows;
     }

    public function getUserName($author)
    {
         return $this->user->getUserName($author);
    }

}

 class NewsView
{
    private $db;
    private $user;

    public function __construct(&$locator)
    {
        $this->model = new NewsModel($locator);
     }

    public function printNews()
    {
        $rs = $this->model->getAllRows();
        foreach ($rs as $row)
        {
            echo '<div id="newscontent">';
            echo '<p class="newsTitle">' . stripslashes( $row['newsTitle']) . '</p>';
            if($row['newsImage'])
            {
                echo '<img class="newsimage" src="images/pageimages/' . $row['newsImage'] . '"/>';
            }
            $body = stripslashes($row['newsText']);
            $bodyArr = explode(chr(13),$body);
            foreach($bodyArr as $content)
            {
                if(trim($content=='') || !isset($content))
                {
                    echo '<br/>';
                }
                else
                {
                    echo '<p class="newsText">' . $this->getPreparedString($content) . '</p>';
                }
            }
            echo '<p class="newsAuthor">Written by <i>' . $this->model->getUserName($row['newsAuthor']) . '</i></p>';
            echo '</div>';
        }
    }

    public function getPreparedString($str)
    {
        $str = strip_tags($str);
		$str = str_replace('[b]','<b>',$str);
		$str = str_replace('[/b]','</b>',$str);
		$str = str_replace('[i]','<i>',$str);
		$str = str_replace('[/i]','</i>',$str);
		$str = str_replace('[u]','<u>',$str);
		$str = str_replace('[/u]','</u>',$str);
        $str = str_replace('[list]','<ul>',$str);
        $str = str_replace('[/list]','</ul>',$str);
        $str = str_replace('[item]','<li>',$str);
        $str = str_replace('[/item]','</li>',$str);
        $str = preg_replace("!\\[url=(.*?)\\](.*?)\\[/url\\]!i", "<a target="_blank" href="\\1">\\2</a>", $str);
        return $str;
    }
}
?>

Posted: Wed Jan 10, 2007 3:28 am
by Hurreman
Think I'm starting to see. If I end up using templates, would I assign the data from within the NewsView or the NewsModel?
Example below:

Code: Select all

<?php
class NewsView
{
    private $db;
    private $user;
    private $tpl;

    public function __construct(&$locator)
    {
        $this->model = $locator->get('NewsModel');
        $this->tpl = $locator->get('Template_Lite');;
     }

    public function printNews()
    {
        $rs = $this->model->getAllRows();

        $this->tpl->assign("newsArr",$rs);

        $this->tpl->display("news.tpl");
        }
    }
}
?>

And the template

Code: Select all

<div id="container">
		
	<div id="maindiv">
        { foreach value=row from=$newsArr}

                {foreach key=key value=item from=$row}

                        {if $key eq "newsTitle"}

                                <h3>{$item}</h3>

                        {elseif $key eq "newsImage"}

                                <img src="{$item}"/>

                        {elseif $key eq "newsText"}

                                <p>{$item}</p>

                        {/if}

                { /foreach }

	{ /foreach }
	</div>
		
</div>

Posted: Wed Jan 10, 2007 4:02 am
by Christopher
Hurreman wrote:Think I'm starting to see. If I end up using templates, would I assign the data from within the NewsView or the NewsModel?
Like you have shown, the template code is all in the View.

The key to MVC is the dependencies -- and the most important is that the Model is not dependent on the View or Controller. The Model is in the domain layer and the View and Controller are in the presentation layer. The Model should only be dependent on a datasource which is on the lowest layer. Between the View and Controller the goal is to keep the View more independent. The Controller is the one that knows about everything -- so keep that code small.

Posted: Wed Jan 10, 2007 10:05 am
by Hurreman
Thanks again, It feels good being on the right track for once :wink:

Now, there's still my problem with a lot of files in the /actions folder, where the files for all actions are stored in chaos (or will be if I continue).
My current filestructure looks like follows: ( but filled with lots of more actions and classes )
  • Actions/
    • addnews.php
    • adminnews.php
    • delnews.php
    • editnews.php
    • updatenews.php
  • Lib/
    • FrontController.php
    • Locator.php
    • MySQL.php
    • News.php
  • index.php
  • style.css
Now, when redesigning and moving over to Template_Lite, I could perhaps have one sub-folder per "action type". One folder for news etc.
Something like this:
  • Actions/
    • News/
      • Templates/
        • addnews.tpl
        • adminnews.tpl
        • delnews.tpl
        • editnews.tpl
        • updatenews.tpl
      • Styles/
        • News.css
      • addnews.php
      • adminnews.php
      • delnews.php
      • editnews.php
      • updatenews.php
  • Lib/
    • FrontController.php
    • Locator.php
    • MySQL.php
    • News.php
  • Templates/
    • head.tpl
    • index.tpl
  • config.php
  • index.php
  • style.css

Using folders for the actions would however require that the FrontController knows that whener I visit index.php?action=addnews, it should look for it within the news action-folder. Somehow this solution doesn't seem like a very good one.

Any ideas? How do you guys do?

Posted: Wed Jan 10, 2007 11:06 am
by Maugrim_The_Reaper
Technically, having so many files is not really a problem except that it's harder to manage them. Another variant, probably quite possible with some changes to your frontcontroller and uri format, is to centralise each separate action/command class into a single class. i.e. you would have a NewsController class with add(), edit(), delete(), etc methods. This might also help centralise any common logic shared by each action in the class constructor or a set of private methods - for example each likely needs a News model.

Another tack is to have a parent Action or Controller class (whichever direction you go) to centralise common code you have in all your controller/action classes, i.e. in the constructor, etc.

I think you pretty much have the View area covered ;).

Posted: Wed Jan 10, 2007 12:10 pm
by Hurreman
Maugrim_The_Reaper wrote:Technically, having so many files is not really a problem except that it's harder to manage them.
You're right. And now that I think about it, I'm not sure they would be easier to maintain if they were separated in folders. A better idea is probably just to change my naming standard, and call files "News_Add.php" instead of "addNews.php". Then, I could just scroll down to the files starting with "N" to find all my News-actions.

Maugrim_The_Reaper wrote:Another variant, probably quite possible with some changes to your frontcontroller and uri format, is to centralise each separate action/command class into a single class. i.e. you would have a NewsController class with add(), edit(), delete(), etc methods.
All methods for example adding, deleting and editing news are already in Lib/News.php. The actions add/delete/edit/view then just access those methods and present the results.

Code: Select all

include('inc/pageLayout.php');
class home extends pagelayout
{
    // Content (overwrites the default printContent() in pagelayout)
    function printContent()
    {
        echo '<div id="content">';
        $this->locator->setArgs('News',$this->locator);
        $news = $this->locator->get('News');
        $news->printNews();
        echo '</div>';
    }

    // Execute
    function execute()
    {
        $this->printHead();
        $this->printHeader();
        $this->printNavigation();
        $this->printContent();
        $this->printRightDiv();
        $this->printFooter();
    }
}

The above example should now instead end up being something similiar to:

Code: Select all

$news = $this->locator->get('News');
$newsArr = $news->getNews();

$tpl = $this->locator->get('Template_Lite');
$tpl->assign("newsArr",$newsArr);

I'm a bit lost when it gets down to printing out all content. Let's say that my main page exists of a main template (containing all basic layout), a navigation menu (dynamic, changes depending on user and actual site content), news entries, and a small calendar (which fetches event information from mysql). I would need to initialize all modules and have them write to the template by using $tpl->assign(), and use placeholders in the main template wherever I want to place the module ( {include file="navigation.tpl"}, calendar.tpl, etc.. ).

However, where would I define which modules to call? In a "main view" class, which the actions then inherit?

index.php

Code: Select all

<?php
include 'Lib/Locator.php';
include 'Lib/FrontController.php';

$locator = new Locator();

$tpl = $locator->get('Template_Lite');

$fc = new FrontController($locator,'actions/','home','error');
$fc->execute();

$tpl->view("Templates/index.tpl");
?>