How do I set up Product Relations i.e Up-sells, Related Products, and Cross-sell Products?

May 1, 2010 by  
Filed under Magento

There are three types of product relations in Magento: Up-sells, Related Products, and Cross-sell Products.  When viewing a product, Upsells for this product are items that your customers would ideally buy instead of the product they’re viewing.  They might be better quality, produce a higher profit margin, be more popular, etc. These appear on the product info page. Related products appear in the product info page as well, in the right column. Related products are meant to be purchased in addition to the item the customer is viewing. Finally, Cross-sell items appear in the shopping cart.  When a customer navigates to the shopping cart (this can happen automatically after adding a product, or not), the cross-sells block displays a selection of items marked as cross-sells to the items already in the cart.  They’re a bit like impulse buys – like magazines and candy at the cash registers in grocery stores.

Up-sells

To add Upsells to a product:

  1. Log in to the Magento admin
  2. Navigate to Catalog -> Manage Products
  3. Find the product to which you want to add Up-sells
  4. Select and edit this product
  5. Select the Up-sells tab
  6. image

  7. From the products grid that appears, check any products you’d like to mark as Up-sells (press “Reset Filter” to see all products)
  8. Once a product has been checked, the “Position” field opens up.  This determines the sort order of the Upsells in the main product’s page
  9. Press “Save”
  10. You’re done! Navigate to the front-end and check out your newly created Upsells block! (shown below)
  11. image
    In the above screenshot, you should assume your customers would rather buy a cup with coffee in it, making it a perfect Upsell.

Related Products

To add related items to a product:

  1. Log in to the Magento admin
  2. Navigate to Catalog -> Manage Products
  3. Find the product you want to add related items to
  4. Select this product to load it for editing
  5. Select the Related Products tab
  6. From the products grid that appears, check any products you’d like to mark as related (press “Reset Filter” to see all products)
  7. Once a product has been checked, the “Position” field opens up.  This determines the sort order of the related products on the main product’s page
  8. Press “Save”
  9. You’re done! Navigate to the front-end and check out your newly created Related products block! (shown below)
  10. image
    In the above screenshot, a coffee cup (with coffee) is a related item.  Also, a Grouped item called “Aerial View” is marked as related. Note that “Aerial View” is missing the checkbox. This is because it is a Configurable Product, and cannot be added using the checkbox, because the configurable attributes must be selected first.

Cross-Sells

Cross-sells display after a product has already been added to the shopping cart.  In this design package, three products are randomly picked from the products that are marked as cross-sells of all the products in the shopping cart.  To add cross-sell items to a product:

  1. Log in to the Magento admin
  2. Navigate to Catalog -> Manage Products
  3. Find the product you want to add cross-sells to
  4. Select and edit this product
  5. Select the Cross-sells tab
  6. From the products grid that appears, check any products you’d like to mark as cross-sells (press “Reset Filter” to see all products)
  7. Once a product has been checked, the “Position” field opens up.  This determines the sort order of the cross-sells in the shopping cart.  If you have multiple products in the cart they are randomly selected, so the sort order will not take effect.
  8. Press “Save”
  9. In the front-end, add the product you just edited to the shopping cart. 
  10. In the shopping cart you should now be able to see the cross-sells in the cross-sell block as shown below:
  11. image

    Ask a doctor for your medical problems free

How do I create an Attribute Set or collection of attributes?

May 1, 2010 by  
Filed under Magento

What’s an attribute set?

 An attribute set is a collection of attributes.  This is definitely easiest to describe with an example.  Let’s say one of your categories is “LCD Displays”.  In addition to the default Magento attributes, you want to show your customers some extra information in the front-end:

 

  • Screen Size
  • Brightness
  • Maximum Resolution

 

You went through the process of creating each of these attributes in the “Attributes Manager”.  If you didn’t, read the tutorial on creating attributes. Now you’re ready to create some LCD Display products.  It would certainly be annoying to have to associate each of these attributes separately to each LCD Display product.  No worries – you don’t have to.

Creating an attribute set

To create an attribute set:

  1. Navigate in the admin to Catalog -> Manage Attribute Sets.
  2. Press “Add New Set” in the top right
  3. The next page let’s you name the set, and base it on another attribute set. A good name might be “LCD Displays”.
  4. Based On: You can select another attribute set as the starting point for the set you’re about to create.  It will take all the attributes from the ‘based on’ set and let you modify this set to create the new one. Select the ‘default’ set for now, and press “Continue.”
  5. The next page is where you actually assign attributes to this set.  The column on the right contains all unassigned attributes – you should see the LCD Display attributes from above in this list.  Press “Add New” on the middle column to create a new “group” within this attribute set.  Groups determine certain display options/sort order in the front-end, and correspond to certain tabs in the product page in the admin.  In this case, naming your group something like “LCD Displays” would make sense. Click the image below for more detail:
  6. image

  7. Your group now appears under “general” in the center column.  Now, drag the LCD attributes from the “Unassigned attributes” column into this group.Click the image below for more detail.
  8. To remove attributes from the center column, simply drag them back to the Unassigned Attributes list to the right. You will not be able to remove System Attributes, marked with a red circle on the icon, but you can remove all other Simple Attributes.
    image

 

You’re done!  Press “Save Attribute Set”.

Note: At this time you cannot change a product’s attribute set after the product has been created.  You can however add or remove attributes from a product set while it’s being used by products.  Do so at your own risk – if you need to remove an attribute, it might be wiser to set it to “Display: No” in the attribute manager.  This way the data is not lost, but the attribute will not display to your customers.

Using Attribute Sets

 

Now you’re ready to create some LCD Display products!  It’s easy as pie:

 

  1. Go to Catalog -> Manage Products
  2. Press “Add Product
  3. Under “Attribute Set,” select the “LCD Displays” set you just created.
  4. image

  5. Since you created a group called “LCD Displays”, you now have a tab called “LCD Displays” in the Product editor page.  Under this tab, the three attributes you added to the group are ready for data entry.  Click the image below for more detail:
  6. image

  7. Save the product!

 

There you have it!  Now to create additional LCD display products, simply follow steps 1-5 above to your hearts content – enjoy!

How do Attributes or any property of a product work in Magento ?

May 1, 2010 by  
Filed under Magento

image
(some sample Magento attributes)

What’s an attribute in Magento?

An attribute in Magento is defined as any property of a product. This includes product id, product title, sku, images, description… everything!  Although this may seem a bit abstract, it’s also one of the most powerful concepts in Magento and provides an almost limitless ability to control the products. We built it like this so that you can add new product attributes without having to write a single line of code.  You also don’t need to add any columns to your database – it’s all done automatically from the attributes manager.  That’s right – you just add the attribute from the admin, and you can start entering data for products using this new attribute.

So why is this good?

We’ll keep it real simple. Your store sells stereos.  Let’s say that when you create a product in Magento, you have to enter title, price and description, as shown below:
image
You decide that customers make important buying decisions based on the manufacturer of the stereo.  No problem – you can add the attribute manufacturer to your store.  After doing so, you’ll see something like this on the product creation page.
image
Note that manufacturer has now been added.

Adding new attributes

A store owner can add as many additional attributes as desired.  These can be grouped into attribute sets, so similar products can be created with the same attributes.  If you sell TV’s, shoes, books, and power tools you could create four attribute sets: one specific to TV’s, one for shoes, one for books, and one for power tools.  When adding new power tool products to your catalog you simply select the “power tool” attribute set, and the appropirate fields are added for this product.  Check out the “creating attributes” tutorial to learn how to do this

How do I know if my server is compatible with Magento?

March 5, 2010 by  
Filed under Magento

In order to run Magento your server needs to meet some basic software requirements. You can test your server for compatibility by following these simple steps:

a. Download this file to your computer and unzip.

b. Upload the php file to your Magento directory on the server

c. In your browser navigate to this page:

/magento-check.php

For a complete list of system requirements please reference this page.

How to open a PHTML file in Dreamweaver

February 6, 2010 by  
Filed under Magento

By default, Dreamweaver cannot read PHTML files. You can add the file type to the “Open in Code View” section of the preferences if you wish to have fast access, however you cannot view the file in design view if you do that. So if you use Dreamweaver (versions 4, MX, MX2004, 8, or 9, aka CS3,CS4) to design your sites, and you wish to open Magento’s Template files (they have .phtml extensions) in Dreamweaver, you can follow these steps to add support for .phtml and make Dreamweaver render PHP code (with coloring, hinting, et al) as well as allow you to see the design in code view if desired. Below are three steps to follow.

IMPORTANT: This tutorial is for Dreamweaver on Windows (XP or Vista) or Mac OS X.

Dreamweaver 4 users: if you are using the archaic Dreamweaver 4, you only need to follow step one. However, it’s highly recommended that you just upgrade to version 8, CS3 or newer for superb CSS and Web Standards support.

Vista may need to edit files by running notepad as Administrator; however this requirement is not common and if encountered, may be avoidable by following these steps after a fresh restart. However, if unavoidable, simply go to Start > All Programs > Accessories, and then right click on Notepad and select “Run as Administrator”. Once notepad is open, use File > Open to browse to the applicable file before making the necessary changes.

Step One: Add .phtml to extension.txt in your Application Data

Open the following extension configuration file in a notepad and change the lines as specified below:

XP: Documents and Settings > [user] > Application Data > Adobe Dreamweaver > Configuration > extensions.txt

NOTE: If you cannot see the Application Data Folder, go to Tools → Folder Options → View and make sure that Show Hidden Files and Folders is checked.

Vista: Users > [user] > AppData > Roaming > Adobe > Dreamweaver 9 > Configuration > Extensions.txt

Mac OS X: Users > [Home Folder] >Library > Application Support > Adobe > Dreamweaver [Your Version] > [en_US or other locale (only for version CS4)] > Configuration > Extensions.txt

In the first line add PHTML like so:
HTM,HTML,SHTM,SHTML, … ,TXT,PHP,PHP3,PHP4,PHP5,PHTML,JSP,WML,TPL, … ,MASTER:All Documents

In the PHP Files line add PHTML like so:

PHP,PHP3,PHP4,PHP5,TPL,PHTML:PHP Files

Step Two
: Add .phtml to the extension.txt configuration file

This file is pretty much exactly like the extensions.txt file located in Dreamweaver’s Application Data folder, except it is in Dreamweaver’s Program Files folder, inside a configuration folder. Just as in Step One, find the file and change the lines as specified below.

XP, Vista: Program Files > Adobe > Dreamweaver [Your Version] > configuration > Extensions.txt

XP, Vista: Program Files > Adobe > Dreamweaver [Your Version] > configuration > Extensions.txt

Mac OS X: Applications > Adobe Dreamweaver [Your Version] > configuration > Extensions.txt
In the first line add PHTML like so:

HTM,HTML,SHTM,SHTML, … ,TXT,PHP,PHP3,PHP4,PHP5,PHTML,JSP,WML,TPL, … ,MASTER:All Documents
In the PHP Files line add PHTML like so:

PHP,PHP3,PHP4,PHP5,TPL,PHTML:PHP Files
Step Three: Add PHTML to MMDocumentTypes.xml

This will apply your php code coloring settings to your phtml files This file is an XML file which should be located in:

XP, Vista: Program Files > Adobe > Dreamweaver [Your Version] > configuration > DocumentTypes > MMDocumentTypes.xml

Mac OS X: Applications > Adobe Dreamweaver [Your Version] > configuration > DocumentTypes > MMDocumentTypes.XML

Note: Dreamweaver 8 users on Windows may also need to apply these changes to: C:Program Files > Macromedia > Dreamweaver 8 > Configuration > Document Types > MMDocumentTypes.xml

Note: In Windows 7/Vista you may need to update the file permissions under Properties>Security tab in order to save your changes to the file

Source : Magento Wiki

Magento Models and Object Relational Mapping Basics

January 17, 2010 by  
Filed under Magento

The implementation of a “Models Tier” is a huge part of any MVC framework. It represents the data of your application, and most applications are useless without data. Magento Models play an even bigger role, as they typically contain the “Business Logic” that’s often (right or wrong) relegated to the Controller or Helper methods in other PHP MVC frameworks.

The following is part of a longer series about Magento aimed at developers familiar with PHP MVC development. While each article can be read stand alone, each article does build on concepts covered in previous articles. If you’re confused, be sure to catch up on the older stuff first.

Traditional PHP MVC Models

If the definition of MVC is somewhat fuzzy, the definition of a Model is even fuzzier. Prior to the wide adoption of the MVC pattern by PHP developers, data access was usually raw SQL statements and/or a SQL abstraction layer (such as AdoDB). Developers would write queries and not think too much about that objects they were modeling.

In 2009 raw SQL is mostly frowned upon, but many PHP frameworks are still SQL centric. Models will be objects that provide some layer of abstraction, but behind the scenes developers are still writing SQL and/or calling SQL like abstraction methods to read and write-down their data.

Other frameworks eschew SQL and take the Object Relational Mapping (ORM) approach. Here, a developer is dealing strictly with Objects. Properties are set, and when a save method is called on the Object, the data is automatically written to the database. Some ORMs will attempt to divine object properties from the database, others require the user to specify them in some way, (usually in an abstract data language such as YAML). One of the most famous and popular implementations of this approach is ActiveRecord.

This definition of ORM should suffice for now, but like everything Computer Science these days, the strict definition of ORM has blurred over the years. It’s beyond the scope of this article to settle that dispute, but suffice it say I’m generalizing a bit and probably asking to be jumped by a couple of Java developers when I leave the house.

Magento Models

It should be no surprise that Magento takes the ORM approach. While the Zend Framework SQL abstractions are available, most of your data access will be via the built in Magento Models, and Models you build yourself. It should also come as no surprise that Magento has a highly flexible, highly abstract, sometimes confusing concept of what a Model is.

Anatomy of a Magento Model

Most Magento Models can categorized in one of two way. There’s a basic, ActiveRecord-like/one-object-one-table Model, and there’s also an Entity Attribute Value (EAV) Model. There’s also Model Collections. Collections are PHP objects used to hold a number of individual Magento Model instances. The Varien team has implemented the PHP Standard Library interfaces of IteratorAggregate and Countable to allow each Model type to have it’s own collection type. If you’re not familiar with the PHP Standard Library, think of Model Collections as arrays that also have methods attached.

Magento Models don’t contain any code for connecting to the database. Instead, each Model has two modelResouces, (one read, one write), that are used to communicate with the database server (via read and write adapter objects). By decoupling the logical Model and the code that talks to the database, it’s theoretically possible to write new resource classes for a different database platform while keeping your Models themselves untouched.

Creating a Basic Model
To begin, we’re going to create a basic Magento Model. PHP MVC tradition insists we model a weblog post. The steps we’ll need to take are

1.Crete a new “Weblog” module

2.Create a database table for our Model

3.Add Model information to the config for a Model named Blogpost

4.Add Model Resource information to the config for the Blogpost Model

5.Add A Read Adapter to the config for the Blogpost Model

6.Add A Write Adapter to the config for the Blogpost Model

7.Add a PHP class file for the Blogpost Model

8.Add a PHP class file for the Blogpost Model

9.Instantiate the Model

Create a Weblog Module

You should be an old hat at creating empty modules at this point, so I’ll skip the details and assume you can create an empty module named Weblog. After you’ve done that, we’ll setup a route for an index Action Controller with an action named “testModel”. As always, the following examples assume a Package Name of “Alanstormdotcom”.

In Alanstormdotcom/Weblog/etc/config.xml, setup the following route

standard

Alanstormdotcom_Weblog

weblog

And then add the following Action Controller in

class Alanstormdotcom_Weblog_IndexController extends Mage_Core_Controller_Front_Action {

public function testModelAction() {

echo ‘Setup!’;

}

}

at Alanstormdotcom/Weblog/controllers/IndexController.php. Clear your Magento cache and load the following URL to ensure everything’s been setup correctly.

http://example.com/weblog/index/testModel

You should see the word “Setup” on a white background.

Creating the Database Table

Magento has a system for automatically creating and changing your database schemas, but for the time being we’ll just manually create a table for our Model.

Using the command-line or your favorite MySQL GUI application, create a table with the following schema

CREATE TABLE `blog_posts` (

`blogpost_id` int(11) NOT NULL auto_increment,

`title` text,

`post` text,

`date` datetime default NULL,

`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,

PRIMARY KEY (`blogpost_id`)

)

And then populate it with some data

INSERT INTO `blog_posts` VALUES (1,’My New Title’,'This is a blog post’,’2009-07-01 00:00:00′,’2009-07-02 23:12:30′);

The Global Config and Creating The Model

There are four individual things we need to setup for a Model in our config.

1.Enabling Models in our Module

2.Enabling Model Resources in our Module

3.Add an “entity” to our Model Resource. For simple Models, this is the name of the table

4.Specifying a Read Adapter for our specific Model Resource

5.Specifying a Write Adapter for our specific Model Resource

When you instantiate a Model in Magento, you make a call like this

$model = Mage::getModel(‘weblog/blogpost’);

The first part of the URI you pass into get Model is the Model Group Name. Because of the way Magento __autoloads classes, this also has to be the (lowercase) name of your module. The second part of the URI is the lowercase version of your Model name.

So, let’s add the following XML to our module’s config.xml.

Alanstormdotcom_Weblog_Model

weblog_mysql4

The outer tag is your Group Name, which should match your module name. is the BASE name all Models in the weblog group will have. The tag indicates which Resource Model that weblog group Models should use. There’s more on this below, but for now be content to know it’s your Group Name, followed by a the literal string “mysql4”.

So, we’re not done yet, but let’s see what happens if we clear our Magento cache and attempt to instantiate a blogpost Model. In your testModelAction method, use the following code

public function testModelAction() {

$blogpost = Mage::getModel(‘weblog/blogpost’);

echo get_class($blogpost);

}

and reload your page. You should see an exception that looks something like this (be sure you’ve turned on developer mode).

include(Alanstormdotcom/Weblog/Model/Blogpost.php) [function.include]: failed to open stream: No such file or directory
By attempting to retrieve a weblog/blogpost Model, you told Magento to instantiate a class with the name

Alanstormdotcom_Weblog_Model_Blogpost

Magento is trying to __autoload include this Model, but can’t find the file. Let’s create it! Create the following class at the following location

File: app/code/local/Alanstormdotcom/Weblog/Model/Blogpost.php

class Alanstormdotcom_Weblog_Model_Blogpost extends Mage_Core_Model_Abstract

{

protected function _construct()

{

$this->_init(‘weblog/blogpost’);

}

}

Reload your page, and the exception should be replaced with the name of your class.

All basic Models should extend the Mage_Core_Model_Abstract class. This abstract class forces you to implement a single method named _construct (NOTE: this is not PHP’s constructor __consutrct). This method should call the class’s _init method with the same identifying URI you’ll be using in the Mage::getModel method call.

The Global Config and Resources

So, we’ve setup our Model. Next, we need to setup our Model Resource. Model Resources contain the code that actually talks to our database. In the last section, we included the following in our config.

weblog_mysql4

The value in will be used to instantiate a Model Resource class. Although you’ll never need to call it yourself, when any Model in the weblog group needs to talk to the database, Magento will make the following method call to get the Model resource

Mage::getResourceModel(‘weblog/blogpost’);

Again, weblog is the Group Name, and blogpost is the Model. The Mage::getResourceModel method will use the weblog/blogpost URI to inspect the global config and pull out the value in (in this case, weblog_mysql4). Then, a model class will be instantiated with the following URI

weblog_mysql4/blogpost

So, if you followed that all the way, what this means is, resource models are configured in the same section of the XML config as normal Models. This can be confusing to newcomers and old-hands alike.

So, with that in mind, let’s configure our resource. In our section add

Alanstormdotcom_Weblog_Model_Mysql4

You’re adding the tag, which is the value of the tag you just setup. The value of is the base name that all your resource modes will have, and should be named with the following format

Packagename_Modulename_Model_Mysql4

So, we have a configured resource, let’s try loading up some Model data. Change your action to look like the following

public function testModelAction() {

$params = $this->getRequest()->getParams();

$blogpost = Mage::getModel(‘weblog/blogpost’);

echo(“Loading the blogpost with an ID of “.$params['id']);

$blogpost->load($params['id']);

$data = $blogpost->getData();

var_dump($data);

}

And then load the following URL in your browser (after clearing your Magento cache)

http://example.com/weblog/index/testModel/id/1

You should see an exception something like the following

Warning: include(Alanstormdotcom/Weblog/Model/Mysql4/Blogpost.php) [function.include]: failed to open stream: No such file ….
As you’ve likely intuited, we need to add a resource class for our Model. Every Model has its own resource class. Add the following class at at the following location

File: app/code/local/Alanstormdotcom/Weblog/Model/Mysql4/Blogpost.php

class Alanstormdotcom_Weblog_Model_Mysql4_Blogpost extends Mage_Core_Model_Mysql4_Abstract{

protected function _construct()

{

$this->_init(‘weblog/blogpost’, ‘blogpost_id’);

}

}

Again, the first parameter of the init method is the URL used to identify the Model. The second parameter is the database field that uniquely identifies any particular column. In most cases, this should be the primary key. Clear your cache, reload, and you should see

Loading the blogpost with an ID of 1

array

empty

So, we’ve gotten things to the point where there’s no exception, but we’re still not reading from the database. What gives?

Each Model group has a read adapter (for reading from the database) and a write adapter (for updating the database). Magento allows a Model to use the default adapter, or for developers to write their own. Either way, we need tell Magento about it. We’ll be adding a new tag section named to the section of our module config.

core_write

core_read

We’re adding two sub-sections to . One for writing, and one for reading. The tag names ( and ) are based on the Group Name we defined above (“weblog”).

OK, surely with our adapter’s in place we’re ready. Let’s clear our cache, reload the the page, and …

Can’t retrieve entity config: weblog/blogpost

Another exception! When we use the Model URI weblog/blogpost, we’re telling Magneto we want the Model Group weblog, and the blogpost Entity. In the context of simple Models that extend Mage_Core_Model_Mysql4_Abstract, an entity corresponds to a table. In this case, the table named blog_post that we created above. Let’s add that entity to our XML config.

Alanstormdotcom_Weblog_Model_Mysql4

blog_posts

We’ve added a new section to the resource Model section of our config. This, in turn, has a section named after our entity () that specifies the name of the database table we want to use for this Model.

Clear your Magento cache, cross your fingers, reload the page and …

Loading the blogpost with an ID of 2

Loading the blogpost with an ID of 1

array

‘blogpost_id’ => string ’1′ (length=1)

‘title’ => string ‘My New Title’ (length=12)

‘post’ => string ‘This is a blog post’ (length=19)

‘date’ => string ’2009-07-01 00:00:00′ (length=19)

‘timestamp’ => string ’2009-07-02 16:12:30′ (length=19)

Eureka! We’ve managed to extract our data and, more importantly, completely configure a Magento Model.

Basic Model Operations

All Magento Models inherit from the the Varien_Object class. This class is part of the Magento system library and not part of any Magento core module. You can find this object at

lib/Varien/Object.php

Magento Models store their data in a protected _data property. The Varian_Object class gives us several methods we can use to extract this data. You’ve already seen getData, which will return an array of key/value pairs. This method can also be passed a string key to get a specific field.

$model->getData();

$model->getData(‘title’);

There’s also a getOrigData method, which will return the Model data as it was when the object was initially populated, (working with the protected _origData method).

$model->getOrigData();

$model->getOrigData(‘title’);

The Varien_Object also implements some special methods via PHP’s magic __call method. You can get, set, unset, or check for the existence of any property using a method that begins with the word get, set, unset or has and is followed by the camel cased name of a property.

$model->getBlogpostId();

$model->setBlogpostId(25);

$model->unsetBlogpostId();

if($model->hasBlogpostId()){…}

For this reason, you’ll want to name all your database columns with lower case characters and use underscores to separate characters. More recent version of Magento have depreciated this syntax in favor of implementing the PHP ArrayAccess interface

$id = $model->['blogpost_id'];

$model->['blogpost_id'] = 25;

//etc…

That said, you’re likely to see both techniques used throughout the Magento code base, as well as third party extensions.

CRUD, the Magento Way

Magento Models support the basic Create, Read, Update, and Delete functionality of CRUD with load, save, and delete methods. You’ve already seen the load method in action. When passed a single parameter, the load method will return a record whose id field (set in the Model’s resource) matches the passed in value.

$blogpost->load(1);

The save method will allow you to both INSERT a new Model into the database, or UPDATE an existing one. Add the following method to your Controller

public function createNewPostAction() {

$blogpost = Mage::getModel(‘weblog/blogpost’);

$blogpost->setTitle(‘Code Post!’);

$blogpost->setPost(‘This post was created from code!’);

$blogpost->save();

echo ‘post created’;

}

and then execute your Controller Action by loading the following URL

http://example.com/weblog/index/createNewPost

You should now see an additional saved post in you database table. Next, try the following to edit your post

public function editFirstPostAction() {

$blogpost = Mage::getModel(‘weblog/blogpost’);

$blogpost->load(1);

$blogpost->setTitle(“The First post!”);

$blogpost->save();

echo ‘post edited’;

}

And finally, you can delete your post using very similar syntax.

public function deleteFirstPostAction() {

$blogpost = Mage::getModel(‘weblog/blogpost’);

$blogpost->load(1);

$blogpost->delete();

echo ‘post removed’;

}

Model Collections

So, having a single Model is useful, but sometimes we want to grab list of Models. Rather than returning a simple array of Models, each Magento Model type has a unique collection object associated with it. These objects implement the PHP IteratorAggregate and Countable interfaces, which means they can be passed to the count function, and used in for each constructs.

We’ll cover Collections in full in a later article, but for now let’s look at basic setup and usage. Add the following action method to your Controller, and load it in your browser.

public function showAllBlogPostsAction() {

$posts = Mage::getModel(‘weblog/blogpost’)->getCollection();

foreach($posts as $blog_post){

echo ‘

‘.$blog_post->getTitle().’

‘;

echo nl2br($blog_post->getPost());

}

}

Load the action URL,

http://example.com/weblog/index/showAllBlogPosts

and you should see a (by now) familiar exception.

Warning: include(Alanstormdotcom/Weblog/Model/Mysql4/Blogpost/Collection.php) [function.include]: failed to open stream
You’re not surprised, are you? We need to add a PHP class file that defines our Blogpost collection. Every Model has a protected property named _resourceCollectionName that contains a URI that’s used to identify our collection.

protected ‘_resourceCollectionName’ => string ‘weblog/blogpost_collection’
By default, this is the same URI that’s used to identify our Resource Model, with the string “_collection” appended to the end. Magento considers Collections part of the Resource, so this URI is converted into the class name

Alanstorm_Weblog_Model_Mysql4_Blogpost_Collection

Add the following PHP class at the following location

File: app/code/local/Alanstormdotcom/Weblog/Model/Mysql4/Blogpost/Collection.php

class Alanstormdotcom_Weblog_Model_Mysql4_Blogpost_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {

protected function _construct()

{

$this->_init(‘weblog/blogpost’);

}

}

Just as with our other classes, we need to init our Collection with the Model URI. (weblog/blogpost). Rerun your Controller Action, and you should see your post information.

Wrapup and a Quick Note on Core Magento Models
Congratulations, you’ve created and configured you first Magento Model. In a later article we’ll take a look at Magento’s Entity Attribute Value Models (EAV), which expand on what we’ve learned here.

Also, there’s a little fib we had to tell you earlier. In this article we indicated that all basic Magento Models inherit from Mage_Core_Model_Abstract. This isn’t 100% true. This Abstract method hasn’t existed for Magento’s entire life, and there are still many Models in the system that inherit directly from Varien_Object. While this shouldn’t affect any Models you create, it is something you’ll want to be aware of while working with Magento code.

Magento Controller Dispatch and Hello World

January 17, 2010 by  
Filed under Magento

The Model-View-Controller (MVC) architecture traces its origins back to the Smalltalk Programming language and Xerox Parc. Since then there have been many systems that describe their architecture as MVC. Each system is slightly different, but all have the goal of separating data access, business logic and user-interface code from one another.

The architecture of most PHP MVC frameworks will look something like this.

1.A URL is intercepted by a single PHP file (usually called a Front Controller)

2.This PHP file will examine the URL, and derive a controller name and an action name (a process that’s often called routing)

3.The derived controller is instantiated

4.The method name matching the derived action name is called on the controller

5.This action method will instantiate and call methods on models, depending on the request variables

6.The action method will also prepare a data structure of information, which is passed on to the view

7.The view then renders HTML, using the information in the data structure it has received from the controller

While this pattern was a great leap forward from the “each php file is a page” pattern established early on, for some software engineers, it’s still a hack. Common complaints are

•The Front Controller PHP file still operates in the global namespace

•Convention over configuration leads to less modularity.

◦URLs routing is often inflexible

◦Controllers are often bound to specific views

◦Even when a system offers a way to override these defaults, the convention leads to applications where it’s difficult/impossible to drop in new a new model, view, or controller implementation without massive re-factoring.

As you’ve probably guessed, the Magento team shares this world view and has created a more abstract MVC pattern that looks something like this.

1.A URL is intercepted by a single PHP file

2.This PHP file instantiates a Magento application

3.The Magento application instantiates a Front Controller object

4.Front Controller instantiates any number of Router objects (specified in global config)

5.Routers check the request URL for a “match”

6.If a match is found, an Action Controller and Action are derived

7.Action Controller is instantiated and the method name matching the Action Name is called

8.This action method will instantiate and call methods on models, depending on the request

9.This Action Controller will then instantiate a Layout Object

10.This Layout Object will, based some request variables and system properties (also known as “handles”), create a list of Block objects that are valid for this request

11.Layout will also call an output method on certain Block objects, which start a nested rendering (Blocks will include other Blocks)

12.Each Block has a corresponding Template file. Blocks contain PHP logic, templates contain HTML and PHP output code

13.Blocks refer directly back to the models for their data. In other words, the Action Controller does not pass them a data structure

We’ll eventually touch on each part of this request, but for now we’re concerned with the Front Controller -> Routers -> Action Controller section

Hello World

Enough theory, it’s time for Hello World. We’re going to

1.Create a Hello World module in the Magento system

2.Configure this module with routes

3.Create Action Controller(s) for our routes

Create Hello World Module

First, as we did before, we’ll create a directory structure for this module

app/code/local/Alanstormdotcom/Helloworld/Block

app/code/local/Alanstormdotcom/Helloworld/controllers

app/code/local/Alanstormdotcom/Helloworld/etc

app/code/local/Alanstormdotcom/Helloworld/Helper

app/code/local/Alanstormdotcom/Helloworld/Model

app/code/local/Alanstormdotcom/Helloworld/sql

and then a configuration file (config.xml) for the module

PATH: app/code/local/Alanstormdotcom/Helloworld/etc/config.xml

0.1.0

and a file to activate the module

PATH: app/etc/modules/Alanstormdotcom_Helloworld.xml

true

local

Finally, ensure the module is active

1.Clear your Magento cache

2.In the Magento Admin, go to

System->Configuration->Advanced

3.Expand “Disable Modules Output” (if it isn’t already)

4.Ensure that Alanstormdotcom_Helloworld shows up

Configuring Routes

Next, we’re going to configure a route. A route will turn a URL into an Action Controller and a method. Unlike other PHP MVC systems, you need to explicitly define a route in the global Magento config.

In your config.xml file, add the following section

standard

Alanstormdotcom_Helloworld

helloworld

We have a lot of new terminology here

What is a ?

The tag refers to a Magento Area. For now, think of Areas as individual Magento applications. The “frontend” Area is the public facing Magneto shopping cart application. The “admin” Area is the the private administrative console application. The “install” Area is the application you use to run though installing Magento the first time.

Why a tags if we’re configuring individual routes?

There’s a famous quote about computer science, often attributed to Phil Karlton

There are only two hard things in Computer Science: cache invalidation and naming things

Magento suffers from the naming problem in spades. You’ll find there are are many places in the global config, and the system in general, where the naming conventions seem unintuitive or even ambiguous. This is one of those places. Sometimes the tag will enclose configuration information about routers, other times it will enclose configuration information about the actual router objects that do the routing. This is going to seem counter intuitive at first, but as you start to work with Magento more and more, you’ll start to understand its world view a little better. (Or, in the words of Han Solo, “Hey, trust me!”).

What is a ?

When a router parses a URL, it gets separated as follows

http://example.com/frontName/actionControllerName/actionMethod/

So, by defining a value of “helloworld” in the tags, we’re telling Magento that we want the system to respond to URLs in the form of

http://example.com/helloworld/*

Many developers new to Magento confuse this frontName with the Front Controller object. They are not the same thing. The frontNames belong solely to routing.

What’s the tag for?

This tag should be the lowercase version of you module name. Our module name is Helloworld, this tag is helloworld.

You’ll also notice our frontName matches our module name. It’s a loose convention to have frontNames match the module names, but it’s not a requirement. In fact, a single module could define multiple and therefore have multiple frontNames.

What’s Alanstormdotcom_Helloworld for?

This module tag should be the full name of your module, including its package/namespace name. This will be used by the system to locate your controller files.

Create Action Controller(s) for our routes

One last step to go, and we’ll have our Action Controller. Create a file at

app/code/local/Alanstormdotcom/Helloworld/controllers/IndexController.php
That contains the following

class Alanstormdotcom_Helloworld_IndexController extends Mage_Core_Controller_Front_Action {

public function indexAction() {

echo ‘Hello Index!’;

}

}

Clear your config cache, and load the following URL

http://exmaple.com/helloworld/index/index

You should also be able to load

http://exmaple.com/helloworld/index/

http://exmaple.com/helloworld/

You should see a blank page with the text “Hello World”. Congratulations, you’ve setup your first Magento controller!

Where do Action Controllers go?

Action Controllers should be placed in a module’s controllers (lowercase c) folder. This is where the system will look for them.

How should Action Controllers be named?

Remember the tag back in config.xml?

Alanstormdotcom_Helloworld

An Action Controller’s name will

1.Start with this string specified in config.xml (Alanstormdotcom_Helloworld)

2.Be followed by an underscore (Alanstormdotcom_Helloworld_)

3.Which will be followed by the Action Controller’s name (Alanstormdotcom_Helloworld_Index)

4.And finally, the word “Controller” (Alanstormdotcom_Helloworld_IndexController)

All Action Controller need Mage_Core_Controller_Front_Action as an ancestor.

What’s that index/index nonsense?

As we previously mentioned, Magento URLs are routed (by default) as follows

http://example.com/frontName/actionControllerName/actionMethod/

So in the URL

http://exmaple.com/helloworld/index/index

the URI portion “helloworld” is the frontName, which is followed by index (The Action Controller name), which is followed by another index, which is the name of the Action Method that will be called. (an Action of index will call the method public function indexAction(){…}.

If a URL is incomplete, Magento uses “index” as the default, which is why the following URLs are equivalent.

http://exmaple.com/helloworld/index/

http://exmaple.com/helloworld/

If we had a URL that looked like this

http://exmaple.com/checkout/cart/add

Magento would

1.Consult the global config to find the module to use for the frontName checkout (Mage_Checkout)

2.Look for the cart Action Controller (Mage_Checkout_CartController)

3.Call the addAction method on the cart Action Controller

Other Action Controller tricks

Let’s try adding a non-default method to our Action Controller. Add the following code to IndexController.php

public function goodbyeAction() {

echo ‘Goodbye World!’;

}

And then visit the URL to test it out.

http://example.com/helloworld/index/goodbye

Because we’re extending the Mage_Core_Controller_Front_Action class, we get some methods for free. For example, additional URL elements are automatically parsed into key/value pairs for us. Add the following method to your Action Controller.

public function paramsAction() {

echo ‘

‘;

foreach($this->getRequest()->getParams() as $key=>$value) {

echo ‘

Param: ‘.$key.’

‘;

echo ‘

Value: ‘.$value.’

‘;

}

echo ‘

‘;

}

and visit the following URL

http://example.com/helloworld/index/params?foo=bar&baz=eof

You should see each parameter and value printed out.

Finally, what would we do if we wanted a URL that responded at

http://example.com/helloworld/messages/goodbye

Here our Action Controller’s name is messages, so we’d create a file at

app/code/local/Alanstormdotcom/Helloworld/controllers/MessagesController.php

with an Action Controller named

Alanstormdotcom_Helloworld_MessagesController

and an Action Method that looked something like

public function goodbyeAction()

{

echo ‘Another Goodbye’;

}

And that, in a nutshell, is how Magento implements the controller portion of MVC. While it’s a little more complicated than other PHP MVC framework’s, it’s a highly flexible system that will allow you build almost any URL structure you want.

How to Implement The Magento Config File

January 17, 2010 by  
Filed under Magento

The config is the beating heart of the Magento System. It describe, in whole, almost any module/model/class/template/etc than you’ll need to access. It’s a level of abstraction that most PHP developers aren’t used to working with, and while it adds development time in the form of confusion and head scratching, it also allows you an unprecedented amount of flexibility as far as overriding default system behaviors go.

To start with, we’re going to create a Magento module that will let us view the system config in our web browser. While this is all wrote copying and pasting, it’s worth going through on your own as a way to start getting comfortable with things you’ll be doing while working with Magento, as well as learning key terminology.

Setting up a module Directory Structure

We’re going to be creating a Magento module. A module is a group of php and xml files meant to extend or override core system behavior. This may meaning adding additional data models to track sales information, changing the behavior of existing classes, or adding entirely new features.

It’s worth noting that most of the base Magento system is built using the same module system you’ll be using. If you look in

app/code/core/Mage

each folder is a separate module built by the team at Varien. Together, these modules form the community shopping cart system you’re using. Your modules should be placed in the following folder

app/code/local/Packagename

“Packagename” should be a unique string to Namespace/Package your code. It’s an unofficial convention that this should be the name of your company. The idea is to pick a string that no one else if the world could possibly be using.

app/code/local/Microsoft

When I’m working on my own Magento projects, I use a version of my domain name, “Alanstormdotcom”.

So, to add a module to your Magento system, create the following directory structure

app/code/local/Alanstormdotcom/Configviewer/Block

app/code/local/Alanstormdotcom/Configviewer/controllers

app/code/local/Alanstormdotcom/Configviewer/etc

app/code/local/Alanstormdotcom/Configviewer/Helper

app/code/local/Alanstormdotcom/Configviewer/Model

app/code/local/Alanstormdotcom/Configviewer/sql

You won’t need all these folder for every module, but setting them all up now is a smart idea.

Next, there’s two files you’ll need to create. The first, config.xml, goes in the etc folder you just created.

app/code/local/Alanstormdotcom/Configviewer/etc/config.xml

The second file should be created at the following location

app/etc/modules/Alanstormdotcom_Configviewer.xml

The naming convention for this files is Packagename_Modulename.xml.

The config.xml file should contain the following XML. Don’t worry too much about what all this does for now, we’ll get there eventually

0.1.0

Finally, Alanstormdotcom_Configviewer.xml should contain the following xml.

true

local

That’s it, you now have a bare bones module that won’t do anything, but that Magento will be aware of. To make sure you’ve done everything right

1.Clear your Magento cache

2.In the Magento Admin, go to

System->Configuration->Advanced

3.Expand “Disable modules output” (if it isn’t already)

4.Ensure that Alanstormdotcom_Configviewer shows up

Congratulations, you’ve built your first Magento module!

Creating a Module Config

Of course, this module doesn’t do anything yet. When we’re done, our module will

1.Check for the existence of a “showConfig” query string variable

2.If showConfig is present, display our Magento config and halt normal execution

3.Check for the existence of an additional query string variable, showConfigFormat that will let us specify text or xml output.

First, we’re going to add the following section to our config.xml file.

singleton

Alanstormdotcom_Configviewer_Model_Observer

checkForConfigRequest

Then, create a file at

Alanstormdotcom/Configviewer/Model/Observer.php

and place the following code inside

<?php

class Alanstormdotcom_Configviewer_Model_Observer {

const FLAG_SHOW_CONFIG = ‘showConfig’;

const FLAG_SHOW_CONFIG_FORMAT = ‘showConfigFormat’;

private $request;

public function checkForConfigRequest($observer) {

$this->request = $observer->getEvent()->getData(‘front’)->getRequest();

if($this->request->{self::FLAG_SHOW_CONFIG} === ‘true’){

$this->setHeader();

$this->outputConfig();

}

}

private function setHeader() {

$format = isset($this->request->{self::FLAG_SHOW_CONFIG_FORMAT}) ?

$this->request->{self::FLAG_SHOW_CONFIG_FORMAT} : ‘xml’;

switch($format){

case ‘text’:

header(“Content-Type: text/plain”);

break;

default:

header(“Content-Type: text/xml”);

}

}

private function outputConfig() {

die(Mage::app()->getConfig()->getNode()->asXML());

}

}

That’s it. Clear your Magento cache again, and then load any Magento URL with a showConfig=true query string

http://magento.example.com/?showConfig=true

What am I looking at?

You should be looking at a giant XML file. This describes the state of your Magento system. It lists all modules, models, classes, event listeners or almost anything else you could think of.

For example, consider the config.xml file you created above. If you search the XML file in your browser for the text

Configviewer_Model_Observer

you’ll find your class listed. Every module’s config.xml file is parsed by Magento and included in the global config.

Why Do I Care?

Right now this may seem esoteric, but this config is key to understanding Magento. Every module you’ll be creating will add to this config, and anytime you need to access a piece of core system functionality, Magento will be referring back to the config to look something up.

A quick example before we move on to more practical things. As an MVC developer, you’ve likely worked with some kind of helper class, instantiated something like

$helper_sales = new HelperSales();

One of the things Magento has done is abstract away PHP’s class declaration. In Magento, the above code looks something like

$helper_sales = Mage::helper(‘sales’);

In plain english, the static helper method will

1.Look in the section of the Config.

2.Within , look for a section

3.Within the section look for a section

4.Instantiate the class found in #3 (Mage_SalesRule_Helper)

While this seems like a lot of work (and it is), the key advantage is by always looking to the config file for class names, we can override core Magento functionality without changing or adding to the core code. This level of meta programming, not usually found in PHP, allows you to cleanly extend only the parts of the system you need to.

« Previous Page