311

How can the following be accomplished in Magento?

  • Display a "Hello World" message using a controller/view/model approach. So, if I went to http://example.com/myController it would show the string 'Hello World'. Being able to show this string within the template of my website (for example, the header, footer, etc.) will be a bonus.

  • How do I add a method to this controller (or a new controller if necessary), which interacts with a model, and performs the query Select * FROM articles where id='10' and returns the row (containing the columns id, title, content) to the controller? And then use the controller to include a view, which would display this row. So going to http://example.com/myController/show_row (or something similar) would display the row within a view. (No need to be fancy, just a echo $row->id; or something similar would work.)

Any other information about Magento's code structure will also be very helpful.

Alex Bogias
  • 1,826
  • 2
  • 30
  • 45
Ali
  • 261,656
  • 265
  • 575
  • 769

5 Answers5

546

First and foremost, I highly recommend you buy the PDF/E-Book from PHP Architect. It's US$20, but is the only straightforward "Here's how Magento works" resource I've been able to find. I've also started writing Magento tutorials at my own website.

Second, if you have a choice, and aren't an experienced programmer or don't have access to an experienced programmer (ideally in PHP and Java), pick another cart. Magento is well engineered, but it was engineered to be a shopping cart solution that other programmers can build modules on top of. It was not engineered to be easily understood by people who are smart, but aren't programmers.

Third, Magento MVC is very different from the Ruby on Rails, Django, CodeIgniter, CakePHP, etc. MVC model that's popular with PHP developers these days. I think it's based on the Zend model, and the whole thing is very Java OOP-like. There's two controllers you need to be concerned about. The module/frontName controller, and then the MVC controller.

Fourth, the Magento application itself is built using the same module system you'll be using, so poking around the core code is a useful learning tactic. Also, a lot of what you'll be doing with Magento is overriding existing classes. What I'm covering here is creating new functionality, not overriding. Keep this in mind when you're looking at the code samples out there.

I'm going to start with your first question, showing you how to setup a controller/router to respond to a specific URL. This will be a small novel. I might have time later for the model/template related topics, but for now, I don't. I will, however, briefly speak to your SQL question.

Magento uses an EAV database architecture. Whenever possible, try to use the model objects the system provides to get the information you need. I know it's all there in the SQL tables, but it's best not to think of grabbing data using raw SQL queries, or you'll go mad.

Final disclaimer. I've been using Magento for about two or three weeks, so caveat emptor. This is an exercise to get this straight in my head as much as it is to help Stack Overflow.

Create a module

All additions and customizations to Magento are done through modules. So, the first thing you'll need to do is create a new module. Create an XML file in app/modules named as follows

cd /path/to/store/app
touch etc/modules/MyCompanyName_HelloWorld.xml
<?xml version="1.0"?>
<config>
     <modules>
        <MyCompanyName_HelloWorld>
            <active>true</active>
            <codePool>local</codePool>
        </MyCompanyName_HelloWorld>
     </modules>
</config>

MyCompanyName is a unique namespace for your modifications, it doesn't have to be your company's name, but that the recommended convention my magento. HelloWorld is the name of your module.

Clear the application cache

Now that the module file is in place, we'll need to let Magento know about it (and check our work). In the admin application

  1. Go to System->Cache Management
  2. Select Refresh from the All Cache menu
  3. Click Save Cache settings

Now, we make sure that Magento knows about the module

  1. Go to System->Configuration
  2. Click Advanced
  3. In the "Disable modules output" setting box, look for your new module named "MyCompanyName_HelloWorld"

If you can live with the performance slow down, you might want to turn off the application cache while developing/learning. Nothing is more frustrating then forgetting the clear out the cache and wondering why your changes aren't showing up.

Setup the directory structure

Next, we'll need to setup a directory structure for the module. You won't need all these directories, but there's no harm in setting them all up now.

mkdir -p app/code/local/MyCompanyName/HelloWorld/Block
mkdir -p app/code/local/MyCompanyName/HelloWorld/controllers
mkdir -p app/code/local/MyCompanyName/HelloWorld/Model
mkdir -p app/code/local/MyCompanyName/HelloWorld/Helper
mkdir -p app/code/local/MyCompanyName/HelloWorld/etc
mkdir -p app/code/local/MyCompanyName/HelloWorld/sql

And add a configuration file

touch app/code/local/MyCompanyName/HelloWorld/etc/config.xml

and inside the configuration file, add the following, which is essentially a "blank" configuration.

<?xml version="1.0"?>
<config>
    <modules>
        <MyCompanyName_HelloWorld>
            <version>0.1.0</version>
        </MyCompanyName_HelloWorld>
    </modules>
</config>

Oversimplifying things, this configuration file will let you tell Magento what code you want to run.

Setting up the router

Next, we need to setup the module's routers. This will let the system know that we're handling any URLs in the form of

http://example.com/magento/index.php/helloworld

So, in your configuration file, add the following section.

<config>
<!-- ... -->
    <frontend>
        <routers>
            <!-- the <helloworld> tagname appears to be arbitrary, but by
            convention is should match the frontName tag below-->
            <helloworld>
                <use>standard</use>
                <args>
                    <module>MyCompanyName_HelloWorld</module>
                    <frontName>helloworld</frontName>
                </args>
            </helloworld>
        </routers>
    </frontend>
<!-- ... -->
</config>

What you're saying here is "any URL with the frontName of helloworld ...

http://example.com/magento/index.php/helloworld

should use the frontName controller MyCompanyName_HelloWorld".

So, with the above configuration in place, when you load the helloworld page above, you'll get a 404 page. That's because we haven't created a file for our controller. Let's do that now.

touch app/code/local/MyCompanyName/HelloWorld/controllers/IndexController.php

Now try loading the page. Progress! Instead of a 404, you'll get a PHP/Magento exception

Controller file was loaded but class does not exist

So, open the file we just created, and paste in the following code. The name of the class needs to be based on the name you provided in your router.

<?php
class MyCompanyName_HelloWorld_IndexController extends Mage_Core_Controller_Front_Action{
    public function indexAction(){
        echo "We're echoing just to show that this is what's called, normally you'd have some kind of redirect going on here";
    }
}

What we've just setup is the module/frontName controller. This is the default controller and the default action of the module. If you want to add controllers or actions, you have to remember that the tree first part of a Magento URL are immutable they will always go this way http://example.com/magento/index.php/frontName/controllerName/actionName

So if you want to match this url

http://example.com/magento/index.php/helloworld/foo

You will have to have a FooController, which you can do this way :

touch app/code/local/MyCompanyName/HelloWorld/controllers/FooController.php
<?php
class MyCompanyName_HelloWorld_FooController extends Mage_Core_Controller_Front_Action{
    public function indexAction(){
        echo 'Foo Index Action';
    }

    public function addAction(){
        echo 'Foo add Action';
    }

    public function deleteAction(){
        echo 'Foo delete Action';
    }
}

Please note that the default controller IndexController and the default action indexAction can by implicit but have to be explicit if something come after it. So http://example.com/magento/index.php/helloworld/foo will match the controller FooController and the action indexAction and NOT the action fooAction of the IndexController. If you want to have a fooAction, in the controller IndexController you then have to call this controller explicitly like this way : http://example.com/magento/index.php/helloworld/index/foo because the second part of the url is and will always be the controllerName. This behaviour is an inheritance of the Zend Framework bundled in Magento.

You should now be able to hit the following URLs and see the results of your echo statements

http://example.com/magento/index.php/helloworld/foo
http://example.com/magento/index.php/helloworld/foo/add
http://example.com/magento/index.php/helloworld/foo/delete

So, that should give you a basic idea on how Magento dispatches to a controller. From here I'd recommended poking at the existing Magento controller classes to see how models and the template/layout system should be used.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
Alana Storm
  • 164,128
  • 91
  • 395
  • 599
  • 5
    Thanks, this is very helpful. Please consider adding some info about using model/database and views so your answer can be complete – Ali Feb 26 '09 at 05:04
  • 1
    I highly recommend the book he linked to as well, i got it today and reading through it now. Its very useful – Ali Feb 26 '09 at 15:29
  • 8
    make sure that the app/code/local/MyCompanyName/HelloWorld/etc/config.xml has the same case as the xml located in etc/modules (MyCompanyName_HelloWorld NOT mycompanyname_helloworld) otherwise there will be to entries in the backend! – Moak Aug 22 '09 at 09:24
  • 2
    make sure you read the response from @Matus Zeman to understand why fooAction was not found on the IndexController, it's just a 'normal' Zend Framework MVC/router thing and you used the bad url, so you should remove the "This is NOT the MVC controller" part on your answer. – regilero May 11 '11 at 08:14
  • 8
    I've got just small comment on Alan's perfect answer: "What we've just setup is the module/frontName controller. This is NOT the MVC controller." It is exactly same type of controller as FooController is. In ZF index action in IndexController is called by default, so requesting http://example.com/magento/index.php/helloworld/ will call IndexController::indexAction() in helloworld module. Thus calling .../helloworld/foo will try to find FooController in helloworld module and call indexAction() on it. To trigger IndexController::fooAction() you need to request: .../helloworld/index/foo. – Matus Zeman Sep 02 '09 at 11:46
  • I am learning Magento in 2 ways : poking around and your blog. Nice! – Vinayak Garg Jun 19 '12 at 10:15
  • This is one of the most excellently framed answers I have ever seen on SO! – jerrygarciuh Oct 06 '12 at 16:05
  • Alan storm should be the father of magento module tutorials! – Robi Jan 31 '13 at 23:08
  • In the app/code/local/MyCompanyName/HelloWorld/etc/config.xml file 0.1.0 line should not contain any spaces i think. Thank you for the tutorial. – Thushara Mannaperuma Feb 13 '13 at 03:23
  • 1
    Thanks Alan for the helpful post! Folks, This should go without saying, but make sure your XML is valid -- I just spent the entire day searching for the problem in my code, on a whim I checked the validity of my xml config files by opening them in a web browser. I had forgotten a '/' in one of my XML tags, after I fixed that it worked. grrr. Also don't forget to check the log files at ./myproject/var/log -- helpful debug info gets printed there, I found that after I found the XML error and the error was listed there in the log. – hypervisor666 May 04 '13 at 04:16
  • 2
    @hypervisor666 Turn on "developer mode" (google it). With developer mode on, Magento will crash on any errors in XML files. – Alana Storm May 04 '13 at 04:53
  • Here you can get that book as free. http://beytullah.me/wp-content/uploads/2012/11/magento-ebook-en.pdf – Syed Ibrahim Jan 03 '15 at 14:09
  • 1
    I'm wondering why no one ever extended this answer further ? @AlanStorm ends his answer with a too brief notice to look at template and layout but even for people knowing MVC structure Magento can be a little bit hard to put hands on. With the block and layout (sort of elements in-between the view and controller), which does not exists in a basic MVC structure. Plus, by stopping on a controller which is echo'ing things, we, in this wiki, fail to teach newer user the proper MVC structure where there IS a clear separation in the presentation and business layer. – β.εηοιτ.βε Jan 04 '15 at 11:37
  • Awesome answer. Plus one to that. For those who do not want to manually create the barebone files to make a module, here's a useful project : `https://github.com/shell/Magento-Module-Creator` . – Gogol Jan 09 '15 at 11:17
  • Thanks For telling to **`Clear cache from "Cache management"`** – Pratik Joshi Jan 29 '15 at 07:38
  • Module gives 404 error in magento 1.9.2.1 : http://stackoverflow.com/questions/32188034/magento-1-9-2-1-custom-module-404 – Pratik Joshi Aug 28 '15 at 10:29
  • This is awesome intro to magneto, I've been reading a lot about it and usually the tutorials go all around, but this is straight forward and understandable. Thank you mate you are too kind :) – The Bumpaster Sep 15 '15 at 06:16
  • @AlanStorm Whenever I search for products using the REST API V1/products, I don't get the category_id in the response. To do this I have been told to add a new plugin to the Magento. But I am confused between modules and plugins. DO I have to follow your answer to achieve my goal? Here is the link to my question http://magento.stackexchange.com/questions/95314/category-ids-attribute-missing-while-searching-for-products-via-rest-api-rest-v – nr5 Dec 31 '15 at 11:43
39

I've been wrestling with Magento for the last month or so and I'm still trying to figure it out. So this is a case of the blind leading the blind. There's little in the way of documentation and the forum/wiki is chaotic at best. Not only that, but there are several solutions that are either outdated or far from optimal. I'm not sure if you have a project or just trying to figure it out, but it's probably easier if you started with modifying existing functionality as opposed to creating something completely new. For that I'd definately go with the "Recommended articles for developers" in the wiki. The new payment method one was a real eye-opener.

For debugging I'd definitely recommend using FirePHP and looking at your HTML source when something goes wrong. The ole echo debug method doesn't really work all that well.

The general architecture is so mind-numbingly complex, that even if I completely understood it, I'd need to write a book to cover it. The best I can do is give you advice I wish someone had given me when I first started...

Stay away from core files. Don't modify them, instead write your own module and override what you need.

Magento uses config files consisting of XML to decide what it needs to do. In order to get it to run your own stuff as opposed to core functionality you need the correct xml. Unfortunately there is no guide on how to build you XML; you need to look at examples and do some serious testing. To complicate things the content of these files is largely case-sensitive. However if you master these you can override any part of the basic functionality which makes for a very powerful system.

Magento uses methods like Mage::getModel('mymodel'), Mage::getSingleton('mysingleton'), Mage::helper('myhelper') to return objects of certain classes. It finds these by default in its core namespace. If you want it to use your own, you need to override these in your config.xml file.

The name of your classes must correspond to the folder they're in.

A lot of the objects in Magento ultimately extend something called a Varien_Object. This is a general purpose class (kind of like a swiss army knife) and its purpose in life is to allow you to define your own methods/variables on the fly. For example you'll see it used as a glorified array to pass data from one method to another.

During development make sure you caching is disabled. It'll make magento excruciatingly slow, but it'll save you a lot of head trauma (from banging it on your desk).

You'll see $this being used a lot. It means a different class depending on what file you see it. get_class($this) is your friend, especially in conjunction with FirePHP.

Jot things down on paper. A lot. There are countless little factoids that you're gonna need 1-2 days after you encounter them.

Magento loves OO. Don't be surprised if tracing a method takes you through 5-10 different classes.

Read the designer's guide here. It's meant mostly for graphics designers, but you need it to understand where and why the output from your module will end up. For that don't forget to turn on "Template path hints" in the developer section of the admin panel.

There's more, but I'll stop here before this turns into a dissertation.

Community
  • 1
  • 1
Manos Dilaverakis
  • 5,849
  • 4
  • 31
  • 57
  • Please post more if you can, all info is very helpful :) – Ali Feb 25 '09 at 11:29
  • Misa, you should probably register here on Stackoverflow, if you lost your cookie all your rep would be gone ;) – Ali Feb 25 '09 at 14:00
  • Thank you! This is very helpful. [Ner](https://stackoverflow.com/users/2057131/ner?tab=profile) – Ner Oct 29 '17 at 09:02
3

I will rather recommend Mage2Gen, this will help you generate the boilerplate and you can just focus on the core business logic. it just helps speed up the things.

Sajid
  • 379
  • 4
  • 18
0

A Magento Module is a group of directories containing blocks, controllers, helpers, and models that are needed to create a specific store feature. It is the unit of customization in the Magento platform. Magento Modules can be created to perform multiple functions with supporting logic to influence user experience and storefront appearance. It has a life cycle that allows them to be installed, deleted, or disabled. From the perspective of both merchants and extension developers, modules are the central unit of the Magento platform.

Declaration of Module

We have to declare the module by using the configuration file. As Magento 2 search for configuration module in etc directory of the module. So now we will create configuration file module.xml.

The code will look like this:

<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Cloudways_Mymodule" setup_version="1.0.0"></module> </config>

Registration of Module The module must be registered in the Magento 2 system by using Magento Component Registrar class. Now we will create the file registration.php in the module root directory:

app/code/Cloudways/Mymodule/registration.php

The Code will look like this:

?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Cloudways_Mymodule',
__DIR__
);

Check Module Status After following the steps above, we would have created a simple module. Now we are going to check the status of the module and whether it is enabled or disabled by using the following command line:

php bin/magento module:status

php bin/magento module:enable Cloudways_Mymodule

Share your feedback once you have gone through complete process

0

I was trying to make my module from magaplaza hello world tutorial, but something went wrong. I imported code of this module https://github.com/astorm/magento2-hello-world from github and it worked. from that module, i created it a categories subcategories ajax select drop downs Module. After installing it in aap/code directory of your magento2 installation follow this URL.. http://www.example.com/hello_mvvm/hello/world You can download its code from here https://github.com/sanaullahAhmad/Magento2_cat_subcat_ajax_select_dropdowns and place it in your aap/code folder. than run these commands...

php bin/magento setup:update
php bin/magento setup:static-content:deploy -f
php bin/magento c:c

Now you can check module functionality with following URL http://{{www.example.com}}/hello_mvvm/hello/world

Sanaullah Ahmad
  • 474
  • 4
  • 12