CodeIgniter Forums
Data to View - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Using CodeIgniter (https://forum.codeigniter.com/forum-5.html)
+--- Forum: Model-View-Controller (https://forum.codeigniter.com/forum-10.html)
+--- Thread: Data to View (/thread-61363.html)



Data to View - Urastor - 04-10-2015

Hellu, Smile
Let's say I want to make my controller a little bit more cleaner and my view more "attractive".
At the moment I'm using this code in my controller method:

PHP Code:
[...]
 
       $catString '';
 
       if (is_null($year) && $menuIndex === 2) {
 
           for ($cy = (int) date('Y'); $cy >= $this->config->item('cat_show_til_year'); $cy --) {
 
               $catString .= '<h2 class="cat_year"><a href="/category/search/' $category '/' $cy '">' $cy '</a></h2>';
 
               $catString .= $this->createCategoryPageString($this->site->getArticlesByCat($category$menuIndex$cy8));
 
           }
 
       } elseif (! is_null($year) && $menuIndex === 2) {
 
           $catString .= $this->createCategoryPageString($this->site->getArticlesByCat($category$menuIndex$year));
 
           $this->data['site_title'] .= ' &gt; ' $year;
 
       } else {
 
           $catString .= $this->createCategoryPageString($this->site->getArticlesByCat($category$menuIndex));
 
       }
[...] 

($this->site.. is a reference to the model)
The method createCategoryPageString, who I'm referring to, looks like this:

PHP Code:
   private function createCategoryPageString($result)
 
   {
 
       if (count($result) === 0)
 
           return '<p>Keine Beiträge vorhanden..</p>';
 
       
        $pages 
'';
 
       foreach ($result as $page) {
 
           $img_thumb parse_url(img_url() . 'akt/' $page->beiName '/thumbnail.jpg')['path'];
 
           if (file_exists(ltrim($img_thumb'/'))) {
 
               $img_link '<img src="' $img_thumb '" alt="' $page->beiTitel '" title="' $page->beiTitel '">';
 
           } else {
 
               $img_link '<img src="' img_url() . 'article_img.png" alt="' $page->beiTitel '" title="' $page->beiTitel '">';
 
           }
 
           
            $pages 
.= '<article class="cat_container"><header class="cat_header"><h2 class="hidden">Kategorie</h2>';
 
           $pages .= $img_link;
 
           $pages .= '</header><div class="cat_body">';
 
           $pages .= '<h2><a href="/page/show/' $page->beiName '">' $page->beiTitel '</a></h2>';
 
           $pages .= '<p>' character_limiter(strip_tags($page->beiInhalt), 130'...') . '</p>';
 
           $pages .= '</div></article>';
 
       }
 
       
        return $pages
;
 
   

As you can see, both methods using string concatenation to create a string, that represents an article. The problem is: all this happens in the controller, which should only use logic and not build the html for the view, right? The $catString is then send to the view and I can output the result with echo, but I'm curious how I could write it in the view and make everything a little bit more clean. I know I could just write it down but then the logic is just in the view and argh.. can't get it.

How should I do such things? Or is this the right way?


RE: Data to View - ivantcholakov - 04-10-2015

For similar cases my habit is using HMVC. Your current code does not look well, indeed, redesign would be difficult.


RE: Data to View - RobertSF - 04-10-2015

In general, you can clean things up by only building an array of data in your controller, passing that array to your view, and then letting your view insert the HTML. You can put arrays within arrays in the data array you send your view, and in your view, it's perfectly acceptable to use loops and conditional logic (if-then-else).

My brain's a little soft right now, so pardon me for not following your code, but I think I know what you mean. Suppose you had an array of friends, but not everyone had an email address. To display those without an email address, you could do something like this:
PHP Code:
// in your controller
foreach ($friends as $name => $email)
{
 
   if ($email == '')
 
   {
 
       // "\n" to make the HTML look nice
 
       $html '<p>' $name '</p>' "\n";
 
   }
}
$data = array(
 
   'html' => $html;
$this->load->view('friends_with_no_email'$data);

// in your view
<h1>Friends with no email address</h1>
<?
php echo $html ?>

But it would be better to do something like this:
PHP Code:
// in your controller
foreach ($friends as $name => $email
{
 
   if ($email == '')
 
   {
 
       $no_email_friends[] = $name;
 
   }
}
$data = array (
 
   'no_email_friends' => $no_email_friends
);
$this->load->view('friends_without_email'$data);

// in your view
<h1>Friends with no email address</h1>
<?
php foreach ($no_email_friends as $name): ?>
<p><?php echo $name ?></p>
<?php endforeach; ?>

That way, there is no HTML code in your controller. In my experience, the more complex the data, the more you gain by creating the data structure in the controller, and letting the view handle all the HTML. The PHP alternate syntax I used in the second example may seem verbose at first, but it results in view files that are easier to read and that generate cleaner HTML without having to include a bunch of "\n" and "\t" in your strings.


RE: Data to View - Urastor - 04-10-2015

Okay... thanks for reply. Smile
I tried to clean the whole mess up and this is the result:

Controller-method:
PHP Code:
[...]
if (
is_null($year) && $menuIndex === 2) {
 
           for ($cyear = (int) date('Y'); $cyear >= $this->config->item('cat_show_til_year'); $cyear --) {
 
               $this->data['articles'][$cyear] = $this->getArticles($this->site->getArticlesByCat($category$menuIndex$cyear8));
 
           }
 
           $this->data['show_years'] = true;
 
       } elseif (! is_null($year) && $menuIndex === 2) {
 
           $this->data['articles'][$year] = $this->getArticles($this->site->getArticlesByCat($category$menuIndex$year));
 
           $this->data['site_title'] .= ' &gt; ' $year;
 
       } else {
 
           $this->data['articles'][] = $this->getArticles($this->site->getArticlesByCat($category$menuIndex));
 
       }
[...] 

the getArticle-method (before: getCategoryPageString()):
PHP Code:
   private function getArticles($result)
 
   {
 
       if (count($result) === 0)
 
           return array();
 
       
        $pages 
= array();
 
       
        foreach 
($result as $page) {
 
           $img_thumb parse_url(img_url() . 'akt/' $page->beiName '/thumbnail.jpg')['path'];
 
           if (! file_exists(ltrim($img_thumb'/'))) {
 
               $img_thumb img_url() . 'article_img.png';
 
           }
 
           
            $pages
[$page->beiName] = array(
 
               'img' => $img_thumb,
 
               'title' => $page->beiTitel,
 
               'content' => $page->beiInhalt
            
);
 
       }
 
       
        return $pages
;
 
   

and finally a part of my view:
PHP Code:
[...]
 
       <?php foreach($articles as $year => $article): ?>  
        <?php if($show_years): ?>  
        <h2 class="cat_year">
            <a href="/category/search/<?=$category?>/<?=$year?>"><?=$year?></a>
        </h2>
        <?php endif; ?>
        <?php foreach($article as $name => $content): ?>
        <article class="cat_container">
            <header class="cat_header">
                <h2 class="hidden">Kategorie</h2>
                <img src="<?=$content['img']?>" alt="<?=$content['title']?>" title="<?=$content['title']?>">
            </header>
            <div class="cat_body">
                <h2>
                    <a href="/page/show/<?=$name?>"><?=$content['title']?></a>
                </h2>
                <p><?=character_limiter(strip_tags($content['content']), 130'...')?></p>
            </div>
        </article>
        <?php endforeach; ?>
        <?php endforeach; ?>
[...] 

This is much better and the view is well-feed. Is this the way to go? (sry for asking so often, but I would like to get the whole view thing, because, at least I think, it's hard to seperate :/)

Quote:The PHP alternate syntax I used in the second example may seem verbose at first, but it results in view files that are easier to read and that generate cleaner HTML without having to include a bunch of "\n" and "\t" in your strings.
Hihi.. even if a lot of people don't like this syntax, I really do when working with mixed html/php files. Big Grin


RE: Data to View - RobertSF - 04-10-2015

Yes, what you did is much better. Good job.

The only thing is the religious war between <?= and <?php echo. I prefer the first, but Codeigniter coding rules/conventions require the second. Also, many Open Source projects won't accept pull requests using the first. Just be aware of it. Smile


RE: Data to View - Urastor - 04-11-2015

Code:
The only thing is the religious war between <?= and <?php echo. I prefer the first, but Codeigniter coding rules/conventions require the second. Also, many Open Source projects won't accept pull requests using the first. Just be aware of it. Smile
Alright, I will keep that in mind.

Thanks for helping, I appreciate it. (:


RE: Data to View - CroNiX - 04-11-2015

(04-10-2015, 08:59 PM)RobertSF Wrote: The only thing is the religious war between <?= and <?php echo. I prefer the first, but Codeigniter coding rules/conventions require the second. Also, many Open Source projects won't accept pull requests using the first. Just be aware of it. Smile
Where does CI specify to use full PHP open tags?
http://www.codeigniter.com/user_guide/general/alternative_php.html#alternative-echos

There's even a setting in config to use short tags, which will convert to full open tags via regex if php.ini doesn't allow them.


RE: Data to View - Urastor - 04-11-2015

(04-11-2015, 10:01 AM)CroNiX Wrote: Where does CI specify to use full PHP open tags?

Here: http://www.codeigniter.com/user_guide/general/styleguide.html#short-open-tags

So.. I think he just wanted to say, that when you use PHP < 5.4 it would be smarter to not use them.
But that CI can convert the tags automatically is something I didn't know, maybe a thing to check out.


RE: Data to View - InsiteFX - 04-12-2015

The reason for the war was that years ago the short tags interfered with the xml opening tag.