Model without table

Published on and tagged with cakephp  faq

It is one of those questions you hear often in the CakePHP channel: “How can I create a model without a table?” The answer is simple:

class ModelWithoutTable extends AppModel
{
    var $useTable = false;
}

Related post: A controller without a model

13 comments baked

  • Mandy

    Thanks cakebaker.

    Maybe you should mention that by doing this you can still take advantage of all the cake’s inbuilt validations like VALID_NOT_EMPTY, VALID_EMAIL, etc…

    -Mandy

  • sviktorov

    using model without table i cool but is it possible to use phpCake without database ?

  • sviktorov

    could we setup phpcake without db?

  • cakebaker

    @sviktorov: Well, you don’t need a database to use CakePHP. If you use models, simply put var $useTable = false; into your AppModel, so that they don’t try to use a database.

    HTH

  • ben

    Using models without corresponding tables in v1.2 makes FormHelper::create() throw up as it ‘automagically’ (I love this term) calls Model::schema().
    The issued warning suggests overriding it with an own schema() function in the model. While this may be a solution in most cases, I can only make my schema() return a bogus array because which fields my ‘dynamic’ model has depends on many things. I have yet to find out any consequences of returning a bogus schema which does not correspond to the actual fields.

  • stupid ben

    pfneuf – after taking a long walk at the sea shore I realized how fixated I was on always creating a form with a model. I came to the point were I thought about that poor other guy who wanted to create a form just to send an email WITHOUT saving the e-mail to the database (how foolish) …
    But then -blam!- cake to the rescue! You can even create a form without a model!
    This can be done by calling $form->create() with a nulled model name like this:
    $form->create(null, array(‘action’ => ‘myFunction’));

    Seeing it written down this seems like trivia – and probably is, too. But after hours staring at the tempdocs nothing seemed obvious to me anymore. So I took off my clothes and took a walk down the shore. I wish everybody had a shore. And that it hadn’t been that cold. Dammit.

  • cakebaker

    @ben: I am glad you found a solution. Another solution is to do it without the helper if there is too much magic.

  • Brad

    But if you want to create a form that validates without connecting to a database, it still throws up the errors. Hrumph.

  • cakebaker

    @Brad: Hm, I just tested it, and it works without any errors (I’m using the latest version from the repository). Here the code I used, first the model:

    class Test extends AppModel {
        var $useTable = false;
        var $validate = array('test' => array('rule' => array('between', 2, 5), 'allowEmpty' => true));
    }
    

    And here the controller action:

    function index() {
        // $data['Test']['test'] = '12345'; // output: ok
        $data['Test']['test'] = '123456'; // output: nok
        $this->Test->set($data);
        if ($this->Test->validates()) {
            echo 'ok';
        } else {
            echo 'nok';
        }
        exit;
    }
    
  • Brian

    Hey all –

    I tried using the example given, but I ran into another problem which I haven’t found a solution to yet: When you specify “var $useTable = false;” it seems you also remove your ability to call other models referenced in the $uses array.

    Exhibit A –

    class ModelWithoutTable extends AppModel {
    var $name = ‘ModelWithoutTable ‘;
    var $useTable = false;
    var $uses = array(‘ModelWithoutTable’,’TableModel’);

    function get_info_from_other_model() {
    return $this->TableModel->field(‘id’,”name = ‘foo'”);
    }
    }

    When $this->TableModel is encountered, Cake throws –
    Notice: Undefined property: ModelWithoutTable::$TableModel

    My reason for having this table-less model is so that I can have one model act as a manager for several other models. I need to access these other models using cake conventions.

    Why not put this in a controller, you ask? I can’t do this because this manager functionality is needed by several different controllers throughout my site. The manager prepares data for interfacing with a third-party tool. I suppose I could make a parent controller class that other classes could be derived from, but really I just want to be able to call the manager class at whim. Also, I don’t think making the manager a Vendor class will work without some ugly hackery.

    Anyway, I hope I was clear in my explanation and I would appreciate any feedback for solving this problem.

    Cheers!

  • cakebaker

    @Brian: var $uses is a controller feature, and hence it doesn’t work in the model (that’s the reason for the notice you get).

    An idea of how it could be solved (I’m not sure I fully understood what you try to accomplish):

    class ModelWithoutTable extends AppModel {
        var $useTable = false;
        var $TableModel = null;
    
        function __construct() {
            App::import('Model', 'TableModel');
            $this->TableModel = new TableModel();
        }
    
        function get_info_from_other_model() {
            return $this->TableModel->field(’id’,”name = ‘foo’”);
        }
    }
    

    Hope that helps!

  • Alan Daniel

    To use it without warnings causeds by the form helper:

    var $useTable = false;	
    function schema($field = false) {
        //your code
    }
    	
    function getColumnType($column) {	
        //your code
    }
  • cakebaker

    @Alan Daniel: Thanks for your comment.

    An alternative to your approach is to define the $_schema variable in your model as descibed in the cookbook.

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License