Symfony tutorial: How to make a gallery for admin-module 62

A while ago I’ve read this cool article by Will Linssen on sortable list in jQuery and this inspired me to take it to the next level which is Symfony. This is a tutorial how to make a for example product gallery in Symfony backend admin modules. For this I’m using Symfony 1.4, sfJqueryReloadedPlugin , sfThumbnailPlugin and Doctrine. The main goals we want to achieve here are:

  • every product is able to have many images
  • the images are sortable in desired order
  • we want a drag’n'drop interface to change the order
  • we want to get the embeding of form to minimum

1. The schema

So just to give you an idea let’s get things started. This is how the product might look like:

Product:
  columns:
    name:             { type: string(255), notnull: true }
    description:      { type: blob }
    price:            { type: decimal }

Once again, this is not a final product, I’m just giving you something to work on. Expanding this model is up to you.
So now it’s time for the image:

Image:
  columns:
    name:       { type: string(255), notnull: true }
    image:      { type: string(255), notnull: true }
    ord:        { type: integer }
    product_id: { type: integer }
  relations:
    Product:
      foreignAlias: Images
      local: product_id
      foreign: id
      onDelete: cascade

Now just build all with:

./symfony doctrine:build --all

and generate an admin module for products (I’m assuming that you already have you backend app):

./symfony doctrine:generate-admin backend Product

2. The new image form

Now the thing we want to do is to embed a “add new Image” form in our existing form of Product edition. So go to you lib/form directory and create a class like this one.

// lib/form/BackendEmbedImageForm.class.php
<?php
/**
* Description of BackendEmbedImageForm
*
* @author Karol Sójko <karolsojko@gmail.com>
*/

class BackendEmbedImageForm extends ImageForm
{
  public function configure()
  {
    unset($this['product_id'], $this['ord']);

    $this->widgetSchema['name'] = new sfWidgetFormInput();
    $this->widgetSchema['image'] = new sfWidgetFormInputFileEditable(array(
      'file_src' => sfConfig::get('app_product_pictures_folder') . 'thumbnail/' . $this->getObject()->getImage(),
      'is_image' => true,
      'edit_mode' => !$this->isNew(),
      'template' => '%file% %input%'
    ));

    $this->validatorSchema['name'] = new sfValidatorString();
    $this->validatorSchema['image'] = new sfValidatorFile(array(
      'path' => sfConfig::get('sf_web_dir') . sfConfig::get('app_product_pictures_folder'),
      'required' => false,
      'mime_types' => 'web_images'
    ));
  }
}

As you can see the paths to the folders where the pictures will be stored are defined in the app.yml. This form extends the ImageForm as we don’t want to mess that one up and just keep things nice and clean. And as we want to have some thumbnails let’s override the save function in Image class:


public function save(Doctrine_Connection $conn = null)
{
  if($this->isModified())
  {
    $uploadDir = sfConfig::get('sf_web_dir') . sfConfig::get('app_product_pictures_folder');
    $thumbnail = new sfThumbnail(100, 100);
    $thumbnail->loadFile($uploadDir.'/'.$this->getPhoto());
    $thumbnail->save($uploadDir.'/thumbnail/'. $this->getPhoto());
  }
  return parent::save($conn);
}

3. The Product form

So now we want the product form to embed the new image form and we want to override the bind function to corespond to the changes as well.

// lib/form/doctrine/ProductForm.class.php
<?php
/**
* Product form.
*
* @author     Karol Sójko <karolsojko@gmail.com>
*/
class ProductForm extends BaseProductForm
{
  public function configure()
  {
    $imageForm = new BackendEmbedImageForm();
    $this->embedForm('image', $imageForm);
    $this->widgetSchema['image']->setLabel('New Image');
  }

  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    if (is_null($taintedValues['image']['name']) ||
      strlen($taintedValues['image']['name']) === 0 )
    {
      unset($this->embeddedForms['image'], $taintedValues['image']);
      $this->validatorSchema['image'] = new sfValidatorPass();
    }
    else
    {
      $this->embeddedForms['image']->getObject()->setProduct($this->getObject());
    }
    $output = parent::bind($taintedValues, $taintedFiles);
    foreach ($this->embeddedForms as $name => $form)
    {
      $this->embeddedForms[$name]->isBound = true;
      $this->embeddedForms[$name]->values = $this->values[$name];
    }

    return $output;
  }
}

4. The CSS, jQuery, routing and actions

First of all let’s get some style going on here:

/* web/css/imageList.css */
#info {
display: block;
padding: 10px; margin-bottom: 20px;
background-color: #efefef;
}

#images-list {
list-style: none;
}

#images-list li {
display: block;
padding: 20px 10px; margin-bottom: 3px;
background-color: #efefef;
}

#images-list li img.handle {
margin-right: 20px;
cursor: move;
}

Then let’s install the sfJQueryReloaded plugin. This is very important as we will use the jQuery helper. So now let’s make ourselves some jQuery magic:

// web/js/sortList.js

$(document).ready(function() {
  $("#images-list").sortable({
    handle : '.handle',
    update : function () {
      var order = $('#images-list').sortable('serialize');
      $("#info").load("sort-images?"+order);
    }
  });
});

As you can se we invoke a route sort-images with the load function. So let’s make that route in the routing.yml and let’s add a delete route while we’re at it.

product_sort_images:
  url:  /product/:id/sort-images
  param: { module: product, action: sortImages }

product_delete_image:
  url: /product/:id/delete
  param: { module: product, action: deleteImage }

Here are the coresponding actions:

// backend/modules/product/actions/actions.class.php

public function executeDeleteImage(sfWebRequest $request)
{
  $image = Doctrine::getTable('Image')->findOneById($request->getParameter('id'));
  $image->delete();

  return sfView::NONE;
}

public function executeSortImages(sfWebRequest $request)
{
  foreach($request->getParameter('listItem') as $position => $item)
  {
    $image = Doctrine::getTable('Image')->findOneById($item);
    if($image != null)
    {
      $image->setOrd($position);
      $image->save();
    }
  }

  return sfView::NONE;
}

5. The component

Now let’s make a component that will display all the available images for us. We want to call the component “showImages”, so let’s just add this to the generator.yml.

// backend/modules/product/config/generator.yml
config:

...

form:

  display: [ ~showImages, image, name, description, price ]

Now let’s add a method to the components class in our product module:

// backend/modules/product/actions/components.class.php

public function executeShowImages(sfWebRequest $request)
{
  $productId = $request->getParameter('id');
  $this->images = array();
  if($productId)
  {
    $query = Doctrine_Query::create()->from('Image i')
      ->where('i.product_id = ?', $productId)
      ->orderBy('i.ord ASC');

    $this->images = $query->execute();
  }
}

The reason why i didn’t use the $product->getImages() method is that I want them to be ordered by the ord field. Now let’s create the view for this component:

<?php use_stylesheet('imageList'); ?>
<?php use_javascript('sortList'); ?>
<?php use_helper('jQuery'); ?>

<div id="info"></div>
<div id="imagesList">
  <ul id="images-list">
    <?php foreach ($images as $image): ?>
      <li id="listItem_<?php echo $image->getId(); ?>">
        <img src="/images/arrow.png" alt="move" width="16" height="16" class="handle" />
        <strong><?php echo $image->getName(); ?></strong>
        <?php echo image_tag(sfConfig::get('app_product_pictures_folder') .
          'thumbnail/' . $image->getImage()); ?>
        <?php echo jq_link_to_remote(image_tag('/images/delete.png', array()), array(
          'url' => '@product_delete_image?id=' . $image->getId(),
          'complete' => '$("#listItem_' . $image->getId() . '").hide();',
          ), array('style' => 'background-image: none;')); ?>
      </li>
    <?php endforeach; ?>
  </ul>
</div>

As you can see we use here the jq_link_to_remote function to invoke the delete function with jQuery.

Hope this helps. Share the love :)

62 thoughts on “Symfony tutorial: How to make a gallery for admin-module

  1. Reply dan Dec 4, 2012 12:16 pm

    Hi there,
    this tutorial helped me a lot, so I wanted to share something.
    In the embedded form, when you validate, you may want to set the image field to be required (here showing your unedited version):

    $this->validatorSchema['image'] = new sfValidatorFile(array(
    ‘path’ => sfConfig::get(‘sf_web_dir’) . sfConfig::get(‘app_product_pictures_folder’),
    ‘required’ => false,
    ‘mime_types’ => ‘web_images’
    ));

    if you leave it as it is, and you insert the image name but you don’t choose the file, you get a symfony error.
    If you set that required to true, it won’t complain if you leave both empty, but will just flash “Required” on the file upload element, if you have filled the name field but didn’t choose the file.

    ciao

  2. Reply parpar Nov 17, 2012 11:38 am

    thanks!that was wonderful!..

  3. Reply Tarek Oct 11, 2012 2:20 pm

    I always error message

    The component does not exist: “product”, “showImages”.

    when I access to this application “http://127.0.0.1/symfony/web/backend_dev.php/product/new ”

    can you help me please

    • Reply Karol Sójko Oct 13, 2012 1:26 pm

      Can’t really do much with a description like that – search if you didn’t do a typo (case sensitive typo maybe). It seems to work for everyone else just fine.

  4. Reply best blog Aug 5, 2012 5:32 am

    I have been browsing online more than 2 hours today, yet I never
    found any interesting article like yours. It’s pretty worth enough for me. Personally, if all web owners and bloggers made good content as you did, the net will be a lot more useful than ever before.

  5. Reply asiancoder Jan 26, 2012 4:49 pm

    Hey Karol, I got another question.

    I want to automatically rename my pictures and let them have the name of my article number.

    Do you know how I can achieve this ?

    greets

  6. Reply asiancoder Jan 26, 2012 2:37 am

    Hey, I am trying to implement your image gallery but i am facing the error:

    500 | Internal Server Error | Doctrine_Record_UnknownPropertyException
    Unknown record property / related component “image” on “Image”

    I followed the reply and changed getPhoto() to getImage().

    could you help me on my issue ? I could send you my code if that helps …

    greetings

    • Reply Karol Sójko Jan 26, 2012 9:10 am

      It seems like don’t have an “image” field defined in your model. Please check your classes for that field and the yml model.

      • Reply asiancoder Jan 26, 2012 1:04 pm

        hey, thank you for your answer, but i have an image field in my schema:

        Image:
        columns:
        name: { type: string(255) }
        article_id: { type: integer }
        order: { type: integer }
        metainfo: { type: string(255) }

        the classes are created and inside the database it exists

      • Reply asiancoder Jan 26, 2012 1:16 pm

        Thanks, its working now, you rock man :)

        my 3rd day on symfony, I love it, but if I am honest, i barely understood your code, I couldn’t rebuild that on my own … thanks for sharing!

        you rock!

      • Reply asiancoder Jan 26, 2012 2:28 pm

        hey, I still have a question to your code:

        BackendImageForm.class.php:

        $this->widgetSchema['image'] = new sfWidgetFormInputFileEditable(array(
        ‘file_src’ => sfConfig::get(‘app_product_pictures_folder’) . ‘thumbnail/’ . $this->getObject()->getImage(),
        ‘is_image’ => true,
        ‘edit_mode’ => !$this->isNew(),
        ‘template’ => ‘%file% %input%’
        ));

        isnt ‘thumbnail/’ missing a / at beginning ?

        because here, in the Image class:
        if($this->isModified())
        {
        $uploadDir = sfConfig::get(‘sf_web_dir’) . sfConfig::get(‘app_product_pictures_folder’);
        $thumbnail = new sfThumbnail(100, 100);
        $thumbnail->loadFile($uploadDir.’/’.$this->getPhoto());
        $thumbnail->save($uploadDir.’/thumbnail/’. $this->getPhoto());
        }

        it has one …

  7. Reply JaYmZ Dec 19, 2011 3:45 pm

    Witam.
    Na wstepie – swietny tutorial. Gratuluje.

    Postanowilem wdrozyc Twoje rozwiazanie do mojego skromnego projektu, jednak zetknalem sie z problemem przy zapisie kolejnosci zdjec w ramach wybranej galerii (pozycja w ogole nie jest zapisywana).

    W pliku konfiguracyjnym routing.yml mam wpis postaci:
    modgallery_sort_images:
    url: /gallery/:id/sort-images
    param: { module: gallery, action: sortImages }

    W partalu odpowiedzialnym za wyswietlanie zdjec:

    <li id="listItem_getId(); ?>”>
    __(‘Przesuń’), ‘title’ => __(‘Przesuń’), ‘size’ => ’16×16′, ‘class’ => ‘handle’)) . __(‘Przesuń’) ?>
    getName(); ?>
    __(‘Skasuj’),
    ‘alt’ => __(‘Skasuj’))) . __(‘Skasuj’), array(
    ‘confirm’ => __(‘Czy na pewno chcesz usunąć wybrane zdjęcie?’),
    ‘url’ => ‘@modgallery_delete_image?id=’ . $image->getId(),
    ‘complete’ => ‘$(“#listItem_’ . $image->getId() . ‘”).hide();’,
    ), array(‘style’ => ‘background-image: none;’)); ?>

    Metoda obslugujaca sortowanie zdjec wyglada tak:
    public function executeSortImages(sfWebRequest $request) {
    foreach($request->getParameter(‘listItem’) as $position => $item) {
    $image = Doctrine::getTable(‘Image’)->findOneById($item);
    if($image != null) {
    $image->setOrd($position);
    $image->save();
    }
    }

    return sfView::NONE;
    }

    Jednak nie jest ona wywolywana z poziomu skryptu:
    $(document).ready(function() {
    $(“#images-list”).sortable({
    handle : ‘.handle’,
    update : function () {
    var order = $(‘#images-list’).sortable(‘serialize’);
    $(“#info”).load(“sort-images?”+order);
    }
    });
    });

    Prosilbym o jakies wskazowki, gdzie szukac bledu.
    Bylbym wdzieczny za pomoc.
    Pozdrawiam.

  8. Reply Kuba Jan 13, 2011 3:48 pm

    yes… You right… it’s problem with $productId… Thank You Karol

  9. Reply Kuba Jan 12, 2011 12:28 pm

    Ok so controller of the component “_showImages” is file “component.class.php”. I have there line $this->images = $query->execute();. Component is inculde to layout but all the time I have error… Have You any idea ?

    • Reply Karol Sójko Jan 12, 2011 2:50 pm

      check if your controller enters the if($productId) statement -> maybe the images doesn’t get to be declared. And if it is, try to print out what your $query->execute() returns.

    • Reply Albert St Clair Dec 13, 2011 2:47 pm

      Add $this->images = array(); before the if statement so error does not get thrown if product id is empty and variable is not created.

  10. Reply Kuba Jan 7, 2011 9:17 pm

    Hi Karol…

    I have a problem with:

    Notice: Undefined variable: images in C:\xampp\xampplite\htdocs\Galeria2\apps\backend\modules\product\templates\_showImages.php on line 10

    Can You help me? :)

    • Reply Karol Sójko Jan 7, 2011 8:19 pm

      The variable should be declared and assigned in the controller of the component f.e. $this->images = ……

  11. Reply karol Aug 9, 2010 10:43 pm

    hey,
    i’m wondering, if you want to add more upload fields, you need to:
    1. in ProductFrom -> configure -> add for loop to embed as many forms you wont
    2. … no idea yet
    maybe somebody?

  12. Reply Stephen Jun 29, 2010 3:56 am

    Hi,

    Great tutorial BTW…
    It all seems to be firing up well and am building on the great model.

    I had a question:
    My model is slightly different to yours but the conceptual modelling is similar.
    I’m not clear on how to update the “product_id” of Image with the “id” of Product.
    As you can imagine, to get the images to show at the moment I have to manually add the “product_id” into the table Image.
    What method do you add this and how…?

    Any help greatly appreciated..

    • Reply Karol Sójko Jun 29, 2010 8:46 am

      Not quite sure if I understood correctly but here’s the thing :
      - the Image is in schema defined to have a relation with Product on the field product_id
      - in the product form you’ve got a line in the bind method:

      $this->embeddedForms['image']->getObject()->setProduct($this->getObject());

      - so you’re Image has a getter and setter for the product, which updates the product_id if necessary

      • Reply Stephen Jul 5, 2010 11:37 am

        Hey,

        Thanks for the feedback BTW. i have got it up and running for adding 1 PHOTO.
        I can also edit the other info of the JOB model (the photo is imbedded)
        However , If I add any further images i get the error below:
        SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ’4′ for key ‘PRIMARY’

        It appears from the SQL dump it is attempting to INSERT INTO rather than UPDATE.
        Do you know of a way to make it UPDATE instead..?
        doUpdateObject.?

        Thanks in advance.. :)

  13. Reply oscar Jun 8, 2010 5:21 pm

    Hi,

    first of all, thanks for sharing your knowledge and work.
    I’ve implemented what you explain and have a question:

    The “new image form” should appear directly in the product form (where you fill up the product information)?

    I it does, each time I press save for saving “product information” I have a warning message showing some mandatory fields in the “new image form”. So, each time I want to change a product field, I have to updload and image.

    Did I do something wrong?

    thanks in advance

    • Reply oscar Jun 8, 2010 5:31 pm

      Another thing, where should I put the public function save(Doctrine_Connection $conn = null)
      function?

    • Reply Karol Sójko Jun 8, 2010 5:38 pm

      Check if you have done the binding right. In worst case just make changes to the validators setting required to false.

      • Reply oscar Jun 8, 2010 6:25 pm

        Ok, now is right. Thanks.

        But now, a new problem is coming ;) . Is about the $this->getPhoto() in the save function. I get Unknown record property / related component "photo". should I change it for the name/realname of the image?

      • Reply Karol Sójko Jun 8, 2010 6:29 pm

        yup, you’re right ;) should be ‘getImage’

      • Reply oscar Jun 8, 2010 6:44 pm

        Man, i’m becoming crazy. I’m so sorry of being disturbing you so much.

        Now i get:
        The file "C:\wamp\www\cabanacafe\web/uploads/galerias/e3ed0f7ffdea280893b01c4af719c40a7b173e6d.jpg" is not readable.

        This makes me asking the following: In the thumbnail generation:

        $uploadDir = sfConfig::get('sf_web_dir') . sfConfig::get('app_galeria_images_folder');
        $thumbnail = new sfThumbnail(100, 100);
        $thumbnail->loadFile($uploadDir.'/'.$this-getImage());
        $thumbnail->save($uploadDir.'/thumbnail/'. $this->getImage());

        when calling loadFile, shouldn’t be previously saved the image in $uploadDir? In old fashioned PHP i used to take the image from temp_name.

        I think I’m gonna have some fresh air :@

        one more time, thanks

      • Reply Karol Sójko Jun 8, 2010 6:47 pm

        esnure that the file is in the directory in which the app is looking for it. Make sure as well that you have read write rights on that folder (chmod) ;) . Any further problems please mail me ;)

  14. Reply Goska May 19, 2010 3:51 pm

    Hi Karol,

    Thanks for this post, its very good and helpful! I would highly appreciate your advice on problems I have which are related to your tutorial.

    In bind function the if-loop checks whether a name of an image is given or not:

    if (is_null($taintedValues['image']['name']) || strlen($taintedValues['image']['name']) === 0 )

    But what to do in case when ‘name’ of image is not required and the presence of the file name, so ‘image’ field has to be tested? I thought of something like this:

    if (is_null($taintedFiles['image']['image'])

    but it doesnt work. Do you have any ideas how to solve it?

    The second problem I have is when submitting a form with empty required fields. I get message:
    ‘Notice: Undefined index: image … on line … ‘
    and reference to this line:
    $this->embeddedForms[$name]->values = $this->values[$name];
    Do you know what it could be?

    Thanks for your time,
    Cheers

    • Reply Lyubomir Aug 8, 2010 12:21 pm

      Hallo, Carol!

      This gallery is really well done, but really, if we do not need the name of the picture, the script gives error.

      how can bind() to rewrite to work?

      Thanks.

  15. Reply Iraklis May 5, 2010 1:43 pm

    In the generator.yml I put the display on edit section.

    If I do this, edit doesn’t show “new Image”.

    How can I fix it?

    • Reply Karol Sójko May 5, 2010 1:51 pm

      Go to the dev enviorment by backend_dev.php and check what errors/warnings does it show ? And it always doesn’t hurt to clear cache ;)

      • Reply Iraklis May 5, 2010 4:30 pm

        I think I’m doing something wrong, but I don’t know what.

        I’m in dev mode, my log shows nothing wrong.

        It shows in new item, but doesn’t in edit item :(

        My generator.yml shows like this:

        generator:
        class: sfDoctrineGenerator
        param:
        model_class: noticia
        theme: admin
        non_verbose_templates: true
        with_show: false
        singular: ~
        plural: ~
        route_prefix: noticia
        with_doctrine_route: true
        actions_base_class: sfActions

        config:
        actions: ~
        fields: ~
        list: ~
        filter: ~
        form: ~
        edit:
        display: [ ~muestraAnexos, fecha, title, texto ]
        new: ~

        • Reply Karol Sójko May 5, 2010 6:02 pm

          you have the display section under edit .. try putting it under form (to have it both in new and edit) ;)

          so:

          form:
          display: [ ... ]

      • Reply Iraklis May 5, 2010 8:38 pm

        sigh… I don’t get it…

        If I put on “form:”, It doesn’t show in new neither.

      • Reply Iraklis May 5, 2010 9:07 pm

        LOL I’m so dumb!

        I don’t display in “display:”!!! shiiit!

        A “noticia” has some “anexo”‘s… so…

        display: [ ~muestraAnexos, fecha, title, texto, anexo ]

        xD

        Thanks for your time!

  16. Reply Christian Apr 26, 2010 10:03 pm

    thanks for the great post.
    Erm.. although its shameless selfpromotion but you might want to check out sfImageTransformExtraPlugin instead of sfThumbnail. The separation between design and code will be a lot easier. :)

  17. Pingback: My Bookmarks For January 23rd – April 6th | Cristiano on Tech/Life

  18. Reply Gabor Mar 28, 2010 6:40 pm

    Hi!

    I had this problem:

    Error: $(“#images-list”).sortable is not a function
    Source: http://mywebsite.com/js/sortList.js
    Line: 4

    Apparently, the jquery-ui-1.7.2.custom.min.js that contains the corresponding function – sortable – was not included. Adding the line below solved the problem (found as usage example in the jQueryHelper.php)

    // add this right after use_helper(‘jQuery’)
    echo jq_add_plugins_by_name(array(‘sortable’));

    Interestingly, it seems for me that this is the correct usage. Or did it come with a version change of the helper…?

    • Reply Karol Sójko Mar 28, 2010 7:33 pm

      Hello, thanks for the comment. I had the latest jquery and the jquery-ui included (provided by google) and everything was fine. So you should remember to include those libraries before including your own script. Cheers !

  19. Reply Gabor Mar 28, 2010 6:38 pm

    Hi!

    I had this problem:

    Error: $(“#images-list”).sortable is not a function
    Source: http://mywebsite.com/js/sortList.js
    Line: 4

    Apparently, the jquery-ui-1.7.2.custom.min.js that contains the corresponding function – sortable – was not included. Adding the line below solved the problem (found as usage example in the jQueryHelper.php)

    Interestingly, it seems for me that this is the correct usage. Or did it come with a version change of the helper…?

    • Reply Karol Sójko Apr 18, 2010 11:26 pm

      You have to have a jquery version with all the additional plugins, including sortable

    • Reply Tito May 23, 2010 4:27 pm

      Nice tutorial!
      Been struggling for a few hours, though, until I found out something important: sfJqueryReloadedPlugin is a bit out of date and it is not aware of its own structure!
      So I had to add this in my settings.yml :
      all:
      .settings:
      jquery_web_dir: /sfJqueryReloadedPlugin
      (the default path is /sfJQueryPlugin)
      Like Gabor I couldn’t get the sortable plugin to autoload and I had to use the “jq_add_plugins_by_name(array(‘sortable’));” trick.

      Notice that if anyone wants to use the latest jQuery libs and plugins, they’ll have to download them into their /plugins/sfJqueryReloadedPlugin/web/js and /plugins/sfJqueryReloadedPlugin/web/js/plugin folders and get Symfony to point at them in the setting.yml :
      all:
      .settings:
      jquery_web_dir: /sfJqueryReloadedPlugin
      jquery_core: jquery-1.4.2.min.js
      jquery_sortable: jquery-ui-1.8.2.custom.min.js

      Well, that’s all, folks!

  20. Reply Dunkelheit Mar 4, 2010 1:35 pm

    Very useful, cheers!

  21. Reply Jakub Świeca Feb 24, 2010 3:15 pm

    Problem rozwiązany :) w metodzie save() trzeba dodac parent::save().

    Swietny tutorial!

    Pozdrawiam

  22. Reply Jakub Świeca Feb 24, 2010 2:00 pm

    Witam.

    Zrobiłem wszystko dokładnie z Pana opisem, zdjęcie jest uploadowane, jednak dane nie są zapisywane w tabeli Image. Komponent dziala, bo jak wrzucę coś do tabeli Image to wyświetla się w panelu… Gdzie może być błąd? W formularzu produktu mam embedI18n oraz to co w Pana opisie.

    Pozdrawiam

  23. Reply Sean Feb 22, 2010 11:16 pm

    Hello Karol.

    Thanks for the tutorial, but I can’t get it to work.

    I get an error:

    The component does not exist: “product”, “showImages”.

    I have a few questions, if I may

    1. (Step 5) After I add
    form:
    display: [ ~showImages, image, name, description, price ]
    Do I need to rebuild the project or do anything apart from saving?

    2. I don’t have // backend/modules/product/actions/components.class.php
    Do I just create it?

    3. You say “Now let’s create the view for this component:” Where do I store this and what should the file name be?

    Thank you for your time.

    • Reply Karol Sójko Feb 22, 2010 11:33 pm

      1. No you don’t need to do anything else

      2. You have an error saying that the components doesn’t exist because you don’t have backend/modules/product/actions/components.class.php. Yes you have to create it name the class in it productComponents and make it extend sfComponents, then paste the component I’ve written executeShowImages.

      3. The view is stored in a partial. It’s place is in backend/modules/product/templates/_showImages.php

      Hope this helps :)

  24. Reply andrea Feb 4, 2010 7:07 pm

    you are the best!

    • Reply Karol Sójko Feb 4, 2010 7:25 pm

      thank you :D

      • Reply piotr Mar 9, 2010 9:22 pm

        I’d love to see a final effect, but “Widget ‘image’ does not exist” alert drives me crazy. It shows up after clicking any action (new,edit).. Any suggestions?
        There is a problem in SF_ROOT_DIR\cache\backend\dev\modules\autoProduct\templates\_form_field.php in line 6..

        Byt the way, I’m particularly interested in ajax based tutorials, drag&drop scripts … of course in connection with symfony. If you have some interesting sources, thanks for sharing!

        Ps. język polski mile widziany, chciałem utrzymać międzynarodowy charakter bloga, :)
        Co do powyższego błędu, możliwe, że coś pominąłem, dopiero zaczynam przygodę z symfony. Niemniej jednak utworzyłem wszystkie wymagane pliki, uzupełniłem bazę i wgrałem kilka zdjęć podając uprzednio ścieżkę w pliku app.yml

        • Reply Karol Sójko Mar 9, 2010 9:30 pm

          First of all try clearing the cache : symfony cc

          Then check if you have done everything corectly. The ‘image’ widget is defined in BackendEmbedImageForm so it’s on its place.

          Hope you get it going soon, cheers :)

  25. Reply blogtutorial Feb 2, 2010 7:56 am

    interesting info, thanks

Leave a Reply