views:

121

answers:

3

Hi,
I have an issue that is quite annoying with symfony 1.2 and propel.
I have a model where I have implemented inheritance using the single-table strategy. So, here is an excerpt of my model:
Ad (id, posted_date, description) then RealEstateAd(location, price, transaction_type) and JobAd(position, requirements, company) which inherit both from Ad.

I would like to display all ads, but I would like to display a RealEstateAd differently from a JobAd. To achieve this, I've used a partial for a RealEstateAd and a partial for a JobAd.
So, in the action, I did this:

$c = new Criteria();  
$this->allAds = AdPeer::doSelect($c);

In the template, I check the class of each object:

$add = $allAds[$i];
if ($add instanceof RealEstateAdd)
  //Use the RealEstatePartial

The problem is that class of an object in the $allAds array is sfOutputEscaperObjectDecorator. So, nothing is displayed at all.

How could I deal with this issue? is there a way to get an array with objects which are actually of the class RealEstateAd or JobAd? How is the hydrating process carried out here?

A: 

I don't know much about symfony or propel, so if i'm way off base here i apologize and just ignore this post...

What if you create a helper function getAdType() that uses some methodology to distinguish between the different types of ads.

function getAdType( $ad ) {

    if ( isset( $ad->position ) ) {
        return 'job';
    }
    elseif ( isset( $ad->transaction_type ) ) {
        return 'realestate';
    }

}


$add = $allAds[$i];
if ( getAdType( $add ) == 'realestate' )
    //Use the RealEstatePartial
Galen
That's an interesting option Galen. I finally got that we can get the object class by accessing the decorator undelying objet with the getRawValue() method.
Pattchen
A: 

Hi there,

I might be misunderstanding something, but unless you have overloaded AdPeer::doSelect(), then it will only return an array of instance of Ad.

If you were to post your schema, it would be easier for me or others to help as it is not really clear how you've built your object model. Is RealEstateAd a propel class defined in schema.yml? or is it a custom class you've added to lib?

Eitherway, AdPeer::doSelect* will only return Ad, so it sounds like what you need is a custom retriever in the AdPeer. Again, more info about your schema will help.

JuanD
Hi Juan and thanks for your time. Actually, AdPeer::doSelect() doesn't return Ad objects, but decorators of Ad objects.As gpilotino points out, it's possible to get the underlying object with the getRawValue() method.So, in my example, I can do:$add->getRawValue();and then do the test : if ($rawValue instanceof RealEstateAdd) { //... }
Pattchen
+1  A: 

sfOutputEscaperObjectDecorator has a raw method to get the undelying object.

Anyway, the best thing you can do is to have three different classes (i assume that real estates and job ads are Models)

class Ad { public function __toString() { print 'ad'; } } 

class RealEstates extends Ad { public function __toString() { print 'realad'; } }

class JobAd extends Ad { public function __toString() { print 'jobad'; } }

so you can just call print $myAd; in your view without checking the object types. (use polymorphism luke)

gpilotino
Many thanks gpilotino. $add->getRawValue() works fine.Actually, I have 3 classes in my propel model: Ad, RealEstateAd and JobAd.
Pattchen