Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

edit handler CRUD generated question

edited September 2013 in Apps

After I have adapted successfully "add" handler and view I am struggling with "edit".

The module contains several drop-down lists, multi-image field, wysiwyg filed.

In order to have the drop-down list in the "add" handler I add them to "data" in this way:

require_once ('apps/arttypes/lib/Functions.php');
...
$form->data[arttypes] = arttype_list_all ();
$form->data[artcats] = artcat_list_all ();
...

The same thing in the "edit" handler does not work (I get the error: Fatal error: Fatal error: Cannot use object of type articles\Article as array) So I tried this:

require_once ('apps/arttypes/lib/Functions.php');
...
$form->data->arttypes = arttype_list_all ();
$form->data->artcats = artcat_list_all ();
...

In this way I can generate the drop-down lists as before but the record is no longer saved. Believing that this is due to the presence of the arrays of drop-down lists inside "data" which also is unnecessary and burdensome reload from the DB, I did the following:

require_once ('apps/arttypes/lib/Functions.php');
...
if (! $form->submit ()) {
$form->data->arttypes = arttype_list_all ();
$form->data->artcats = artcat_list_all ();
...
};

In this way it seems to work but I'm far from knowing whether it is the right way.

Comments

  • edited September 2013

    I have basically the same question. I've been using the equivalent of $form->data->data['arttypes'] in my edit handler but also far from knowing if it's the right way.

  • The $form->data is an associative array or object that gets passed to the form's view template. Mainly, the contents of $form->data would be your model properties, but can also include other things like lists for drop-downs. Just be sure to name the elements differently so an array for a drop-down list doesn't clobber the property value it's meant to work with.

    For example, suppose there's a category property linking to a Category model, and you want to show a list of categories, just be sure to call that something like categories or category_list so it doesn't overwrite your category value.

    $form->data = new myapp\Article ($_GET['id']);
    // assumes Article has a category property
    
    $form->data->categories = myapp\Category::query ()
        ->order ('name', 'asc')
        ->fetch_assoc ('id', 'name');
    

    And in the view:

    <select name="category">
        <option value="">- select -</option>
    {% foreach categories as cat_id, cat_name %}
        <option value="{{cat_id}}"
            {% if cat_id == $data->category %}selected{% end %}
        >{{cat_name}}</option>
    {% end %}
    </select>
    

    In the default CRUD code, $form->data is an object, so you would use the form $form->data->categories instead of $form->data['categories'] which you would use if $form->data was an array instead of an object.

    Let me know if that helps.

  • Much more clear now although I have not figured out why in the "add" handler (CRUD generated) I used the form $form->data['categories'] succesfully.

  • The difference is in whether you set $form->data to be an array or an object. If you choose to set it as an array, then you would use $form->data['categories'] but if it's an object (like setting $form->data = new myapp\Article) then you would use $form->data->categories to set additional properties.

  • Got it. Thank you.

  • I think I'm still confused about this.

    In my edit handler, I have

    // Get categories
    use categories\Category;
    $q = new Category ();
    $categories = $q::query ()
        ->order ('rank')
        ->fetch_assoc ('id', 'name');
    $form->data->categories = $categories;
    

    However, the same thing in my add handler throws an error ("ErrorException: Creating default object from empty value") unless I change the last line to

    $form->data['categories'] = $categories;
    
  • This is because $form->data is set to false by default, and PHP doesn't implicitly create an object via $a->b = 'value' but it does so with arrays via $a['b'] = 'value'.

    Also, there's no need to create a $q query in your edit handler, just do this:

    $categories = Category::query ()
        ->order ('rank')
        ->fetch_assoc ('id', 'name');
    

    Saves creating an extra object for nothing :)

  • Thanks for the help. I guess I don't need the $categories variable either, because this works fine:

    $form->data->categories = Category::query ()
        ->order ('rank')
        ->fetch_assoc ('id', 'name');
    

    For the object / array question, is it safe to create the data object as an empty product in the add handler? (It's a handler for adding products.)

    $form = new Form ('post', $this);
    $form->data = new products\Product ();
    
    // Get categories
    use categories\Category;
    $form->data->categories = Category::query ()
        ->order ('rank')
        ->fetch_assoc ('id', 'name');
    
  • If you're not pulling any data into it via new products\Product or using it as a Product object later on, then I would opt for new StdClass instead. But that is a totally acceptable way of initializing it as far as I can see :)

  • Thanks. There is a product object created in the echo $form->handle (function ($form) { ... } block that's part of the default crud-app generated add handler, but that object is local to the $form->handle function, I believe. (I'm still not entirely clear how $form->handle does its magic.)

  • Another way to look at the handle(function()... line is like this:

    <?php
    
    $callback = function ($form) {
        // do stuff
    };
    
    echo $form->handle ($callback);
    
    ?>
    

    The function can then be called via call_user_func() inside of the handle() method like this:

    $res = call_user_func ($callback, $this);
    

    Which is how the $form object gets sent to the callback function. Feels a bit like magic, but helps keep things short and organized :)

Sign In or Register to comment.