CodeIgniter Forums

Full Version: Best Practice
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]skeletonfriend[/eluser]
Hi,
I'm developing an application for a record label and I'm currently stuck on one thing, I'm getting it to work but it doesn't seem to be the way to do it in terms of best practice. So, that's why I would like some input from any of you, how would you do it and so on.

My issue is: I have one artist controller, which loads the artist model and link model (an artist can have multiple links). In the controller I pass all artists to the view, through the model method getArtists(). In the view I loop through the result, but I need to list all the links that the artist may have....and that's where my best practice issue comes to mind. I solved this by, in the view, directly loop against the link models method getLinksByArtist() and pass the appropriate id to the method. Somehow, it doesn't seem right to use the link model directly in the view...I'm stuck on how I could solve this in the controller first, then pass it to the view.

One idea at first, was to, in the getArtists() method, join the artist_links table with the artist table, but then I need to loop through the result in the view for the links, somehow. Any ideas?

Artist model: getArtists()
Link model: getLinksByArtist()

This is how the code looks at the moment....

Controller
Code:
function Index()
{
  //simplified
  data['view_data'] = $this->artist_model->getArtists();
  $this->load->view('index', $data);
}

View
Code:
<?php foreach($view_data asĀ $row): ?>
  <h2>&lt;?= $row->title; ?&gt;</h2>
  <p>&lt;?= $row->description ?&gt;</p>

  &lt;?php if($this->link_model->getLinksByArtist($row->artist_id)): ?&gt;
    &lt;?php foreach($this->link_model->getLinksByArtist($row->artist_id) as $link): ?&gt;
      <li><a >href; ?&gt;">&lt;?= $link->title; ?&gt;</a></li>
    &lt;?php endforeach; ?&gt;
  &lt;?php endif; ?&gt;
&lt;?php endforeach; ?&gt;

El Forum

[eluser]manilodisan[/eluser]
you could build an array in the controller (where key is the artist and value is the array with links) with all the data you need and pass it to the view keeping it simple this way.

El Forum

[eluser]crumpet[/eluser]
This is the easiest way to do it for you..
Code:
$data['artists'] = $this->artist_model->getArtists();
foreach($data['artists'] as $artist){
   $data['artists']['links'] = $this->links_model->getLinksByArtist($artist['id']);
}
...but...its not very efficient if you are getting more than one artist because you will do like 10 queries at once. I don't know if its possible to write a join statement that will do it all in one query - its easy to use 2 queries though. Get the artists you want. Then allow getLinksByArtist to take an array of artist ids and for each of those ids create a where statement. This way you get all the links in one query. THen you need a foreach statement to put it all into one array so you access it like $artist['links'] in the view file..

El Forum

[eluser]ray73864[/eluser]
in the model, try something like this (not guaranteed to work but should give you some help).

$this->db->select('a.artist','l.link');
$this->db->from('artist a);
$this->db->join('link l','l.artistid=a.artistid','LEFT JOIN');
$this->db->where('a.id',<artist id>);

this should get all artists and all links for an artist, the artist doesn't necessary have to have any links, if it doesn't it will return no links.

El Forum

[eluser]Unknown[/eluser]
but what about view? is it remain unchanged?

El Forum

[eluser]skeletonfriend[/eluser]
Hey,
Thanks for the replies.

Okey, I could do a join statement, a left join, but how do I loop through all the links in the view if I choose to do it that way? The problem isn't really getting the data from the model...it's how I render it to the view.

As I wrote in my previous post, I did start out with a join statement in a model method named getInfoAboutArtists(), which get potential data from artist_links table and some other tables I haven't mentioned.

Any good ideas on how to render multiple links I might receive with my result?

El Forum

[eluser]gon[/eluser]
If you use a LEFT JOIN, which is my opinion is the right way, you could then process data after the query, and generate two arrays, one for artists, and another one for links.
The trick is that the links array is a hash, having the artist ID as the key.
So then in the view you can iterate through artists, and check if there are links for that artist by looking at the links hash with the ID.

You'll have to iterate the query result, and only store the artist the first time it appears. And the link part of every row be stored in the hash:

Code:
$query = $this->db->QUERY_WITH_JOIN;

$artists = array();
$links = array();

foreach ($query->results_array() as $row) {
   if (!isset($artists[$row['artist_id'])) {
       $artists[] = array('artist_id' => $row['artist_id'],
                          .............  < here you get artist fields of every row
                     );
       $links[$row['artist_id']] = array();
   }
  
   // if it is a LEFT JOIN, there could be no link
   if ($row['link']) {
       $links[$row['artist_id']] = $row['link'];
   }  
}
return array('artists' => $artists, 'links' => $links);

El Forum

[eluser]skeletonfriend[/eluser]
Thank you gon! It works like a charm...this way I only need one query to produce the result which is performance-wise the best way to do it.

Again, thanks for your help.

El Forum

[eluser]skeletonfriend[/eluser]
Hmm...I'm having some troubles here which I can't find the solution to....can anyone of you see what's wrong? What's happening is that this code lists artist with information related to that specific artist, such as albums, links and so forth. The problem is that it's only listing one album and one link, even though there are more of each in the result from the database.

Can you spot the problem?

Model
Code:
function getArtistsAndRelatedInfo()
    {
        $this->db->select('artists.artist_id AS artist_id, artists.title AS title, artists.description AS description, artist_links.title AS link_title, artist_links.href AS link_href, albums.title AS album_title, albums.release_date AS album_release, album_formats.title AS format_title');
        $this->db->from('artists');
        $this->db->join('artist_links', 'artists.artist_id = artist_links.artist_id', 'left');
        $this->db->join('album_artists', 'artists.artist_id = album_artists.artist_id', 'left');
        $this->db->join('albums', 'album_artists.album_id = albums.album_id', 'left');
        $this->db->join('album_formats', 'albums.format_id = album_formats.format_id', 'left');
        $this->db->order_by('artists.title', 'desc');
        $query = $this->db->get();
        
        if ($query->num_rows() > 0)
        {
            // Create necessary arrays
            $artists = array();
            $albums = array();
            $links = array();
            
            // Loop through all artists and them to an array
            foreach ($query->result_array() as $row)
            {
                if (!isset($artists[$row['artist_id']]))
                {
                    $artists[$row['artist_id']] = array(
                                    'artist_id' => $row['artist_id'],
                                    'title' => $row['title'],
                                    'description' => $row['description'],
                                );
                                
                    $albums[$row['artist_id']] = array();
                    $links[$row['artist_id']] = array();
                }
                
                // Is there any albums?
                if ($row['album_title'])
                {
                    $albums[$row['artist_id']] = array(
                                                    'album_title' => $row['album_title'],
                                                    'album_release' => date("Y-m-d", strtotime($row['album_release'])),
                                                    'album_format' => $row['format_title']
                                                );
                }
                
                // Is there any links?
                if ($row['link_title'])
                {
                    $links[$row['artist_id']] = array(
                                                'link_title' => $row['link_title'],
                                                'link_href' => prep_url($row['link_href'])
                                            );
                }
            }
        
            return array('artists' => $artists, 'albums' => $albums, 'links' => $links);
        }
    }

View
Code:
&lt;?php foreach($view_data["artists"] as $artist): ?&gt;

<div class="box artist_entry">
    <div class="box artist_image">
        // Image goes here
    </div>
    
    <div class="box artist_list">
        <div class="pad">
            <h2>&lt;?= $artist["title"]; ?&gt;</h2>
            &lt;?= auto_typography($artist["description"]); ?&gt;
            
            <hr />
    
            &lt;?php if ($view_data["albums"]): ?&gt;
                <dl>
                    <dt>iDEAL Releases</dt>
                    &lt;?php foreach ($view_data["albums"] as $album): ?&gt;
                    <dd>&lt;?= $album["album_title"]; ?&gt; &raquo; </dd>
                    &lt;?php endforeach; ?&gt;
                    
                    &lt;?= print_r($view_data["albums"]); ?&gt;
                </dl>
                
                <hr />
            &lt;?php endif; ?&gt;
        
            &lt;?php if ($view_data["links"]): ?&gt;
                <dl>
                    <dt>Links</dt>
                    &lt;?php foreach ($view_data["links"] as $link): ?&gt;
                    <dd><a href="&lt;?= $link[">&lt;?= $link["link_title"]; ?&gt;</a></dd>
                    &lt;?php endforeach; ?&gt;
                    
                    &lt;?= print_r($view_data["links"]); ?&gt;
                </dl>
            &lt;?php endif; ?&gt;
        </div>
    </div>
</div>

&lt;?php endforeach; ?&gt;

El Forum

[eluser]lmv4321[/eluser]
When you are building the $albums and $links arrays, the code is only saving one value in the array. Change the code to the following and it might work:
Code:
// Is there any albums?
                if ($row['album_title'])
                {
                    $albums[$row['artist_id']][] = array(    // added [] to save multiple
                                                    'album_title' => $row['album_title'],
                                                    'album_release' => date("Y-m-d", strtotime($row['album_release'])),
                                                    'album_format' => $row['format_title']
                                                );
                }
                
                // Is there any links?
                if ($row['link_title'])
                {
                    $links[$row['artist_id']][] = array(    // added [] to save multiple
                                                'link_title' => $row['link_title'],
                                                'link_href' => prep_url($row['link_href'])
                                            );
                }

Give that a try.