The Model for NON Database Functions

New topics about Symfony 2 should go here

Moderators: tiagojsag, dcobalt

The Model for NON Database Functions

Postby smugford » Tue Apr 09, 2013 5:55 pm

I have used 1.x forever now and am starting to get a handle on 2.x

what a daunting task converting from 1.x to 2.x is as i'm sure many of you already know.

I have a question about the Model for non database stuff.

in 1.x you had
/lib/model/doctrine/abc.class.php
and
/lib/model/doctrine/abcTable.class.php

All your non database model functions went in abc.class.php and all you database stuff went in abcTable.class.php

I want to add a couple of GD functions to make thumbnails of uploaded images but I'm pretty sure in the MVC conventions they are not suppose to go in the controller file. But I can't find a model folder or any place that even says model for non database stuff anywhere in the docs.

Can someone please let me know what the new convention for "Model" for non database elements are now in Symfony 2

here is one function i'd like to add to the model (or whatever it's called now)

Thanks in advance.
Scott

Code: Select all
    /**
      * Create a thumbnail image from $inputFileName no taller or wider than
      * $maxSize. Returns the new image resource or false on error.
      * Author: mthorn.net
      */
    function thumbnail($inputFileName, $maxSize = 100)
    {
    $info = getimagesize($inputFileName);
     
    $type = isset($info['type']) ? $info['type'] : $info[2];
     
    // Check support of file type
    if ( !(imagetypes() & $type) )
    {
    // Server does not support file type
    return false;
    }
     
    $width = isset($info['width']) ? $info['width'] : $info[0];
    $height = isset($info['height']) ? $info['height'] : $info[1];
     
    // Calculate aspect ratio
    $wRatio = $maxSize / $width;
    $hRatio = $maxSize / $height;
     
    // Using imagecreatefromstring will automatically detect the file type
    $sourceImage = imagecreatefromstring(file_get_contents($inputFileName));
     
    // Calculate a proportional width and height no larger than the max size.
    if ( ($width <= $maxSize) && ($height <= $maxSize) )
    {
    // Input is smaller than thumbnail, do nothing
    return $sourceImage;
    }
    elseif ( ($wRatio * $height) < $maxSize )
    {
    // Image is horizontal
    $tHeight = ceil($wRatio * $height);
    $tWidth = $maxSize;
    }
    else
    {
    // Image is vertical
    $tWidth = ceil($hRatio * $width);
    $tHeight = $maxSize;
    }
     
    $thumb = imagecreatetruecolor($tWidth, $tHeight);
     
    if ( $sourceImage === false )
    {
    // Could not load image
    return false;
    }
     
    // Copy resampled makes a smooth thumbnail
    imagecopyresampled($thumb, $sourceImage, 0, 0, 0, 0, $tWidth, $tHeight, $width, $height);
    imagedestroy($sourceImage);
     
    return $thumb;
    }
     
    /**
      * Save the image to a file. Type is determined from the extension.
      * $quality is only used for jpegs.
      * Author: mthorn.net
      */
    function imageToFile($im, $fileName, $quality = 80)
    {
    if ( !$im || file_exists($fileName) )
    {
    return false;
    }
     
    $ext = strtolower(substr($fileName, strrpos($fileName, '.')));
     
    switch ( $ext )
    {
    case '.gif':
    imagegif($im, $fileName);
    break;
    case '.jpg':
    case '.jpeg':
    imagejpeg($im, $fileName, $quality);
    break;
    case '.png':
    imagepng($im, $fileName);
    break;
    case '.bmp':
    imagewbmp($im, $fileName);
    break;
    default:
    return false;
    }
     
    return true;
    }
     
    $im = thumbnail('temp.jpg', 100);
    imageToFile($im, 'temp-thumbnail.jpg');
User avatar
smugford
Faithful Member
 
Posts: 243
Joined: Sun Nov 29, 2009 8:32 pm

Re: The Model for NON Database Functions

Postby caponica » Wed Apr 10, 2013 4:22 pm

I'd like to see an 'official' reply to what's meant to be done.

In the meantime I would say use the Entity Repository classes ( http://symfony.com/doc/current/book/doc ... ry-classes ) for storing database related code (e.g. like you used to use the XyzTable classes in sf1.x) and use the Entity classes themselves for the non-database things (since these entities are theoretically supposed to be POPOs blithely unaware of any underlying database connection).

I hope that helps!
User avatar
caponica
Senior Member
 
Posts: 118
Joined: Mon Mar 17, 2008 11:25 am
Location: London

Re: The Model for NON Database Functions

Postby smugford » Thu Apr 11, 2013 9:04 pm

ya that helps i put the question to stack overflow and here are the results of this forum and stack overflow

http://stackoverflow.com/questions/15908419/where-is-the-model-for-non-database-functions-in-symfony2/15908965#15908965

"There is not really a convention for this type of stuff per say. You can add the methods to the model, or you can create a separate class that consumes a model and does all of the work that needs to be done.

I personally would create a service that handles the process. Takes the input from the controller, creates the model and the the thumbnails. I would not put the gd functions into my model classes."

So for the thumbnail thing I was asking about creating a service seems to make sense since uploading images is something that would go across entities

For stuff that is specific to the module/bundle putting it in the repository makes sense as well.

I don't know what the "official" answer is all that seems to come to mind is the DRY(Do Not Repeat Yourself) and Thin Controller/Fat Model techniques referred to in http://symfony.com/blog/call-the-expert-a-refactoring-story-part-3-5

I guess the real question is where do the custom functions go so you don't end up repeating code over and over again?

Any ideas, concepts, or theories are more than welcome.
User avatar
smugford
Faithful Member
 
Posts: 243
Joined: Sun Nov 29, 2009 8:32 pm

Re: The Model for NON Database Functions

Postby caponica » Thu Apr 11, 2013 9:59 pm

What do you mean by custom functions?

If it's something like verifyEmail($keycode) then I would say the Entity class itself (or a parent class), so you'd call it with $user->verifyEmail($keycode). Looks like Fred (from SO) would suggest a separate class that you pass the model file to as a parameter, so perhaps you would call it with something like UserManipulator::verifyEmail($user, $keycode) (?)

The benefit of using a separate class is that you could program it up to handle both a $user passed in as either a fully hydrated entity or just an array representation. I've done something similar to this in sf1 when using array hydration for performance.
User avatar
caponica
Senior Member
 
Posts: 118
Joined: Mon Mar 17, 2008 11:25 am
Location: London

Re: The Model for NON Database Functions

Postby smugford » Thu Apr 11, 2013 10:50 pm

Here is an example from my 1.4 app.

in the controller I call it with

$sound = new NotificationType();
$returned_sound = $sound->getCustomSound(0);

Code: Select all
 public static function getCustomSound($value) {
        switch ($value):
            case 0:
                $custom_sound = "cellular.swf";
                break;
            case 1:
                $custom_sound = "reg.swf";
                break;
            case 2:
                $custom_sound = "bing.swf";
                break;
            default:
                $custom_sound = "cellular.swf";
                break;
        endswitch;

        return $custom_sound;
    }


I think repository is the way to go. It looks like instead of having the two files (abc.class.php and abcTable.class.php in 1.x) are now (or can be) combined into one file that is called abcRepository.php

Thanks so much for the answers and clarifications I think go with Model = Repository for now.

Please let me know if that is correct or if i completely missed the mark.
User avatar
smugford
Faithful Member
 
Posts: 243
Joined: Sun Nov 29, 2009 8:32 pm

Re: The Model for NON Database Functions

Postby caponica » Thu Apr 11, 2013 11:25 pm

I really don't think that's right... the Repository is NOT the same as the Model.

The Model in sf1 consisted of an entity class which was split into a (generated) base class and a (developer customised) entity class (e.g. BaseNotificationType and NotificationType) with a separate table class (e.g. NotificationTypeTable).

The Model in Sf2 consists of an entity class (e.g. NotificationType) and a repository class (e.g. NotificationTypeRepository).

So the logical mapping is:
sf1 --> Sf2
BaseXyz --> Xyz
Xyz --> Xyz
XyzTable --> XyzRepository

In other words the BaseNotificationType and NotificationType classes from sf1 are now combined into a single class just called NotificationType.

To me, this seems to be a real PITA. I don't want the class definition/structure to be mixed up with the logic and liked how it used to be separated. I will look into ways to replicate this in Sf2 in future, but my initial quick scan of forums suggest that you could put your custom logic into an (abstract?) 'custom' class and then set your entity class to extend it. I haven't tried doing this yet.

In other words you could have your generated Xyz class and then edit the class definition line, so it becomes:
Code: Select all
class Xyz extends XyzCustom


You can then put your custom logic in XyzCustom:
sf1 --> Sf2
BaseXyz --> Xyz
Xyz --> XyzCustom
XyzTable --> XyzRepository

There should also be a way to over-ride the doctrine entity manager so you can use the old sf1 method of having "class XyzCustom extends Xyz" (in other words Xyz extends BaseXyz), but this is beyond my current knowledge level.

If anybody more experienced in Symfony2 can comment here it would be very useful!
User avatar
caponica
Senior Member
 
Posts: 118
Joined: Mon Mar 17, 2008 11:25 am
Location: London

Re: The Model for NON Database Functions

Postby smugford » Fri Apr 12, 2013 8:18 am

thank you so much for helping me with this. I did a couple hours of googling and finally found this.

Straight from Fabien's Blog
http://fabien.potencier.org/article/49/what-is-symfony2

"Because I really don't care whether Symfony2 is MVC or not. Probably because the MVC word is so overloaded and because nobody implements exactly the same MVC pattern anyway. The separation of concerns is all I care about. And if you like to call Symfony2 an MVC framework, then you should know that Symfony2 is really about providing the tools for the Controller part, the View part, but not the Model part. It's up to you to create your model by hand or use any other tool, like an ORM. Of course, tight integration exists for the most well known ORMs like Doctrine2 and Propel; but they are optional dependencies. The Symfony2 core features do not and will never rely on any ORM."

So basically we we're steered wrong by OLD Symfony Documentation which spends an entire chapter explaining what a MVC is and how important it is. And in reading the blog he is correct no framework implements the MVC the same way.

here are the rest of the relevant links from my googling

http://stackoverflow.com/questions/12045554/autoloading-a-class-in-symfony-2-1

http://richardmiller.co.uk/2012/10/31/symfony2-trimming-fat-from-controllers/

http://stackoverflow.com/questions/9999433/should-everything-really-be-a-bundle-in-symfony-2
The above link is the closest to what I'm use to in the 1.4 version

http://stackoverflow.com/questions/14754627/symfony2-accessing-custom-classes

http://stackoverflow.com/questions/13258169/where-do-model-classes-go-in-symfony2

There seems to be to methods like you found

/src/model or /src/custom etc etc
or
create a service and call the service
User avatar
smugford
Faithful Member
 
Posts: 243
Joined: Sun Nov 29, 2009 8:32 pm


Return to General Symfony 2 discussion

Who is online

Users browsing this forum: No registered users and 6 guests

cron