Zend_Db Insert and Read

April 17th, 2009

This video is the first in a series on Zend_Db. I start with a looking at insert and read using the Zend_Db_Table classes with a bit of Zend_Db_Select thrown in at the end. Next week will be a followup with update and delete with the help of a custom route, some view partials and a few more additions to our service layer. I’m not a fan of putting business logic in the same object as a class belonging to the Table Data Gateway pattern, so I’ve created a custom UserService object to help seperate the view and model layers. This would also be in keeping if you had multiple service layers (for example, a database, a couple RSS feeds and a couple of web services) and wanted to keep their business logic and querying outside of the Controller. I don’t bother with Zend_Form since it’s configuration heavy and only really interesting in conjunction with validators, however it would fit in perfectly as an extension to this project. The code can be downloaded for this and next weeks episode to help you follow along.

 

20 Responses to “Zend_Db Insert and Read”

  1. James says:

    What do you think of skipping the service class in favor of keeping table-specific logic in the table class itself?

    so more like:
    $users = new UsersTable();
    $users->CreateTestUser();

    Thinking after a few tables, keeping all the CRUD in a single class might be a bit unwieldy, and this is the other approach I’ve seen while researching Zend_Db.

  2. jon says:

    Hey James,

    that’s a great point, however often when you’re managing relationships between tables (e.g. a user with many posts, a post with many tags), then the relationships don’t belong in either table. The “service” layer is a very light version of what Evans’ would call an aggregate root, or an entry point into a domain. The thinking here is that you want to encapsulate the complexity of multiple Zend_Db_Table’s (and perhaps other non-database related data sources) in a class that hides the implementation details from its consumers. Also, if you’re just doing simple CRUD, then the Active Record pattern (implemented in Doctrine as well as Propel) makes more sense since it really works well in handling the simple saves on one table. This pattern falls apart when you need to do joins that are more dynamic, or you need to start aggregating or doing reporting against larger data sets.

    my 2 cents.

  3. James says:

    Interesting. Perhaps a mixture of the two styles would work, simple stuff in the table ($user->CreateTestRecord()), and more complicated / higher level work in the service layer?

    Though a lot of the simple operations (and some more complex ones, as I understand it) should be handled by Zend_Db_Table_Abstract’s magic functions.

    Just thinking in-text here… Assuming you declare all the available tables in the service layer, you could make them publicly available and still have the table functionality ($service->users->CreateTestUser()), while also having the ability to just load the one particular table you need if your action is only working on one table (say, updating a user’s email address).

    Just throwing this out there, I don’t quite have the experience to dictate either way. :)

    Thanks for posting the video, your casts are very helpful.

  4. Arro says:

    very interesting, to have some kind of adapter thing between .. thnx

  5. james says:

    there’s a wider article about service layers and zend here:

    http://www.angryobjects.com/2009/03/30/writing-robust-php-backends-with-zend-framework/

    albeit without the actual demo or code

    just to add, these casts are excellent

  6. kisin says:

    very interesting.

    looking forward for the next webcast about zend_db

  7. Russ says:

    I’m using netbeans if that makes any difference to this problem and maybe my installation needs to be altered, but I’m not sure how. I keep getting the Fatal error: Class ‘UsersTable’ not found when I try the first test.

  8. Tommy says:

    I’m having the same problem as Russ. Is there a way to make it autodetect things in my models folder?

  9. Tommy says:

    More info:
    I already have my include path set to application/models. I think the problem might have something to do with the fact that when you use Zend_Loader it gives you a warning saying it’s outdated, so we’re using Zend_Loader_Autoloader. I had to add a namespace of App_ to the autoloader to get it to load things in library/app, and I’m guessing it’s the same for models, but since there’s no namespace involved it just doesn’t try it. I’m not sure.

  10. Russ says:

    I finally figured out my problem. I went through and did the 1.8 installation and then followed the new quick start guide. In that guide, they use the namespace of Default_Model_ for all of the model classes. Once I updated the respective classes and controller, everything worked great.

  11. Alessio says:

    I’m using the ‘latest version of zend framework 1.9,

    if I want to use the configurations included in the db application.ini what should include in __construct and bootstarp ??

    thanks

  12. spinto says:

    Good work here!!!!

    I´m following the example but i can’t instanciate App_UserService in the controller it throw me a error of class not found . I´m using Zend 1.9. Does anyone have this problem?? Need same help here…. thank you

    Spinto

  13. jon says:

    hey Spinto, it sounds like your not registering your namespace in the bootstrap file. I’ve written about it here on the forum:
    http://www.zendcasts.com/forum/post/65/#p65

  14. rmh23 says:

    Hi im having the same issues with the ‘class not found’. Im using zend 1.8 and have tried Jons method with no avail. I understand the namespace for App in the library folder but its looking for the UsersTable.php in the /library/App/UserService.php when the Userstable.php is located in the modules folder. Any ideas of where I have gone wrong?

  15. Magnus von Bromsen says:

    Thanks for great tutorials.

    ZF is very new for me, so therefor I have this newbee question:

    Why a service layer? Why not put this code for select, insert, update … in the Model?

    Sorry for this dump question ;)

    Regards, Magnus

  16. jon says:

    Hi Magnus,

    The model is a fine place to do this depending on the size of your application. The use of a service layer is likely to make sense if your models are complex or are linked to multiple data sources. In such an instance, you might want to create a service layer that acts as a facade and brokers the commits across multiple persistence mechanisms.

  17. nicola says:

    Hi Jon I’m using the framework 1.9 and following your video tutorial I always get the following error: “Fatal error: Class ‘UsersTable’ not found in C: \ Sites \ zendcast \ library \ App \ UserService.php on line 23″. After reading some articles, I resolved this problem renaming the model’s class: “Model_UsersTable”. Is it correct? Can you tell me if I should do something else?
    thank you for your attention

    Nicola

  18. jon says:

    Hi Nicola,

    Model_* is the default namespace for models in the Zend Framework. I believe I got around it by including the ‘models’ folder in my include paths for that particular video.

  19. nicola says:

    Thanks Jon, I use Zend Studio 7.0, when I create a new Zend Framework project, a bootstrap file is generated.I modified it according your tutorial, but when I include the path of the “models” I always get the above error “Fatal error: Class’ UsersTable ‘not found in C: \ Sites \ zendcast \ library \ App \ UserService.php on line 23 “. Where am I wrong? As I wrote you in my last post, I have to rename the model’s class in order to solve the problem.
    I attach you the bootstrap file:
    bootstrap()
    ->run();
    ?>

  20. nicola says:

    error_reporting(E_ALL||E_STRICT);
    ini_set(’display_error’,'1′);

    // Define path to application directory
    defined(’APPLICATION_PATH’)
    || define(’APPLICATION_PATH’, realpath(dirname(__FILE__).”/../application/” ));

    // Define application environment
    defined(’APPLICATION_ENV’)
    || define(’APPLICATION_ENV’, (getenv(’APPLICATION_ENV’) ? getenv(’APPLICATION_ENV’) : ‘production’));

    // Ensure library/ is on include_path
    set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . ‘/../library’),realpath(APPLICATION_PATH . ‘/models/’),
    get_include_path()
    )));

    /** Zend_Application */
    require_once ‘Zend/Application.php’;

    // Create application, bootstrap, and run
    $application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . ‘/configs/application.ini’
    );
    $application->bootstrap()
    ->run();

Leave a Reply

Desktop RSS feed iPhone + iPod