How would you approach Projects + Images modules

edited March 2011 in Modules
Hi! I'm getting into Fuel CMS for the first time, and really have a very basic question. I'm set out to build a portfolio site which typically has projects. The projects module, in this case, would be similar to the one provided in the examples, with the difference that I would like to relate/connect records: in this case, images. So I would need a way to add x amount of images to any project.

Then, in the frontend, I would call each project and loop through the project's images and hook it up to a jquery gallery or slider.

How would you approach this? I'm interested in the module approach and in particular, in a way to have infinite amount of images related to that project, then be able to sort those images in the project, or even delete them.

thanks!

Comments

  • edited 3:33PM
    One of the ways we do this is to add the "multifile" class to a file upload field in your model's projects_model::form_field() method like so (this is a code example from another project we did):
    $fields['image'] = array('type' => 'file', 'class' => 'multifile', 'upload_path' => assets_server_path('properties/{type}/{slug}/big/', 'images'));
    This gives us the ability to upload as many images as you want. You'll notice the {type}/{slug} which are placeholders for values that belong to the record. This allows you to upload the images to a folder like assets/images/properties/web/my-fuel-web-project/big/, where "web" is the type associated with the project and "my-fuel-web-project" is the slug value (these placeholder values like 'slug' must not be empty... if they are, you can use the on_before_post model hook to make sure they have a value e.g. $_POST['slug'] =url_title($_POST['name'], 'dash', TRUE);).

    Then to further process the images you can use the model's on_after_post hook. This gives you a place to perhaps rename the images or create thumbnails. I've posted below a snippet of an older project we've used a similar method on that may help (I'm sure there is a better way we could write this now though:):
    function form_fields($values = array()) { $fields = parent::form_fields(); $CI =& get_instance(); $CI->load->model('clients_model'); $client_options = $CI->clients_model->options_list('id', 'name', array('published' => 'yes'), 'name'); $fields['client_id'] = array('label' => 'Client', 'type' => 'select', 'options' => $client_options, 'class' => 'add_edit', 'first_option' => 'Select or Add a Client...'); $fields['project_url']['label'] = 'Project URL'; $fields['featured']['order'] = 9998; $main_image_after_html = ''; $images_after_html = ''; if (!empty($values['id'])) { $project = $this->find_by_key($values['id']); if (!empty($project->main_image)) { $main_image_after_html = '<br /><img src="'.$project->main_image.'" />'; } if (!empty($project->images)) { $assets_arr = array(); foreach($project->images as $thumb => $img) { $name = end(explode('/', $img)); $assets_arr[] = '<a href="'.$img.'"><img src="'.$thumb.'" /></a>'; } $images_after_html = '<br />'.implode(' ', $assets_arr); } } $upload_path = assets_server_path('work/{image_folder}/', 'images'); $fields['main_image_upload'] = array('after_html' => $main_image_after_html, 'filename' => 'work_{image_folder}', 'label' => 'Upload the main image', 'upload_path' => $upload_path, 'type' => 'file', 'overwrite' => TRUE, 'comment' => 'Uploaded a main image associated with this project', 'order' => 9998); $fields['image_upload'] = array('after_html' => $images_after_html, 'label' => 'Upload an image', 'upload_path' => $upload_path, 'type' => 'file', 'class' => 'multifile', 'overwrite' => TRUE, 'comment' => 'Uploaded images associated with this project', 'order' => 9999); $fields['published']['order'] = 10000; unset($fields['permalink']); return $fields; } function on_before_post() { $CI =& get_instance(); if (empty($_POST['name'])){ $CI->load->model('clients_model'); $client = $CI->clients_model->find_by_key($_POST['client_id']); if (!empty($client->name)) { $_POST['name'] = $client->name; } } if (empty($_POST['image_folder'])) { $_POST['image_folder'] = url_title($_POST['name'], 'underline', TRUE); } if (empty($_POST['permalink'])) { if (!empty($_POST['image_folder'])){ $_POST['permalink'] = $_POST['image_folder']; } else { $_POST['permalink'] = url_title($_POST['name'], 'dash', TRUE); } } // hacky... for changing the $_POST[image_upload_path] $asset_folders = $CI->asset->assets_folders; $upload_path = assets_server_path().$asset_folders['images'].'work/'.$_POST['image_folder'].'/'; if (!empty($_FILES)) { foreach($_FILES as $file => $fileinfo) { $_POST[$file.'_upload_path'] = $upload_path; $_POST['main_image_upload_path'] = $upload_path; $_POST['image_upload_path'] = $upload_path; } } } function on_after_post($values) { $CI =& get_instance(); $CI->load->library('image_lib'); $project = $this->find_by_key($values['id']); // process other images $i = 0; foreach($_FILES as $file => $file_info) { if ($file_info['error'] == 0) { $upload_path = assets_server_path($project->get_img_path(), 'images'); if (!file_exists($upload_path)) { mkdir($upload_path, DIR_WRITE_MODE, TRUE); } // filter out for the main image if (strncmp($file, 'main_image_upload', 17) === 0) { $filename_no_ext = $values['main_image_upload_filename']; $ext = 'jpg'; $filename = $values['main_image_upload_filename'].'.'.$ext; $img_folder = $upload_path; $src_img = $upload_path.$filename; // resize to proper dimensions $config = array(); $config['source_image'] = $src_img; $config['create_thumb'] = FALSE; $config['new_image'] = ''; $config['width'] = 160; $config['height'] = 160; $config['master_dim'] = 'auto'; $config['maintain_ratio'] = TRUE; $CI->image_lib->clear(); $CI->image_lib->initialize($config); if (!$CI->image_lib->resize_and_crop()) { $this->add_error($CI->image_lib->display_errors()); } } // filter out all the asset upload files to create the thumbnail if (strncmp($file, 'image_upload', 12) === 0) { $filename = strtolower($file_info['name']); $filename_arr = explode('.', $filename); $filename_no_ext = $filename_arr[0]; $ext = $filename_arr[1]; $img_folder = $upload_path; $src_img = $upload_path.$filename; // resize to proper dimensions $config = array(); $config['source_image'] = $src_img; $config['create_thumb'] = FALSE; $config['new_image'] = ''; $config['width'] = 594; $config['height'] = 472; $config['master_dim'] = 'auto'; $config['maintain_ratio'] = TRUE; $CI->image_lib->clear(); $CI->image_lib->initialize($config); if (!$CI->image_lib->resize()) { $this->add_error($CI->image_lib->display_errors()); } // now create the thumbnail using our resize_and_crop custom addon to the Image_lib CI class $config = array(); $config['source_image'] = $src_img; $config['create_thumb'] = TRUE; $config['thumb_marker'] = '_thumb'; $config['width'] = 73; $config['height'] = 49; $CI->image_lib->clear(); $CI->image_lib->initialize($config); if (!$CI->image_lib->resize()) { $this->add_error($CI->image_lib->display_errors()); } // now move thumb into the thumb directory... but first create thumbnail directory if it doesn't exist $thumb_folder = $upload_path.'thumbs/'; $old_thumb_path = $upload_path.$filename_no_ext.'_thumb.'.$ext; $new_thumb_path = $thumb_folder.$filename_no_ext.'_thumb.'.$ext; if (!file_exists($thumb_folder)) { mkdir($thumb_folder, DIR_WRITE_MODE, TRUE); } @rename($old_thumb_path, $new_thumb_path); } } } return $values; } return $values; }
  • edited 3:33PM
    Dear Admin,

    Please the snippet you posted above is wonderful, but please can you explain it some more, such as:

    $upload_path = assets_server_path('work/{image_folder}/', 'images');

    what is "{image_folder}" how would i implement something similar (that is, how could i make it the name of the album ? say i had a field for album name, how could i get the
    "{image_folder}" and or a variable take on the value of the album field ?)

    $upload_path = assets_server_path($project->get_img_path(), 'images');

    where is the method get_img_path() located or defined ?

    Thanks in advance.

    A nice break down will really aid me in my learning in fuelcms, php and with a project.
  • edited 3:33PM
    The {image_folder} is a placeholder for the $_POST['image_folder'] value, so in your case, you may want to use {album_name} or whatever your fields name is.

    The get_img_path() method is found on the record level class of the project (not shown above).
    class Projects_model extends Base_module_model { //..... PROJECT MODEL CODE GOES HERE INCLUDING THE ABOVE... } class Project_model extends Base_module_record { function get_url() { return site_url('showcase/project/'.$this->slug); } function get_image_path() { return img_path('projects/'.$this->image); } function get_thumb() { $thumb = $this->_parent_model->thumb_name($this->image); return img_path('projects/'.$thumb); } }
  • edited 3:33PM
    Thank you very much.

    This is very interesting. I am enjoying fuel cms big time. I love all the helpers and the optin controller, everything.

    I cant wait till i am good at this.
  • edited 3:33PM
    Dear everyone,

    for some reason this is not working for me

    $thumb_img = assets_server_path('galleries/{album_name}/thumb/'.$data['file_name'], 'images');

    I get make sure the directory or image is wirteable.

    please what do i do ?
  • edited 3:33PM
    Are you literally using {album_name} or is that just as an example? Also, is the directory you are trying to write to "writable"?
  • edited 3:33PM
    yes i am,

    the directory is writeable (777)

    please help.
  • edited 3:33PM
    What happens if you substitue {album_name} with a directory you know exists in the assets folder that is writable?
  • edited 3:33PM
    It works when i substitute {album_name} with a known directory.

    So please how can i get {album_name} to be a working variable ? {album_name} is dynamic.

    {album_name} works when i am not using the image manipulation class.

    Thanks in advance.
  • edited 3:33PM
    Do you have a field name for your module named "album_name"? It will use that field's value to substitute {album_name}.
  • edited 3:33PM
    thanks for your reply.

    but its not working, it is not translating {album_name} to the value stored in it.

    let me post the entire code i have so far


    function form_fields($values = array())
    {
    $fields = parent::form_fields($values);

    $CI =& get_instance();
    $CI->load->model('tn3_gallery_albums_model');
    $_album_options = $CI->tn3_gallery_albums_model->options_list('album_name', 'album_title');
    $fields['album_name'] = array('type' => 'select', 'options' => $_album_options);
    $img_large_upload_path = assets_server_path('galleries/{album_name}/', 'images');
    $fields['img_large'] = array('type' => 'file', 'upload_path' => $img_large_upload_path, 'overwrite' => TRUE);
    //$img_thumb_upload_path = assets_server_path('galleries/{album_name}/thumb/', 'images');
    //$fields['img_thumb'] = array('type' => 'file', 'upload_path' => $img_thumb_upload_path, 'overwrite' => TRUE);

    //$fields['image_thumb_upload'] = array('type' => 'file', 'upload_path' => $upload_path, 'overwrite' => TRUE);
    //$fields['image_large'] = array('type' => 'file', 'class' => 'multifile', 'upload_path' => assets_server_path('galleries/{type}/', 'images'));
    //$fields['img_thumb']['class'] = 'asset_select images/galleries/{album_name}/thumb/';
    //$fields['img_large']['class'] = 'asset_select images/galleries/{album_name}/';
    //$fields['image_upload']['before_html'] = '
    image
    ';
    return $fields;
    }


    function on_after_post($values)
    {
    $CI =& get_instance();
    $CI->load->library('image_lib');

    // create the thumbnail if an image is uploaded
    if (!empty($CI->upload))
    {
    $data = $CI->upload->data();
    if (!empty($data['full_path']))
    {
    //$thumb_img = assets_server_path('galleries/{album_name}/thumb/'.$data['file_name'], 'images');
    $thumb_img = assets_server_path('galleries/{album_name}/'.$this->thumb_name($data['file_name']), 'images');

    // resize to proper dimensions
    $config = array();
    $config['source_image'] = $data['full_path'];
    $config['create_thumb'] = FALSE;
    //$config['new_image'] = $thumb_img;
    $config['width'] = 800;
    $config['height'] = 800;
    $config['master_dim'] = 'auto';
    $config['maintain_ratio'] = TRUE;
    $CI->image_lib->clear();
    $CI->image_lib->initialize($config);
    if (!$CI->image_lib->resize())
    {
    $this->add_error($CI->image_lib->display_errors());
    }

    // create thumb
    $config = array();
    $config['source_image'] = $data['full_path'];
    $config['create_thumb'] = FALSE;
    $config['new_image'] = $thumb_img;
    $config['width'] = 114;
    $config['height'] = 72;
    $config['master_dim'] = 'auto';
    $config['maintain_ratio'] = TRUE;
    $CI->image_lib->clear();
    $CI->image_lib->initialize($config);
    if (!$CI->image_lib->resize())
    {
    $this->add_error($CI->image_lib->display_errors());
    }
    }
    }

    return $values;
    }

    function thumb_name($image)
    {
    return preg_replace('#(.+)(\.jpg|\.png)#U', '$1_thumb$2', $image);
    }
  • edited 3:33PM
    please its a bit messy, as i have commented some lines out in order to troubleshoot.

    thanks again
  • edited 3:33PM
    The value of {album_name} needs to be set in the form_fields() method on a field's value that get's posted. In the example you posted above, that doesn't seem to be the case. Try one of the following:
    $thumb_img = assets_server_path('galleries/'.$CI->input->post('album_name').'/'.$this->thumb_name($data['file_name']), 'images');
    The following is referencing the uploaded path 'album_name_path' $_POST variable that automatically gets created when uploading a file and will have the properly substituted {album_name} value:
    $thumb_img = $CI->input->post('album_name_path').'/'.$this->thumb_name($data['file_name']), 'images');
  • edited 3:33PM
    Thank you again. you always come through. It worked thanks.
Sign In or Register to comment.