开发者

How do you overide a class that is called by another class with parent::method

I am trying to extend Mage_Catalog_Block_Product_View I have it setup in my version of it in my local directory and everything works fine, but I wasn't getting the results that I wanted. I then saw that another class extended that class as well. Which seemed to reset whatever got set from my class. I know that my class is working fine and executing. Its just that there is another class that is a child of the same class I am extending and calling parent::method to the same method I am overriding, that class gets executed after my class and when it does that, it is running the original method that I am overriding and not mine

This is the function

class Mage_Review_Block_Product_View extends Mage_Catalog_Block_Product_View
protected function _prepareLayout()
{
    $this->getLayout()->createBlock('catalog/breadcrumbs');
    $headBlock = $this->getLayout()->getBlock('head');
    if ($headBlock) {
        $title = $this->getProduct()->getMetaTitle();
        if ($title) {
            $headBlock->setTitle($title);
        }
        $keyword = $this->getProduct()->getMetaKeyword();
        $currentCategory = Mage::registry('current_category');
        if ($keyword) {
            $headBlock->setKeywords($keyword);
        } elseif($currentCategory) {
            $headBlock->setKeywords($this->getProduct()->getName());
        }
        $description = $this->getProduct()->getMetaDescription();
        if ($description) {
            $headBlock->setDescription( ($description) );
        } else {
            $headBlock->setDescription( $this->getProduct()->getDescription() );
        }
    }

    return parent::_prepareLayout();
}

I am trying to modify it just a bit with the following, keep in mind I know there is a title prefix and suffix but I needed it only for the product page and also I needed to add text to the description.

class MyCompany_Catalog_Block_Product_View extends Mage_Catalog_Block_Product_View
protected function _prepareLayout()
{
    $storeId = Mage::app()->getStore()->getId();
    $this->getLayout()->createBlock('catalog/breadcrumbs');
    $headBlock = $this->getLayout()->getBlock('head');
    if ($headBlock) {
        $title = $this->getProduct()->getMetaTitle();
        if ($title) {
            if($storeId == 2){
                $title = "Pool Supplies Fast - "  .$title;
            $headBlock->setTitle($title);
        }
            $headBlock->setTitle($title);
        }else{
            $path  = Mage::helper('catalog')->getBreadcrumbPath();

            foreach ($path as $name => $breadcrumb) {
                $title[] = $breadcrumb['label'];
            }
             $newTitle = "Pool Supplies Fast - "  . join($this->getTitleSeparator(), array_reverse($title));
            $headBlock->setTitle($newTitle);
        }
        $keyword = $this->getProduct()->getMetaKeyword();
        $currentCategory = Mage::registry('current_category');
        if ($keyword) {
            $headBlock->setKeywords($keyword);
        } elseif($currentCategory) {
            $headBlock->setKeywords($this->getProduct()->getName());
        }
        $description = $this->getProduct()->getMetaDescription();
        if ($description) {
            if($storeId == 2){
                $description = "Pool Supplies Fast - ". $this->getProduct()->getName() . " - " . $description;
                $headBlock->setDescription( ($description) );
            }else{
              $headBlock->setDescription( ($description) );
            }

        } else {
             if($storeId == 2){
                 $description = "Pool Supplies Fast: ". $this->getProduct()->getName() . " - " . $this->getProduct()->getDescription();
                $headBlock->setDescription( ($description) );
            }else{
              $headBlock->setDescription( $this->getProduct()->getDescription() );
            }

        }
    }

    return Mage_Catalog_Block_Product_Abstract::_prepareLayout();
}

This executs fine but then I notice that the following class Mage_Review_Block_Product_View_List extends which extends Mage_Review_Block_Product_View and that extends Mage_Catalog_Block_Product_View as well. Inside this class they call the _prepareLayout as well and call the parent with parent::_prepareLayout()

class Mage_Review_Block_Product_View_List extends Mage_Review_Block_Product_View
protected function _prepareLayout()
{
    parent::_prepareLayout();

    if ($toolbar = $this->getLayout()->g开发者_StackOverflow社区etBlock('product_review_list.toolbar')) {
        $toolbar->setCollection($this->getReviewsCollection());
        $this->setChild('toolbar', $toolbar);
    }

    return $this;
}

So obviously this just calls the same class I am extending and runs the function I am overiding but it doesn't get to my class because it is not in my class hierarchy and since it gets called after my class all the stuff in the parent class override what I have set.

I'm not sure about the best way to extend this type of class and method, there has to be a good way to do this, I keep finding I am running into issues when trying to overide these prepare methods that are derived from the abstract classes, there seems to be so many classes overriding them and calling parent::method.

What is the best way to override these functions?


Your post is a little unclear, but I think you're running into the Magento limitation of only being able to override classes that are at the bottom of the inheritance chain.

Here's how Magento's override system works. I'm going to use models as an example, but it applies to helpers and blocks as well.

When Magento needs to instantiate an overridable class, it doesn't use the new keyword.

$foo = new FooBar();

instead, a static factory method is called on global Mage object.

$foo = Mage::getModel('foo/bar');

What getModel does is turn the string "foo/bar" into an actual class name. It does this based on a series of rules, one of which is to check all module configuration for any overrides. Once the class name is determined, an object is instantiated.

This works decently, but it means you may only override the instantiation of a class. There's no way to override methods on parent classes, as those methods are inherited via the normal PHP mechanism.

Clarification: So, let's say you have a class Foo which extends Bar

class Bar
{
    public function example()
    {
    }
} 

class Foo extends Bar
{
    public function example()
    {
        return parent::example();
    }
}

and you override class Bar with something like

//magento configured ot use Baz in place of Bar
class Baz
{
}

When someone instantiates a Foo object and calls the example method, parent will resolves to class Bar, even though you've overridden class Bar in the Magento config.


are you sure that you have overriden the class correctly ? (I mean putting the <rewrite> tag in config.xml of your module to let magento know you are overriding this class) If yes, please explain in clearer words what you are extending and what you think is not working


There are three options here:

  1. Override all the child classes as well, so that they properly descend from your class (or at least call your class in some way).

  2. Place the parent class into the app/code/local/ folder so that Magento finds it rather than the default one. So you'd create the directory app/code/local/Mage/Catalog/Block/Product/ and copy View.php into it. This would be a problem for upgrades, though, as you'd have to merge in any changes that Varien made to the class.

  3. Abandon the rewrites and change it in the template. This may be the best option of all, as you won't have to worry about changes in the _prepareLayout method.

Hope that helps, Joe

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜