findBy() method should returns a new model if fails

[font="Arial"]

Hello

I’ve got a problem with implementing my idea into Yii application.

The idea is:

When I do a find


$shelf = Shelf::model()->with(array('books' => array('condition' => 'price=1')))->findByAttributes(array(

    'active' => '3',  

    'room' => $room

));

and there is an item which matches given parameters => it returns (of course) that item (model),

BUT when there isn’t such one => it should creates a new instance of model Shelf, fills it with some data (i.e. ‘active’ = 0 and so on…) and returns it!

I was planning to do it by afterFind method, but it seems that this method isn’t being called when a find ends with fail (null)

Of course I can do it roughly by:


if(!$shelf)

{

	$shelf=new Shelf();

	$shelf->active = 0;

	$shelf->books = Book:model()->findAllByAttributes(...);

	if(!count($shelf->books))

	{

		$shelf->books = array();

		$shelf->books[0] = Book();

		$shelf->books[0]->name = 'Example';

	}	

}

but it isn’t a nice solution…[/font]

Thanks so much for your help!

Why not just create a static method returning a new model with all filled data you need?




class Shelf extends CActiveRecord

{

    // ...


    public static function createNewShelf()

    {

        $shelf = new Shelf;

        // your code there...

        return $shelf;

    }






$shelf = Shelf::model()->with(array('books' => array('condition' => 'price=1')))->findByAttributes(array(

    'active' => '3',  

    'room' => $room

));

if ($shelf === null)

    $shelf = Shelf::createNewShelf();



But if you want all find methods to return you a new model, then take a look at the populateRecord() method. You can override it as follows:




public function populateRecord($attributes,$callAfterFind=true)

{

    $model = parent::populateRecord($attributes,$callAfterFind);

    if ($model === null)

    {

        $model = new Shelf;

        // your code there...

    }

    return $model

}



Thanks for your help, but it seems that populateRecord method is being called also only when findBy method returns with success.

I’ve added


    public function populateRecord($attributes,$callAfterFind=true)

    {

        $model = parent::populateRecord($attributes,$callAfterFind);

        if ($model === null)

        {

            die();

        }

        return $model;

    }

and it doesn’t die and findBy method returns no results (null).

And yes - I need it to be done with all calls of findBy method. And it’s a bit more complex, so I don’t want to use your first solution

I need to implement this functionality to at least two models, so for example:

when Shelf::findBy method returns null the script should do:


$shelf = new Shelf();

$shelf->books = Book::model()->findBy(...);

and Book:findBy may return null as well, so then it should do:


$book = new Book();

return $book

and this returned $book should be a value of $shelf->books

The idea of use populateRecord will be brilliant, if it is being called even when findBy returns fail, but it isn’t

However, thanks for your ideas.

Looks like populateRecord() isn’t called if with() is used, what’s a surprise for me :)

But you can still override 2 or 3 find methods you need.