Crystal Magento Extension Technical

Crystal Magento Extension

The Crystal Magento Extension is core to how we build Magento websites. It is an integral piece of infrastructure that combines with other components such as our Crystal Speed Booster and our Crystal Caching Systems. Therefore it is imperitive that all web developers in our company understand the extension in regards to how it works, how we use it and why we use it. If you are ever unsure about any parts of it, make sure you ask questions.

Core Crystal Magento Extension

The Crystal Magento Extension comes with a core part to it. This is located in \Dropbox (Crystal Web Designs)\Crystal Web Designs Web Development\crystal magento\crystal extension. The core part of the extension is Global Code that is uploaded to all our clients websites. Therefore do not ever edit this code on a clients website. It is Global Code and therefore no changes are allowed on a website. The only time we ever edit this code is from within this folder \Dropbox (Crystal Web Designs)\Crystal Web Designs Web Development\crystal magento\crystal extension and then we may deploy the uploaded code to our clients websites. When we update the Global Code, we must ensure that any changes are compatible with all our clients websites. Because of the risks associated with such changes, the changes should be kept to a minimum and should be performed by senior developers.

Extra Extensions

We can create extra Crystal Extensions at any time for our clients.Extra extensions maybe a banner extension, a news extension, a testimonial extension or any other extension that will allow clients to edit data that then can be displayed on the website. To create an extension, run the code from this location within your browser http://localhost/Dropbox%20%28Crystal%20Web%20Designs%29/Crystal%20Web%20Designs%20Web%20Development/crystal%20magento/crystal%20extension%20builder/. When you run the code and give your custom extension a name, it should appear under C:\www\websites\extensions. Therefore these extra extensions we make can be uploaded to a specific website and can be modified as required.

Re-usable Code

One important aspect of our extensions are that they are re-usable. We don't want to be constantly writing the same code over and over again. Therefore we should try to create extensions that can be re-used for other clients. This re-usable strategy is also implemented within the companies marketing strategy and is very important to the future of our company. If you are a web developer and you are not creating re-usable code, then you are causing harm to the company. You must think re-usable and be constantly thinking about how you can create code that can be re-used in the future. This point is very important and one that you should understand as much as possible.


Creating an Extension

Let's get a bit more practical and create an extension from start to finish to see how it all works. First of all visit the page http://http://localhost/Dropbox (Crystal Web Designs)/Crystal Web Designs Web Development/crystal magento/crystal extension builder/ and enter in "crystaltest" as the name of the extension and click "Submit Query". Once we have the extension created it should appeared under C:\www\websites\extensions.

The config file

Open app\etc\modules\Crystalwebextensions_Crystalcrystaltest.xml. From this code you should be able to see that our custom created extension relies on the Crystalwebextensions_Crystalextension extension being installed on our website. This just basically means our core Crystal Magento Extension needs to be installed first, then we can create custom extensions. If you don't have the Core Crystal Magento Extension installed, Magento will halt execution of the website and tell you about the error. Other than that, the config file is a normal Magento config file that enables the custom extension that you have created to run.

Core Config

The Model file

The model file is located at app\code\local\Crystalwebextensions\Crystalcrystaltest\Model\Crystaltest.php. A model is basically a representation of an item. For example a news item. A news item may consist of a title, a description and the date that the news occurred. This news item can be obtained through the model file. In our coding we can call our model file with something like Mage::getModel('crystalextension/news'). When that piece of code runs, we are effectively returning our news extension model. To return our test model we would write Mage::getModel('crystalextension/crystaltest').

Model

Mysql file

Our models need to connect to a database and the most common way to do that is through Mysql. We use Mysql for pretty much all our websites and this connection can be found through app\code\local\Crystalwebextensions\Crystalcrystaltest\Model\Mysql4\Crystaltest.php. This is the file that is responsible for that connection and we can also use it to save the data to the database. So everytime we call the save command on our model, put any special save code in this file. For example if the date that is used in the news form is in the format 12/2/2015 but you need to save that value as 2015-02-12 in the database, you would put that code in this file. Therefore, when saving data into the database, put any formatting or special saving code in this file to ensure that the data is saved correctly.

Mysql

Collection file

When we need to get a bunch of data, we put them in a collection which is located at app\code\local\Crystalwebextensions\Crystalcrystaltest\Model\Mysql4\Crystaltest\Collection.php. The collection can hold many items such as all the news items. We can call the collection code with something like Mage::getModel('crystalextension/news')->getCollection(). For our test extension, we can call all the items via the code Mage::getModel('crystalextension/crystaltest')->getCollection().

Collection

Models, Mysql and Collections

So as you can see, the model, mysql and collection files are the backbone of getting data into our database and getting data out. These are the files that are run when you need to get an item, or maybe a collection of items and when you need to save that data back in again. These files are key to ensuring that the data is available for your html pages which you can then format nicely for the website.

Mysql setup file

As we are working with data, we may need to save that data to the database and we therefore need to create tables in the database. The easiest way to do this is to have a Mysql setup file which will create the database table when you install your extension. You can find this file under app\code\local\Crystalwebextensions\Crystalcrystaltest\sql\crystalcrystaltest_setup\mysql4-install-1.0.0.php. Within this file you'll see that all the main columns are already there and that the index key code is ready too. What you now need to do is add any extra columns to the file such as title, description etc. But remember that this file only runs once and only when you first install the extension. Therefore try to get as many columns in the file as possible because once it is installed, you'll then have to either manually add new columns to the table or create update files.

Mysql Setup

Main config file

Magento runs off configuration xml files and learning how these files work is quite important to understanding how to expand Magento with extra functionality. When creating a new Magento extension, a basic configuration file is produced which should give you the functionality that is needed to start off with. In our configuration file we have:

Core code which initiates the extension
Config Setup

The admin router which basically tells Magento we want to have our extension run in the admin
Config Admin Route

Our menu code which injects another menu item into the admin of Magento
Config Admin Menu

Our block name which allows us to create blocks, eg Mage::app()->getLayout()->createBlock('crystalextension/crystaltext')
Config Block

Our mysql model name and also the name of the mysql table
Config Mysql Model

The connection to the mysql database that we wish to use
Config Mysql Connection

Admin block file

To run our admin code we need to create a block file which is located at app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest.php. This file basically tells Magento to load up some admin pages for our extension. It is one of the main entry points to our admin pages.

Block

Grid page

When we click on our menu item we should go to our grid page initially. The grid page will list all our items that are in the database for our extension. This file is located at app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Grid.php. The grid file contains two main parts. The first is the formatting part. Not all data that comes from the database is in a form that we wish to show in our grid. For example imagine we save an image in the database. Well we don't actually save the image, we may just save the location such as /media/image-we-saved.jpg. If we should that name in our grid, it doesn't mean that much especially if we have many items. So we could format that value into something like img src="/media/image-we-saved.jpg" alt="" and this would then show the actual image. therefore the formatting part is great to show our values in a more user friendly way. The second part of the grid file is for our columns. We can specify which columns we want to appear on the page which should be based on what is most import to see first up.

Grid

Edit file

Once we click edit or new on our grid page, we go to the editing page which uses the file at app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit.php. This file is an entry point into the edit page and gets a few things ready for editing.

Edit

Form file

Our edit page needs a form so we can submit the values and then save them into the database. The form is initialised in the form file which is located at app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit. This file simply gets the form ready so we can add form elements to it which thus allows the client to edit the data.

Form

Tab file

Because our edit forms are quite complex, we break them up into tabs making it easier for people to edit. The file is located at app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit and in this file we set which tabs we would like to use. As we wish for our extensions to work in a similar way, we should keep our tabs setup the same and only make changes if necessary.

Tabs

Form Elements

Each tab that we have within our editing page links up to a file. All the files can be found under app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit\Tab. If you open up each file you can see which form elements they produce. The best tab to add in new form elements is app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit\Tab\Content.php which is the main tab that we normally enter the main data into. For example in the news extension we would use the content tab for the Title, Description and Date fields.

Form Content

Controller file

As we use the CRUD system, Create, Read, Update and Delete, we need to run the code to perform these functions. This is all located in app\code\local\Crystalwebextensions\Crystalcrystaltest\controllers\Adminhtml\CrystaltestController.php. If you need to perform some special functions, this would be the area to add it in.

Controller

Simple extension with simple code

Once you know about all the files in the extension, you should see that the setup is a little complex, but there really isn't that much code in there. It has taken a while to get the code so simple and was a process of eliminating parts that we didn't need and focusing on making these extensions as easy as possible to need. Clean code that is easy to read is very important and all staff should be focused on this when adding to these extensions.


Adding columns to the database table

Let's add 2 columns into our database table. Open up app\code\local\Crystalwebextensions\Crystalcrystaltest\sql\crystalcrystaltest_setup and add the lines:
`title` VARCHAR(250) NULL,
`description` TEXT,
so the file looks like:

Mysql Setup Update

Uploading to your website

Login to your website via your favourite ftp program. To upload the extension, simply upload all the files to the root of the website. Once the files are all uploaded, login to the admin of your website and clear the cache. Finally after that is done, your extension should be fully installed and loaded. You can this by verifying the menu item is present and that the database table is present.

Filezilla Upload

Mysql Test Structure

Add some items

Add 3 items to in the admin of the website. Do this by going to your extension via the new menu item that was created and clicking Add New. Give each item an identifier of item-1, item-2 and item-3. Assign the items to the main website that is available and all stores. Once the items are created, we can perform our next functions.

Grid Test Items

New form fields

You may have noticed that our title and description fields were missing when we created those items. Open up the file app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit\Tab\Content.php and we'll add in our two form elements. Again we could use our pre-made form helpers such as parent::addFormTitle(); but for purposes of this task we'll manually create the elements. Once you've added the below code, re-upload the extension again.

$this->fieldset->addField('title', 'text', array(
	'label' => Mage::helper('crystalextension')->__('Title'),
	'name' => 'title',
));

$this->fieldset->addField('description', 'editor', array(
	'label' => Mage::helper('crystalextension')->__('Description'),
	'name' => 'description',
));

Content Form Elements

Edit our items again

As we don't have a title or description on our items, we need to add them. Edit each item and add the following details:

This is the title of the first item

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.

This is the title of the second item

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

This is the title of the third item

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vitae dolor at tellus iaculis egestas. Duis vitae purus sit amet dui suscipit ullamcorper id eu est. Quisque hendrerit varius dolor, id tincidunt diam consectetur et. Vestibulum euismod, eros ac interdum feugiat, est tortor blandit sem, sed commodo neque erat et ex. Donec auctor ante eget velit maximus pulvinar. Suspendisse interdum, ipsum quis faucibus pharetra, lacus odio pharetra dui, vel pellentesque elit elit sed orci. Ut vel ipsum porttitor, viverra lacus et, porta purus. Maecenas at libero porttitor, sollicitudin ipsum sit amet, pellentesque nulla. Aliquam euismod feugiat est, vitae feugiat nibh lobortis cursus.

Donec rhoncus urna quam, vel facilisis diam tincidunt a. Cras scelerisque mauris tortor, rutrum viverra risus posuere sit amet. Proin eleifend est in risus mollis ultricies. Maecenas sed tincidunt tellus. Suspendisse cursus est lorem, nec consequat massa bibendum in. Fusce non lacus suscipit, aliquam felis vel, semper elit. Pellentesque ac vestibulum sapien. Mauris euismod, justo vel malesuada imperdiet, tortor nisl lacinia odio, at viverra nibh est vel sapien. Nullam ullamcorper libero turpis, id imperdiet odio pulvinar non. Suspendisse fringilla eleifend augue id dapibus. Donec viverra urna nec sapien dignissim dictum. Integer eu est aliquet, scelerisque mi vitae, consectetur nibh. Etiam interdum felis eget orci viverra, at porttitor nisl ultricies.

Duis consequat turpis sed libero egestas, a sagittis lacus venenatis. Quisque facilisis est odio, tincidunt ultrices libero vulputate et. Quisque quis pharetra augue. Vestibulum mollis lectus sit amet viverra suscipit. Quisque non augue sit amet ligula laoreet consequat faucibus in lorem. Sed dictum dapibus consectetur. Duis non venenatis dui.

Content Form Elements

Update the grid

The grid can be updated to make it easier for the client to view the information they need to see. We do this by opening up the grid file app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Grid.php. We can either use the pre-made columns such as $this->addColumnTitle($this); but for our purposes of this task, we'll create a manual column. After the indentifier field, add in our title code and then view the grid page again to see this working.

$this->addColumn('title', array(
	'filter_condition_callback' => array($this, '_filterTextLikeCondition'),
	'header' => Mage::helper('crystalextension')->__('Title'),
	'index' => 'title',
));

$this->addColumn('description', array(
	'filter_condition_callback' => array($this, '_filterTextLikeCondition'),
	'header' => Mage::helper('crystalextension')->__('Description'),
	'index' => 'description',
));

Grid Column Added Code

Grid Columns Added

Modifying our grid page

After updating our grid, you should notice that the page is becoming quite long and may look better if we limit the description field. Therefore open up app\code\local\Crystalwebextensions\Crystalextension\Block\Adminhtml\Extension\Grid.php and add in:

$description = $item->getDescription();
if (strlen($description) > 100) {
	$item->setDescription(substr($description, 0, 100) . '...');
}

Grid Code Description

Grid Description Updated

Modifying data before it is saved

Our client has requested that all titles need to be written with words starting with a capital. As people are people and people don't always follow instructions, we'll do two things to ensure this happens. Let's first start by adding a note to the title form element by opening up app\code\local\Crystalwebextensions\Crystalcrystaltest\Block\Adminhtml\Crystaltest\Edit\Tab\Content.php and adding the line:

'note' => 'The title of the items must we written with each word starting with a capital',

Title Note
Now open up the file app\code\local\Crystalwebextensions\Crystalcrystaltest\Model\Mysql4\Crystaltest.php and add in:

$title = $object->getTitle();
$title = ucwords($title);
$object->setTitle($title);

Title Ucwords
Try saving an item and you should see it gets converted to the character case we need. Obviously this isn't the greatest code in the world because if the client has a title such as ABC cutting jobs this would change to Abc Cutting Jobs. The first statement may mean the ABC Television channel is cutting jobs where the second may now mean abc to cutting jobs which is completely different.

Grid Title Ucwords

Crystal Core Extension can you help you

As the core extension has a lot of helper code, we can use that to our advantage and save time creating the extensions we need. The following lists the files with our methods that we can call:

app\code\local\Crystalwebextensions\Crystalextension\Model\Mysql4\Extension.php - pre-save helpers
app\code\local\Crystalwebextensions\Crystalextension\Block\Adminhtml\Extension\Grid - column helpers
app\code\local\Crystalwebextensions\Crystalextension\Block\Adminhtml\Extension\Edit - tab helpers
app\code\local\Crystalwebextensions\Crystalextension\Block\Adminhtml\Extension\Edit\Tab - form helpers

The special legacy model files

Open app\code\local\Crystalwebextensions\Crystalextension\ and you should find 3 files (some are in sub folders). These files are special files because of the way Magento works with models and based on the legacy of how our block system used to work. Therefore these files are not to be edited and are just place holder files that are needed for the custom extension to run. If you look at each file, you'll see that they aren't use for much.

Legacy Model

Legacy Mysql

Legacy Collection

Show our test items on the website

Now that we have some test items, we may want to show them on the website. We can do this by creating a cms page and then using our block/helper system. By combining our block/helper system which comes from our Core Crystal Magento Extension and our Crystal Block Extension we can do some very flexible and powerful things.

Test cms page

Go to CMS -> Page and create a new page. In the content area, add the code:


Cms Test Page

Cms Test Page Content

Now that we have a test page, go to the frontend of the site and view the page which should show something like:

Test Page

Setting up the phtml file

You may have noticed that the test page doesn't have any content from our text extension and this is due to the fact that we haven't created the file. So what we'll do now is create a test file with some dummy data in it. It's a good idea to do this first as it will prove that your test file has been linked up correctly with Magento.

Test Phtml File

Test Phtml File Filezilla

Test Page Testing

Setting up our full phtml file

As we've made many extensions before, we have a number of phtml files ready to go. This means that it most likely means another phtml file is what you will need or will be closed to what you need. Don't try to re-invent the wheel and create your own phtml file, find another one that has been previously created and use that instead. Also don't forget that phtml files can be refined over time, so a previous one may have had a few iterations and therefore be in a much more stable and feature packed state. Add the following to your phtml file:

<?php

$id = intval($this->getId()) > 0 ? intval($this->getId()) : intval($this->getRequest()->getParam('id'));

$collection = Mage::getModel('crystalextension/crystaltest')->getCollection()->setOrder('title', 'ASC');

if ($collection->count()) { ?>
	<div class="crystaltest">
		<div class="crystaltestwrap">
			<div class="collection">
				<?php 
				$i = 0; foreach ($collection as $item) { $i++; ?>
					<div class="item item-<?php echo $i; ?>">
						<div class="item-wrap">
							<?php if (strlen($item->getTitle())) { ?>
								<h2 class="title"><?php echo $item->getTitle(); ?></h2>
							<?php } ?>
							<?php if (strlen($item->getDescription())) { ?>
								<div class="description">
									<?php echo $item->getDescription(); ?>
								</div>
							<?php } ?>
						</div>
					</div>
				<?php } ?>
			</div>
		</div>
	</div>
<?php }

Test Page Complete

Instead of working how how to build a system, work out how to make the system better

Our Crystal Magento Extension and it's subsequent child extensions have been built with functionality already existing and a robust architecture. This gives us a great starting point and means that we're not sitting at our computers trying to figure out how to get something to work as we have that already. Therefore we should be trying to figure out how to make our extensions work better for us and our clients. Crystal is all about the quality and the quality of our work is the cornerstone of our company.

Advanced, Creating a Holder

Imagine we have created an extension and that extension needs to be placed on multiple places in a website. For example a news extension may show some news items on the home page and then show some other news items on the internal pages of the site. But how do we assign news items to both positions. The answer is with a holder. We can create a holder quite easily and then assign the news items to the appropriate holder or even both holders if we wish. This gives us a much more flexibility in the future.

Code to create a holder

Create a holder tab

Holder Tab

Create the holder form element

Holder Form Element

Create the before save code

Holder Before Save

Now the user can save items onto holders

Holder Tab and Form Element

Add in the collection filter

Holder Collection Filter

Now you can set the block item to use each filter

Holder Block Code 1

Holder Block Code 2

Advanced, Creating a Route

Sometimes you need to automatically have pages load up which generally means you need a route. For example imagine you have some news items again and you have a block on the home page. The block on the home page just shows the intro text to the news item but then has a link to the full news item. In that case we need to setup a route so the link to the news item will automatically show a page showing the whole news item. For example you could setup some links that traverse to /news/news-item-1.html and /news/news-item-2.html. If that was the case, we need some code to let Magento know that those are news items and we should show the appropriate one in a page.

Code to create a route

Create the route config

Route Config

Create the route code

Route Code

Create the phtml file which may look something like

Route Phtml File

Create the controller file which will load up our item

Index Controller for Route