Note the upgraded forum! If you are experiencing issues logging in, you may need to reset your password which should send an email. If the email doesn't arrive, be sure to check your spam folder just in case.

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 2:20PM
    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 2:20PM
    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 2:20PM
    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 2:20PM
    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 2:20PM
    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 2:20PM
    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 2:20PM
    yes i am,

    the directory is writeable (777)

    please help.
  • edited 2:20PM
    What happens if you substitue {album_name} with a directory you know exists in the assets folder that is writable?
  • edited 2:20PM
    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 2:20PM
    Do you have a field name for your module named "album_name"? It will use that field's value to substitute {album_name}.
  • edited 2:20PM
    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 2:20PM
    please its a bit messy, as i have commented some lines out in order to troubleshoot.

    thanks again
  • edited 2:20PM
    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 2:20PM
    Thank you again. you always come through. It worked thanks.
Sign In or Register to comment.