首页 > 代码库 > Magento 2 Factory Objects

Magento 2 Factory Objects

In object oriented programming, a factory method is a method that’s used to instantiate an object. Factory methods exist to ensure system developers have control over how a particular object is instantiated, and how its arguments are passed in. There’s a certain school of though that thinks direct use of the new keyword in programming

$object = new Foo;

is an anti-pattern, as directly instantiating an object creates a hard coded dependency in a method. Factory methods give the system owner the ability to control which objects are actually returned in a given context.

A factory object serves a similar purpose. In Magento 2, each CRUD model has a corresponding factory class. All factory class names are the name of the model class, appended with the word “Factory”. So, since our model class is named

Pulsestorm/ToDoCrud/Model/TodoItem

this means our factory class is named

Pulsestorm/ToDoCrud/Model/TodoItemFactory

To get an instance of the factory class, replace your block class with the following.

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php    <?phpnamespace Pulsestorm\ToDoCrud\Block;class Main extends \Magento\Framework\View\Element\Template{    protected $toDoFactory;    public function __construct(        \Magento\Framework\View\Element\Template\Context $context,        \Pulsestorm\ToDoCrud\Model\TodoItemFactory $toDoFactory    )    {        $this->toDoFactory = $toDoFactory;        parent::__construct($context);    }    function _prepareLayout()    {        var_dump(            get_class($this->toDoFactory)        );        exit;    }}

What we’ve done here is use automatic constructor dependency injection to inject a Pulsestorm\ToDoCrud\Model\TodoItemFactory factory object, and assign it to the toDoFactory object property in the constructor method.

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php        protected $toDoFactory;public function __construct(    \Magento\Framework\View\Element\Template\Context $context,    \Pulsestorm\ToDoCrud\Model\TodoItemFactory $toDoFactory){    $this->toDoFactory = $toDoFactory;    parent::__construct($context);}

We also had to inject a block context object and pass that to our parent constructor. We’ll cover these context object in future articles, but if you’re curious about learning more, this quickies post is a good place to start.

In addition to injecting a factory into our block, we also added the following to our _prepareLayout method

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php    function _prepareLayout(){    var_dump(        get_class($this->toDoFactory)    );    exit;}

This will dump the toDoFactory‘s class name to the screen, and is a quick sanity check that our automatic constructor dependency injection worked. Reload your page with the above in place, and you should see the following

string ‘Pulsestorm\ToDoCrud\Model\TodoItemFactory‘ (length=41)

Next, replace your _prepareLayout method with this code

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php    function _prepareLayout(){    $todo = $this->toDoFactory->create();    $todo->setData(‘item_text‘,‘Finish my Magento article‘)    ->save();    var_dump(‘Done‘);    exit;}

This code calls the create method of our factory. This will instantiate a \Pulsestorm\ToDoCrud\Model\TodoItemFactory object for us. Then, we set the item_textproperty of our model, and call its save method. Reload your page to run the above code, and then check your database table

mysql> select * from pulsestorm_todocrud_todoitem\G*************************** 1. row ***************************pulsestorm_todocrud_todoitem_id: 1                      item_text: Finish my Magento article                 date_completed: NULL                  creation_time: NULL                    update_time: NULL                      is_active: 11 row in set (0.00 sec)

You’ll find that Magento has saved the information you requested. If you wanted to fetch this specific model again, you’d use code that looked like the following.

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php        function _prepareLayout(){    $todo = $this->toDoFactory->create();    $todo = $todo->load(1);            var_dump($todo->getData());    exit;}

Here we’ve used the factory to create our model, used the model’s load method to load a model with the ID of 1, and then dumped the model’s data using the various magic setter and getter methods available to a Magento 2 model.

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php        function _prepareLayout(){    $todo = $this->toDoFactory->create();    $todo = $todo->load(1);            var_dump($todo->getData());    var_dump($todo->getItemText());    var_dump($todo->getData(‘item_text‘));    exit;}

Finally, if we wanted to use a CRUD model’s collection object, we’d use code that looked like this

#File: app/code/Pulsestorm/ToDoCrud/Block/Main.php          function _prepareLayout(){    $todo = $this->toDoFactory->create();    $collection = $todo->getCollection();    foreach($collection as $item)    {        var_dump(‘Item ID: ‘ . $item->getId());        var_dump($item->getData());    }    exit;}   

Again, this code uses a factory object to create a CRUD model object. Then, we use the CRUD model object’s getCollection method to fetch the model’s collection. Then, we iterate over the items returned by the collection.

Once instantiated via a factory, Magento 2’s CRUD models behave very similarly, if not identically, to their Magento 1 counterparts. If you’re curious about Magento 1’s CRUD objects, our venerable Magento 1 for PHP MVC Developers article may be of interest, as well as the Varien Data Collections article.

Where did the Factory Come From

You may be thinking to yourself — how did Magento instantiate a Pulsestorm/ToDoCrud/Model/TodoItemFactory class if I never defined one? Factory classes are another instance of Magento 2 using code generation (first covered in our Proxy objectarticle). Whenever Magento’s object manager encounters a class name that ends in the word Factory, it will automatically generate the class in the var/generation folder if the class does not already exist. You can see your generated factory class at the following location

#File: var/generation/Pulsestorm/ToDoCrud/Model/TodoItemFactory.php <?phpnamespace Pulsestorm\ToDoCrud\Model;/** * Factory class for @see \Pulsestorm\ToDoCrud\Model\TodoItem */class TodoItemFactory{    //...}

Magento 2 Factory Objects