Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - CMS & E-Commerce

830 Articles
article-image-rendering-images-typo3-43-part-1
Packt
03 Feb 2010
4 min read
Save for later

Rendering Images in TYPO3 4.3: Part 1

Packt
03 Feb 2010
4 min read
Rendering images using content elements Content elements offer a variety of ways for editors to include images. We will examine these here. Here is a typical selection menu that editor is presented with: A great way to start is to assemble pages from the Regular text element and the Text with image elements Getting Ready Make sure Content (default) is selected in Include static, and the CSS Styled Content template is included in the Include static (from extensions) field of the template record of the current page or any page above it in the hierarchy (page tree). To verify, go to the Template module, select the appropriate page, and click edit the whole template record. How to do it... Create the Text with image element. Under the Text tab, enter the text you want to appear on the page. You can use the RTE (Rich Text Editor) to apply formatting, or disable it. We will cover RTE in more detail later in this article. Under the Media tab, select your image settings. If you want to upload the image, use the first field. If you want to use an existing image, use the second field. Under Position, you are able to select where the image will appear in relation to the text. How it works... When the page is rendered in the frontend, the images will be placed next to the text you entered, in the position that you specify. The specific look will depend on the template that you are using. There's more An alternative to the Text with images is an Images only content element. This element gives you similar options, except limits the options to just a display of images. The rest of the options are the same. You can also resize the image, add caption, alt tags for accessibility and search engine optimization, and change default processing options. See the official TYPO3 documentation for details of how these fields work, (http://typo3.org/documentation/document-library/). See also Render video and audio using content elements and rgmediaimages extension Embedding images in RTE Rich Text Editor is great for text entry. By default, TYPO3 ships with htmlArea RTE as a system extension. Other editors are available, and can be installed if needed. Images can be embedded and manipulated within the RTE. This provides one place for content editors to use in order to arrange content how they want it to appear at the frontend of the site. In this recipe, we will see how this can be accomplished. The instructions apply to all forms that have RTE-enabled fields, but we will use the text content element for a simple demonstration. In the Extension Manager, click on htmlArea RTE extension to bring up its options. Make sure that the Enable images in the RTE [enableImages] setting is enabled. If you have a recent version of DAM installed (at least 1.1.0), make sure that the Enable the DAM media browser [enableDAMBrowser] setting is unchecked. This setting is deprecated, and is there for installations using older versions of DAM. How to do it... Create a new Regular text element content element. In the RTE, click on the icon to insert an image as shown in the following screenshot: Choose a file, and click on the icon to insert it into the Text area. You should see the image as it will appear at the frontend of the site. Save and preview. The output should appear similar to the following screenshot: How it works... When you insert an image through the RTE, the image is copied to uploads folder, and included from there. The new file will be resampled and sized down, so, it usually occupies less space and is downloaded faster than the original file. TYPO3 will automatically determine if the original file has changed, and update the file used in the RTE—but you should still be aware of this behaviour. Furthermore, if you have DAM installed, and you have included an image from DAM, you can see the updated record usage. If you view the record information, you should see the Content Element where the image is used:
Read more
  • 0
  • 0
  • 1416

article-image-advanced-blog-management-apache-roller-40-part-3
Packt
03 Feb 2010
4 min read
Save for later

Advanced Blog Management with Apache Roller 4.0: Part 3

Packt
03 Feb 2010
4 min read
Weblog clients There are times when logging into your Roller weblog to post a new entry can be a tedious process, especially when you have two or more weblogs about different subjects. Let's say that you have to write stuff in your company's blog, and you also write in your personal Roller blog. You can open two web browser windows and log into each blog separately, but it would be better to use a weblog client, as I'll show you in the next exercise. Time for action – using Google docs as your weblog client In this exercise, you'll learn to use Google docs as your weblog client to post entries in your Roller weblogs without having to log in: Open your web browser, go to http://docs.google.com, log in with your username and password (if you don't have a Google account, this is your chance to get one!), then click on the New button, and select the Document option: Your browser will open a new tab for the new Google docs document. Type This is my first post to my Roller weblog from Google Docs! in the word processor writing area, as shown in the following screenshot: Now click on the File menu and select the Save option to save your draft in Google docs: Google docs assigns the title for your document automatically, based on its content. To change the title of your post, click on it: Type Posting to Roller from Google Docs in the dialog that will show up next, and click on OK to continue: Google docs will show the new title for your post: Now click on the Share button and select the Publish as web page option: The Publish this document dialog will appear. Click on the change your blog site settings link to enter your Roller weblog information: The Blog Site Settings dialog will appear next. Choose the My own server / custom option and select MetaWeblog API in the API field. In the URL field you need to type the complete path to Roller's web services—http://alromero.noip.org/roller/roller-services/xmlrpc, in my case. You just need to replace the alromero.no-ip.org part with your dynamic hostname. Then type your Roller username, password, and weblog name, and select the Include the document title when posting option, as shown in the following screenshot: Click on the OK button to save your weblog settings, and then click on the Post to blog button in the Publish this document dialog: A confirmation dialog will pop-up, asking if you want to post the document to your blog now. Click on OK to continue: Google docs will show the This document has been published to your blog success message: Click on the Save & Close button at the upper-right part of the screen to save your document and return to the Google docs main page, then click on Sign out to exit Google docs. Now go to your Roller weblog's main page, to see the post you published from Google docs: What just happened? See how easy it is to use a weblog client, so that you don't need to log into your Roller weblog to post a new entry? And if you want to post to a different Roller weblog, you just need to change your username, blog ID, or URL. There are several other weblog clients available that you can use, depending on your operating system, but all weblog clients work in a similar way. Have a go hero – try out other weblog clients Go and try out some other weblog clients, to see which one is best for you. In Windows, you can use Windows Live Writer (http://download.live.com/writer) and w.bloggar (http://bloggar.com/). In Linux, you can try out BloGTK (https://launchpad.net/blogtk/).
Read more
  • 0
  • 0
  • 1366

article-image-typo3-connecting-external-apis-flicker-and-youtube
Packt
01 Feb 2010
10 min read
Save for later

TYPO3 for Connecting External APIs: Flicker and Youtube

Packt
01 Feb 2010
10 min read
Getting recent Flickr photos The Flickr API is very powerful and gives access to just about everything a user can do manually. You can write scripts to automatically download latest pictures from a photostream, download photos or videos tagged with a certain keyword, or post comments on photos. In this recipe, we will make use of the phpFlickr library to perform some basic listing functions for photos in Flickr. Getting ready Before you start, you should sign up for a free Flickr account, or use an existing one. Once you have the account, you need to sign up for an API key. You can go to Your Account, and select the Extending Flickr tab. After filling in a short form, you should be given two keys—API key and secret key. We will use these in all Flickr operations. We will not go through the steps required for integration into extensions, and will leave this exercise to the reader. The code we present can be used in both frontend plugins and backend modules. As was previously mentioned, we will be using the phpFlickr library. Go to http://phpflickr.com/ to download the latest version of the library and read the complete documentation. How to do it... Include phpFlickr, and instantiate the object (modify the path to the library, and replace api-key with your key): require_once("phpFlickr.php");$flickrService = new phpFlickr('api-key'); Get a list of photos for a specific user: $photos = $flickrService->people_getPublicPhotos('7542705@N08'); If the operation succeeds, $photos will contain an array of 100 (by default) photos from the user. You could loop over the array, and print a thumbnail with a link to the full image by: foreach ($photos['photos']['photo'] as $photo) { $imgURL = $flickrService->buildPhotoURL($photo, 'thumbnail'); print '<a href="http://www.flickr.com/photos/' . $photo['owner'] . '/' . $photo['id'] . '">' . '<img src="' . $imgURL . '" /></a><br />';} How it works... The Flickr API is exposed as a set of REST services, which we can issue calls to. The tough work of signing the requests and parsing the results is encapsulated by phpFlickr, so we don't have to worry about it. Our job is to gather the parameters, issue the request, and process the response. In the example above, we got a list of public photos from a user 7542705@N08. You may not know the user ID of the person you want to get photos for, but Flickr API offers several methods for finding the ID: $userID = $flickrService->people_findByEmail($email);$userID = $flickrService->people_findByUsername($username); If you have the user ID, but want to get more information about the user, you can do it with the following calls: // Get more info about the user:$flickrService->people_getInfo($userID);// Find which public groups the user belongs to:$flickrService->people_getPublicGroups($userID);// Get user's public photos:$flickrService->people_getPublicPhotos($userID); We utilize the people_getPublicPhotos method to get the user's photostream. The returned array has the following structure: Array( [photos] => Array ( [page] => 1 [pages] => 8 [perpage] => 100 [total] => 770 [photo] => Array ( [0] => Array ( [id] => 3960430648 [owner] => 7542705@N08 [secret] => 9c4087aae3 [server] => 3423 [farm] => 4 [title] => One Cold Morning [ispublic] => 1 [isfriend] => 0 [isfamily] => 0 ) […] ) )) We loop over the $photos['photos']['photo'] array, and for each image, we build a URL for the thumbnail using the buildPhotoURL method, and a link to the image page on Flickr. There's more... There are lots of other things we can do, but we will only cover a few basic operations. Error reporting and debugging Occasionally, you might encounter an output you do not expect. It's possible that the Flickr API returned an error, but by default, it's not shown to the user. You need to call the following functions to get more information about the error: $errorCode = $flickrService->getErrorCode();$errorMessage = $flickrService->getErrorMsg(); Downloading a list of recent photos You can get a list of the most recent photos uploaded to Flickr using the following call: $recentPhotos = $flickrService->photos_getRecent(); See also Uploading files to Flickr Uploading DAM files to Flickr Uploading files to Flickr In this recipe, we will take a look at how to upload files to Flickr, as well as how to access other authenticated operations. Although many operations don't require authentication, any interactive functions do. Once you have successfully authenticated with Flickr, you can upload files, leave comments, and make other changes to the data stored in Flickr that you wouldn't be allowed to do without authentication. Getting ready If you followed the previous example, you should have everything ready to go. We'll assume you have the $flickrService object instantiated ready. How to do it... Before calling any operations that require elevated permissions, the service needs to be authenticated. Add the following code to perform the authentication: $frob = t3lib_div::_GET('frob');if (empty($frob)) { $flickrService->auth('write', false);} else { $flickrService->auth_getToken($frob);} Call the function to upload the file: $flickrService->sync_upload($filePath); Once the file is uploaded, it will appear in the user's photostream. How it works... Flickr applications can access any user's data if the user authorizes them. For security reasons, users are redirected to Yahoo! to log into their account, and confirm access for your application. Once your application is authorized by a user, a token is stored in Flickr, and can be retrieved at any other time. $flickrService->auth() requests permissions for the application. If the application is not yet authorized by the user, he/she will be redirected to Flickr. After giving the requested permissions, Flickr will redirect the user to the URL defined in the API key settings. The redirected URL will contain a parameter frob. If present, $flickrService->auth_getToken($frob); is executed to get the token and store it in session. Future calls within the session lifetime will not require further calls to Flickr. If the session is expired, the token will be requested from Flickr service, transparent to the end user. There's more... Successful authentication allows you to access other operations that you would not be able to access using regular authentication. Gaining permissions There are different levels of permissions that the service can request. You should not request more permissions than your application will use. API call Permission level $flickrService->auth('read', false); Permissions to read users' files, sets, collections, groups, and more. $flickrService->auth('write', false); Permissions to write (upload, create new, and so on). $flickrService->auth('delete', false); Permissions to delete files, groups, associations, and so on. Choosing between synchronous and asynchronous upload There are two functions that perform a file upload: $flickrService->sync_upload($filePath);$flickrService->async_upload($filePath); The first function continues execution only after the file has been accepted and processed by Flickr. The second function returns after the file has been submitted, but not necessarily processed. Why would you use the asynchronous method? Flickr service may have a large queue of uploaded files waiting to be processed, and your application might timeout while it's waiting. If you don't need to access the uploaded file right after it was uploaded, you should use the asynchronous method. See also Getting recent Flickr photos Uploading DAM files to Flickr Uploading DAM files to Flickr In this recipe, we will make use of our knowledge of the Flickr API and the phpFlickr interface to build a Flickr upload service into DAM. We will create a new action class, which will add our functionality into a DAM file list and context menus. Getting ready For simplicity, we will skip the process of creating the extension. You can download the extension dam_flickr_upload and view the source code. We will examine it in more detail in the How it works... section. How to do it... Sign up for Flickr, and request an API key if you haven't already done so. After you receive your key, click Edit key details. Fill in the application title and description as you see fit. Under the call back URL, enter the web path to the dam_flickr_upload/mod1/index.php file. For example, if your domain is http://domain.com/, TYPO3 is installed in the root of the domain, and you installed dam_flickr_upload in the default local location under typo3conf, then enter http://domain.com/typo3conf/ext/dam_flickr_upload/mod1/index.php You're likely to experience trouble with the callback URL if you're doing it on a local installation with no public URI. Install dam_flickr_upload. In the Extension Manager, under the extension settings, enter the Flickr API key and the secret key you have received. Go to the Media | File module, and click on the control button next to a file. Alternatively, select Send to Flickr in the context menu, which appears if you click on the file icon, as seen in the following screenshot: A new window will open, and redirect you to Flickr, asking you to authorize the application for accessing your account. Confirm the authorization by clicking the OK, I'LL AUTHORIZE IT button. The file will be uploaded, and placed into your photostream on Flickr. Subsequent uploads will no longer need explicit authorization. A window will come up, and disappear after the file has been successfully uploaded. How it works... Let's examine in detail how the extension works. First, examine the file tree. The root contains the now familiar ext_tables.php and ext_conf_template.txt files.The Res directory contains icons used in the DAM. The Lib directory contains the phpFlickr library. The Mod1 directory contains the module for uploading. ext_conf_template.txt This file contains the global extension configuration variables. The two variables defined in this file are the Flickr API key and the Flickr secret key. Both of these are required to upload files. ext_tables.php As was mentioned previously, ext_tables.php is a configuration file that is loaded when the TYPO3 framework is initializing. tx_dam::register_action ('tx_dam_action_flickrUpload', 'EXT:dam_flickr_upload/class.tx_dam_flickr_upload_action.php:&tx_dam_flickr_upload_action_flickrUpload'); This line registers a new action in DAM. Actions are provided by classes extending the tx_dam_actionbase class, and define operations that can be performed on files and directories. Examples of actions include view, cut, copy, rename, delete, and more. The second parameter of the function defines where the action class is located. $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dam_flickr_upload']['allowedExtensions'] = array('avi', 'wmv', 'mov', 'mpg', 'mpeg','3gp', 'jpg', 'jpeg', 'tiff', 'gif', 'png'); We define an array of file types that can be uploaded to Flickr. This is not hardcoded in the extension, but stored in ext_tables.php, so that it can be overwritten by extensions wanting to limit or expand the functionality to other file types.
Read more
  • 0
  • 0
  • 1936
Visually different images

article-image-magentos-architecture-part-1
Packt
01 Feb 2010
5 min read
Save for later

Magento's Architecture: Part 1

Packt
01 Feb 2010
5 min read
Magento's base structure The fundamental knowledge of Magento's architecture begins with its file structure. It's important to know what goes where by default, so that we may position our new files accordingly, especially in terms of ensuring that our development doesn't overwrite core files. Base directory The default installation contains the following files and directories in the base directory: .htaccess .htaccess.sample 404 (directory) app (directory) cron.php downloader (directory) favicon.ico index.php index.php.sample js (directory) lib (directory) LICENSE_AFL.txt LICENSE.txt media (directory) pear pkginfo (directory) report (directory) skin (directory) var (directory) Each of these files and directories has a different purpose. We'll go through them to ensure that we understand the function of each. This will help us later, if ever we need to find something specific, or when developing. It will also be helpful when we'll be looking to place the files coming out of our new module into the appropriate directory. The function of each of the files in the base directory The following is a run through of all the files in the base directory, to show us what they do: .htaccess—This file controls mod_rewrite for fancy URLs and sets configuration server variables (such as memory limit) and PHP maximum execution time, so that Magento can run better. .htaccess.sample—Works as a backup for .htaccess, so that we know the default .htaccess file (if ever we edit it and need to backtrack). cron.php—The file that should be executed as a cron job every few minutes to ensure that Magento's wide caching doesn't affect our server's performance. favicon.ico—Magento's default favicon; it's the small icon that appears in the toolbar of our browser. index.php—The main loader file for Magento and the file that initializes everything. index.php.sample—The base template for new index.php files, useful when we have edited the index.php file and need to backtrack. LICENSE_AFL.txt—It contains the Academic Free License that Magento is distributed under. LICENSE.txt—It contains the Open Software License that Magento is distributed under. pear—This controls all automatic updating via the downloader and SSH. This file is initialized and handles the updating of each individual module that makes up Magento. php.ini—A sample php.ini file for raw PHP server variables recommended when setting up Magento on our server. This should not be used as a complete replacement, but only as a guide to replace certain lines of the php.ini server file. It is useful when overriding these variables when .htaccess isn't enabled on our server. The function of each of the folders in the base directory The following is a run through of all the folders in the base directory to show us their contents: 404—The default 404 template and skin storage folder for Magento. app—All code (modules), design (themes), configuration, and translation files are stored in this directory. This is the folder that we'll be working in extensively, when developing a Magento powered website. Also contained in this folder are the template files for the default administration theme and installation. downloader—The web downloader for upgrading and installing Magento without the use of SSH. js—The core folder where all JavaScript code included with the installation of Magento is kept. We will find all pre-compiled libraries of JavaScript here. lib—All PHP libraries used to put together Magento. This is the core code of Magento that ties everything together. The Zend Framework is also stored within this directory. media—All media is stored here. Primarily for images out of the box, this is where all generated thumbnails and uploaded product images will be stored. It is also the container for importing images, when using the mass import/export tools. pkginfo—Short form of package information, this directory contains text files that largely operate as debug files to inform us about changes when modules are upgraded in any way. report—The skin folder for the reports that Magento outputs when any error occurs. skin—All assets for themes are stored within this directory. We typically find images, JavaScript files, CSS files, and Flash files relating to themes, in this directory. However, it can be used to store any assets associated with a theme. It also contains the skin files for the installation of skins and administration templates. var—Typically where we will find all cache and generated files for Magento. We can find the cache, sessions (if storing as files), data exports, database backups, and cached error reports in this folder. The template system architecture The template architecture is broken into three areas—two for development of the theme and one for the containment of the assets: /app/design/frontend/default/<template_name>/ layout/—For all the XML files declaring which module tied functions should be called to which template files template/—For all the templates processing the output that is passed from functions called from layout/ and structured into the final output to the user. /skin/frontend/default/<template_name>/—For the containment of all assets relating to our template, images, CSS, Flash, and JavaScript. Structural blocks and content blocks Each theme contains structural and content blocks. Structural blocks are the ones that lay out the theme into sections. Let's take a look at a three-column layout. The following are the structural blocks in a three-column layout: header left content right footer Here's a visual representation of those structural blocks laid over the Magento demo store: In each of the structural blocks, we then have content blocks that give each structural block its content for output to the browser. Let's take the right column; our content blocks set for this column on a standard theme could be: mini cart recently viewed products newsletter subscription block poll
Read more
  • 0
  • 0
  • 1950

article-image-magentos-architecture-part-2
Packt
01 Feb 2010
7 min read
Save for later

Magento's Architecture: Part 2

Packt
01 Feb 2010
7 min read
Modules and how they work within the system Magento primarily works on a base of modules. All functionality is divided up into modules that make up the system overall. It's important to understand what each module does and how to go about adding modules to the system, in order to understand the architecture of modules themselves. Distribution of the modules between directories All modules are located within the /app/code/ directory. Directories are commonly referred to as codePools. There are three possible locations for all modules that relate to the system. They are all split by type to prevent any confusion: community—For community-distributed extensions, usually those that we have installed through Magento Connect or have downloaded from a source, other than our own. Anything installed through Magento Connect will be installed here automatically. core—Reserved for core Magento modules, so that we cannot directly overwrite or interfere with them. We keep our modules out of core to avoid any conflict with the core modules or any future updates. Anything from a Magento upgrade or any new Magento modules will go into this directory. Local—This is where we should be placing our modules when they are either under local development or are not distributed among the community. It's best to keep anything that we develop in this directory, so as to not interfere with the core or community modules. Nothing will be automatically installed here, unless we have physically uploaded it. Modules included with Magento Included modules in the core folder of default Magento installation are as follows: Mage_Admin Mage_AdminNotification Mage_Api Mage_Backup Mage_Bundle Mage_Catalog Mage_CatalogIndex Mage_CatalogInventory Mage_CatalogRule Mage_CatalogSearch Mage_Checkout Mage_Cms Mage_Contacts Mage_Core Mage_Cron Mage_Customer Mage_Dataflow Mage_Directory Mage_Downloadable Mage_Eav Mage_GiftMessage Mage_GoogleAnalytics Mage_GoogleBase Mage_GoogleCheckout Mage_GoogleOptimizer Mage_Install Mage_Log Mage_Media Mage_Newsletter Mage_Page Mage_Paygate Mage_Payment Mage_Paypal Mage_PaypalUk Mage_Poll Mage_ProductAlert Mage_Rating Mage_Reports Mage_Review Mage_Rss Mage_Rule Mage_Sales Mage_SalesRule Mage_Sendfriend Mage_Shipping Mage_Sitemap Mage_Tag Mage_Tax Mage_Usa Mage_Weee Mage_Wishlist Setting up the folder structure of a module Let's presume that we want to set up a module's folder structure, ready for development. Our module's core folders will be placed in /app/code/local/Book/Example/. These folders will primarily be used for storing our code that makes the module work. The folder structure breaks down as follows: Block/ controllers/ etc/ Model/ Mysql4/ Book/ sql/ book_setup/ Typically, developers will pick or choose each folder, depending on whether or not they're going to use it within their module. Note that Model/Mysql4/Book/ has its first letter in uppercase, whereas sql/book_setup/ does not. We must be sure to keep this the same way throughout our development. Template files for the frontend of our module will be stored as follows: XML files will be stored in /app/design/frontend/<interface>/<theme>/layout/example/ Output files will be stored in /app/design/frontend/<interface>/<theme>/template/example/ Any admin template files for the frontend of our module will be stored as follows: XML files will be stored in /app/design/adminhtml/<interface>/<theme>/layout/example/ Output files will be stored in /app/design/adminhtml/<interface>/<theme>/template/example/ Here's a breakdown of what each folder is for: Block/—For processing of all display blocks called by the system for the module. These are controllers that will be called in the XML layout files within a theme, in order to display something. controllers/—Our controllers that support the application and structurally keep things together. etc/—Configuration files for the module, for declaring things such as the default options when installed and declaring all blocks, models, and install/upgrade actions. Model/—For placement of all models to support controllers in the module. sql/—SQL actions when the module is installed/upgraded/uninstalled. Zend Framework and its role within Magento Magento (at its raw PHP base) is built on the Zend Framework. From the database class to the handling of URLs, Magento is in its raw form, with Zend Framework doing all the work. Alongside this, Varien has built several core modules on top of the Zend Framework, in order to tie it altogether into the system as we know it. What is Zend Framework Zend Framework's official site best describes the framework as follows: Zend Framework (ZF) is an open source framework for developing web applications and services with PHP 5. ZF is implemented using 100% object-oriented code. The component structure of ZF is somewhat unique; each component is designed with few dependencies on other components. This loosely coupled architecture allows developers to use components individually. We often call this a "use-at-will" design. While they can be used separately, Zend Framework components in the standard library form a powerful and extensible web application framework when combined. ZF offers a robust, high performance MVC implementation, a database abstraction that is simple to use, and a forms component that implements HTML form rendering, validation, and filtering so that developers can consolidate all of these operations using one easy-to-use, object-oriented interface. Other components, such as Zend_Auth and Zend_Acl, provide user authentication and authorization against all common credential stores. Still others implement client libraries to simply access to the most popular web services available. Whatever your application needs are, you're likely to find a Zend Framework component that can be used to dramatically reduce development time with a thoroughly tested foundation. How Zend Framework works The Zend Framework (at its core) is designed to be used as a package or separate modules. This (among other features) makes it unique, as most other frameworks are designed to be used plainly as frameworks or not at all. However, the Zend Framework comes with classes that allow us to use it as a standalone framework and develop with it as one. Instead of being delivered with a preset amount of directories and layout for developers, it only suggests a layout for our files. This means that we can adapt the framework to meet our current workflow and choose how much we adapt the workflow to fit the framework. It's role and effect in Magento The Zend Framework allows Magento to focus on the core issues at hand. It removes a lot of the work on the database and core structural classes and puts the work towards fixing and adding to core modules of Magento. Most importantly it gives developers a standard approach to development that they can move across and apply to Magento. The standard development practices help greatly in adopting Magento as a platform and make it easier for developers having experience with Zend Framework to adapt to Magento. More information on learning the Zend Framework and resources can be found at the back of this book in the Appendix attached. Its official site is located at: http://framework.zend.com/. Backing up Magento's data It's important to know how to back up our site, to ensure that our installation's data is not lost (if ever things go bad). It is recommended to back up our Magento installation: Regularly as a base to ensure that there are incremental backups of our system Before installing new modules or themes from Magento Connect When developing modules Before upgrading our system
Read more
  • 0
  • 0
  • 1377

article-image-enhancing-user-experience-php-5-ecommerce-part-1
Packt
29 Jan 2010
7 min read
Save for later

Enhancing the User Experience with PHP 5 Ecommerce: Part 1

Packt
29 Jan 2010
7 min read
Juniper Theatricals Juniper Theatricals want to have a lot of products on their online store, and as a result they fear that some products may get lost within the website, or not be as obvious to their customers. To help prevent this problem, we will integrate product searching to make products easy to find, and we will add filters to product lists allowing customers to see products that match what they are looking for (for example, ones within their price range). As some products could still be lost, they want to be able to recommend related products to customers when they view particular products. If a customer wants a product, and it happens to be out of stock, then they want to prevent the customer from purchasing it elsewhere; so we will look at stock notifications too. The importance of user experience Our customers' experience on the stores powered by our framework is veryimportant. A good user experience will leave them feeling wanted and valued, whereas a poor user experience will leave them feeling unwanted, unvalued, and may leave a bad taste in their mouths. Search The ability for customers to be able to search, find, and filter products is vital, as if they cannot find what they are looking for they will be frustrated by our site and go somewhere where they can find what they are looking for much more easily. There are two methods that can make it much easier for customers to find what they are looking for: Keyword search: This method allows customers to search the product catalog based on a series of keywords. Filtering: This method allows customers to filter down lists of products based on attributes, refining larger lists of products into ones that better match their requirements. Finding products The simplest way for us to implement a search feature is to search the product name and product description fields. To make the results more relevant, we can place different priorities on where matches were found; for instance, if a word or phrase is found in both the name and description then that would be of the highest importance; next would be products with the word or phrase in the name; and finally, we would have products that just have the word or phrase contained within the product description itself. So, what is involved in adding search features to our framework? We need the following: Search box: We need a search box for our customers to type in words or phrases. Search feature in the controller: We need to add some code to search the products database for matching products. Search results: Finally, we need to display the matching products to the customer. Search box We need a search box where our customers can type in words or phrases to search our stores. This should be a simple POST form pointing to the path products/search with a search field of product_search. The best place for this would be in our website's header, so customers can perform their search from anywhere on the site or store. <div id="search"><form action="products/search" method="post"><label for="product_search">Search for a product</label><input type="text" id="product_search" name="product_search" /><input type="submit" id="search" name="search" value="Search" /></form></div> We now have a search box on the store: Controlling searches with the products controller A simple modification to our products controller will allow customers to search products. We need to make a small change to the constructor, to ensure that it knows when to deal with search requests. Then we need to create a search function to search products, store the results, and display them in a view. Constructor changes A simple switch statement can be used to detect if we are viewing a product, performing a search, or viewing all of the products in the database as a list. $urlBits = $this->registry->getURLBits();if( !isset( $urlBits[1] ) ){$this->listProducts();}else{switch( $urlBits[1] ){case 'view':$this->viewProduct();break;case 'search':$this->searchProducts();break;default:$this->listProducts();break;}} This works by breaking down the URL and, depending on certain aspects of the URL, different methods are called from within the controller. Search function We now need a function to actually search our products database, such as the following: private function searchProducts(){// check to see if the user has actually submitted the search formif( isset( $_POST['product_search'] ) &&$_POST['product_search'] != '' ){ Assuming the customer has actually entered something to search, we need to clean the search phrase, so it is suitable to run in our database query, and then we perform the query. The phrase is checked against the name and description of the product, with the name taking priority within the results. The highlighted code illustrates the query with prioritization. // clean up the search phrase$searchPhrase = $this->registry->getObject('db')->sanitizeData( $_POST['product_search'] );$this->registry->getObject('template')->getPage()->addTag( 'query', $_POST['product_search'] );// perform the search, and cache the results, ready for the// results template$sql = "SELECT v.name, c.path,IF(v.name LIKE '%{$searchPhrase}%', 0, 1) AS priority,IF(v.content LIKE '%{$searchPhrase}%', 0, 1)AS prioritybFROM content c, content_versions v, content_types tWHERE v.ID=c.current_revision AND c.type=t.IDAND t.reference='product' AND c.active=1AND ( v.name LIKE '%{$searchPhrase}%' OR v.contentLIKE '%{$searchPhrase}%' )ORDER BY priority, priorityb ";$cache = $this->registry->getObject('db')->cacheQuery( $sql );if( $this->registry->getObject('db')->numRowsFromCache( $cache ) == 0 ){// no results from the cached query, display the no results// template} If there are some products matching the search, then we display the results to the customer. else{// some results were found, display them on the results page// IMPROVEMENT: paginated results$this->registry->getObject('template')->getPage()->addTag( 'results', array( 'SQL', $cache ) );$this->registry->getObject('template')->buildFromTemplates('header.tpl.php','products-searchresults.tpl.php', 'footer.tpl.php');}}else{// search form not submitted, so just display the search box page$this->registry->getObject('template')->buildFromTemplates('header.tpl.php','products-searchform.tpl.php', 'footer.tpl.php');}} As the results from the query are stored in a cache, we can simply assign this cache to a template tag variable, and the results will be displayed. Of course, as we need to account for the fact that there may be no results, we must check to ensure there are some results, and if there are none, we must display the relevant template. Search results Finally, we need a results page to display these results on. <h2>Products found...</h2><p>The following products were found, matching your search for{query}.</p><ul><!-- START results --><li><a href="products/view/{path}">{ name}</a></li><!-- END results --></ul> Our search results page looks like this: Improving searches We could improve this search function by making it applicable for all types of content managed by the framework. Obviously if we were going to do this, it would need to be taken out of the products controller, perhaps either as a controller itself, or as a core registry function, or as part of the main content/pages controller. The results could either be entirely in a main list, with a note of their type of content, or tabbed, with each type of content being displayed in a different tab. The following diagrams represent these potential Search Results pages.   And, of course, the tab-separated search results.
Read more
  • 0
  • 0
  • 2173
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $15.99/month. Cancel anytime
article-image-media-file-management-joomla-ftp-and-third-party-extensions
Packt
29 Jan 2010
5 min read
Save for later

Media File management in Joomla with FTP and Third-party Extensions

Packt
29 Jan 2010
5 min read
Alternative method of managing files and media Depending on your circumstances, you may or may not have login access to your web hosting server. If you do not, then one of your only options for uploading files will be to use the Joomla! Media Manager, or the option of third-party Joomla! Extensions. If you do have web server access, then by using a method called FTP (File Transfer Protocol), you will be able to gain greater control over your file management. FTP is a standard network protocol that is used to exchange and manipulate files over a computer network. A common use of FTP is to transfer files over the Internet between a local computer and a web server, which is exactly what we are after! FTP clients There are numerous FTP clients (programs) that can be used to transfer files. Some of these graphically show the file and transfer processes, making the management of your files from your computer to your web server very easy to do. FTP programs FTP programs range from no cost applications through to commercial software. Which one you choose to use will be down to personal preference. Most of these programs provide drag and drop features as well as easy directory navigation tools: There are excellent FTP programs for all major operating systems. Some popular options for Windows and Mac are: Windows FileZilla CuteFTP SmartFTP WS_FTP cURL Mac FileZilla Transmit Cyberduck CuteFTP Fetch FTP Comm and in Terminal If you perform a search using a popular search engine, you will obtain a definitive list of FTP programs. A suggestion would be to download a trial version of these to see which one suits your operating system and requirements. For the purpose of this topic, I have chosen to use and take screenshots from an FTP program called "Transmit". It is a commercial product, but personally one of my favorites. For those whose use MAC computers, Transmit is recognized as a wonderful FTP tool. Connecting using an FTP program Almost all FTP programs require similar information in order to connect to the web server. Depending on the program you are using, the naming of these fields may be slightly different. In order to connect, we need the following information which is usually derived from setting up a user account (with FTP permissions) on your web hosting control panel: Server This is the server address that you wish to connect to. Typically this can look like ftp.yourserver.com. Depending on the domain name settings, it can sometimes be your domain name, such as www.yourserver.com. User Name This is your web server account username. Often this can be in the format of [email protected]. Password This is your web server account password. Initial Path Some programs offer the ability to set an initial directory to navigate to upon login. If you do not have this option, then do not worry. Port If the server requires connections on a port other than the default one, some programs offer you the ability to enter in a port number. It is best to leave this as the default setting unless you know what you are doing. If you are having any issues connecting, then it's best to contact your web hosting administrator in order to check your login access details. There are typically three types of FTP login methods available. These are: Anonymous FTP access This is an easy connection method as you do not need to include any user information. Sometimes software companies offer updates or corporate and government websites offer forms and content to be downloaded via an anonymous connection method. Username A simplified but restricted access level where you will be required to enter just a username. This type of FTP login is often used in school and intranet environments. Username and Password This is a more restricted security access level where the user requires both a username and password in order to access the server. This method is often used by web hosting companies who offer people the ability to upload files to the web server. If your FTP connection is set to username (or username and password), then you should see a dialog box on the screen. This will prompt you to enter your security access details: Once connected, you will need to navigate to your webroot folder. Depending on your web server, this area may be named httpdocs, mainwebsite_html, public_html, or other naming conventions. It will be inside this directory where your Joomla! website files will reside. When you have located your main http documents area and clicked to navigate inside this, you will see the default Joomla! media folder named images. When you have successfully navigated to your remote main media folder (or any of the subfolders within this), you will need to make sure that you also navigate locally to the folders or files you wish to upload. Most FTP programs offer you the ability to create new directories, and drag and drop files from your local computer to the web server. By using an FTP program, you can gain additional control over your website files and content. FTP programs can allow you to: Create files and directories Rename files and directories Move files and directories Delete files and directories Set file and directory permissions FTP programs offer you the most flexibility in managing your website files, but it is important to take care when using FTP programs. By connecting to your directory structure on the web server, you are navigating amongst core Joomla! files.
Read more
  • 0
  • 0
  • 3455

article-image-methods-animation-effects-jquery-14
Packt
29 Jan 2010
6 min read
Save for later

Methods for Animation Effects with jQuery 1.4

Packt
29 Jan 2010
6 min read
Some of the examples in this article use the $.print() function to print results to the page. Pre-packaged effects These methods allow us to quickly apply commonly-used effects with a minimum of configuration. .show() Display the matched elements. .show([duration][, callback]) Parameters duration (optional): A string or number determining how long the animation will run callback (optional): A function to call once the animation is complete Return value The jQuery object, for chaining purposes. Description With no parameters, the .show() method is the simplest way to display an element. $('.target').show(); The matched elements will be revealed immediately with no animation. This is roughly equivalent to calling .css('display', 'block'), except that the display property is restored to whatever it was initially. If an element has a display value of inline, then is hidden and shown, it will once again be displayed inline. When a duration is provided, .show() becomes an animation method. The .show() method animates the width, height, and opacity of the matched elements simultaneously. Durations are given in milliseconds; higher values indicate slower animations, not faster ones. The 'fast' and 'slow' strings can be supplied to indicate durations of 200 and 600 milliseconds, respectively. If supplied, the callback is fired once the animation is complete. This can be useful for stringing different animations together in sequence. The callback is not sent any arguments, but this is set to the DOM element being animated. If multiple elements are animated, it is important to note that the callback is executed once per matched element, not once for the animation as a whole. We can animate any element, such as a simple image: <div id="clickme">Click here</div><img id="book" src="book.png" alt="" width="100" height="123" /> With the element initially hidden, we can show it slowly. $('#clickme').click(function() {$('#book').show('slow', function() {$.print('Animation complete.');});}); .hide() Hide the matched elements. .hide([duration][, callback]) Parameters duration (optional): A string or number determining how long theanimation will run callback (optional): A function to call once the animation is complete Return value The jQuery object, for chaining purposes. Description With no parameters, the .hide() method is the simplest way to hide an element. $('.target').hide(); The matched elements will be hidden immediately, with no animation. This is roughly equivalent to calling .css('display', 'none'), except that the value of the display property is saved in jQuery's data cache so that display can later be restored to its initial value. If an element has a display value of inline, and then is hidden and shown, it will once again be displayed inline. When a duration is provided, .hide() becomes an animation method. The .hide() method animates the width, height, and opacity of the matched elements simultaneously. When these properties reach 0, the display style property is set to none to ensure that the element no longer affects the layout of the page. Durations are given in milliseconds; higher values indicate slower animations, not faster ones. The 'fast' and 'slow' strings can be supplied to indicate durations of 200 and 600 milliseconds, respectively. If supplied, the callback is fired once the animation is complete. This can be useful for stringing different animations together in sequence. The callback is not sent any arguments, but this is set to the DOM element being animated. If multiple elements are animated, it is important to note that the callback is executed once per matched element, not once for the animation as a whole. We can animate any element, such as a simple image: <div id="clickme">Click here</div><img id="book" src="book.png" alt="" width="100" height="123" /> With the element initially shown, we can hide it slowly. $('#clickme').click(function() {$('#book').hide('slow', function() {$.print('Animation complete.');});}); .toggle() Display or hide the matched elements. .toggle([duration][, callback]).toggle(showOrHide) Parameters (first version) duration (optional): A string or number determining how long the animation will run callback (optional): A function to call once the animation is complete Parameters (second version) showOrHide: A Boolean indicating whether to show or hide the elements Return value The jQuery object , for chaining purposes. Description With no parameters, the .toggle() method simply toggles the visibility of elements: $('.target').toggle(); The matched elements will be revealed or hidden immediately with no animation. If the element is initially displayed, it will be hidden; if hidden, it will be shown. The display property is saved and restored as needed. If an element has a display value of inline, then is hidden and shown, it will once again be displayed inline. When a duration is provided, .toggle() becomes an animation method. The .toggle() method animates the width, height, and opacity of the matched elements simultaneously. When these properties reach 0 after a hiding animation, the display style property is set to none to ensure that the element no longer affects the layout of the page. Durations are given in milliseconds; higher values indicate slower animations, not faster ones. The 'fast' and 'slow' strings can be supplied to indicate durations of 200 and 600 milliseconds, respectively. If supplied, the callback is fired once the animation is complete. This can be useful for stringing different animations together in sequence. The callback is not sent any arguments, but this is set to the DOM element being animated. If multiple elements are animated, it is important to note that the callback is executed once per matched element, not once for the animation as a whole. We can animate any element, such as a simple image: <div id="clickme">Click here</div><img id="book" src="book.png" alt="" width="100" height="123" /> We will cause .toggle() to be called when another element is clicked. $('#clickme').click(function() {$('#book').toggle('slow', function() {$.print('Animation complete.');});}); With the element initially shown, we can hide it slowly with the first click: A second click will show the element once again: The second version of the method accepts a Boolean parameter. If this parameter is true, then the matched elements are shown; if false, the elements are hidden. In essence, the following statement $('#foo').toggle(showOrHide); is equivalent to: if (showOrHide) {$('#foo').show();}else {$('#foo').hide();} There is also an event method named .toggle().
Read more
  • 0
  • 0
  • 2100

article-image-enhancing-user-experience-php-5-ecommerce-part-3
Packt
29 Jan 2010
8 min read
Save for later

Enhancing the User Experience with PHP 5 Ecommerce: Part 3

Packt
29 Jan 2010
8 min read
Help! It's out of stock! If we have a product that is out of stock, we need to make it possible for our customers to sign up to be alerted when they are back in stock. If we don't do this, then they will be left with the option of either going elsewhere, or regularly returning to our store to check on the stock levels for that particular product. To try and discourage these customers from going elsewhere a "tell me when it is back in stock" option saves them the need to regularly check back, which would be off-putting. Of course, it is still likely that the customer may go elsewhere; however, if our store is niche, and the products are not available elsewhere, then if we give the customer this option they will feel more valued. There are a few stages involved in extending our framework to support this: Firstly, we need to take into account stock levels. If a product has no stock, we need to insert a new template bit with an "alert me when it is back in stock" form. We need a template to be inserted when this is the case. We then need functionality to capture and store the customer's e-mail address, and possibly their name, so that they can be informed when it is back in stock. Next, we need to be able to inform all of the customers who expressed an interest in a particular product when it is back in stock. Once our customers have been informed of the new stock level of the product, we need to remove their details from the database to prevent them from being informed at a later stage that there are more products in stock. Finally, we will also require an e-mail template, which will be used when sending the e-mail alerts to our customers. Detecting stock levels With customizable products, stock levels won't be completely accurate. Some products may not require stock levels, such as gift vouchers and other non-tangible products. To account for this, we could either add a new field to our database to indicate to the framework that a products stock level isn't required for that particular product, or we could use an extreme or impossible value for the stock level, for example -1 to indicate this. Changing our controller We already have our model set to pull the product stock level from the database; we just need our controller to take this value and use different template bits where appropriate. We could also alter our model to detect stock levels, and if stock is required for a product. if( $productData['stock'] == 0 ){$this->registry->getObject('template')->addTemplateBit( 'stock', 'outofstock.tpl.php' );}elseif( $productData['stock'] > 0 ){$this->registry->getObject('template')->addTemplateBit( 'stock', 'instock.tpl.php' );}else{$this->registry->getObject('template')->getPage()->addTag( 'stock', '' );} This simple code addition imports a template file into our view, depending on the stock level. Out of stock: a new template bit When the product is out of stock, we need a template to contain a form for the user to complete, so that they can register their interest in that product. <h2>Out of stock!</h2><p>We are <strong>really</strong> sorry, but this product is currentlyout of stock. If you let us know your name and email address, wewill let you know when it is back in stock.</p><form action="products/stockalert/{product_path}" method="post"><label for="stock_name">Your name</label><input type="text" id="stock_name" name="stock_name" /><label for="stock_email">Your email address</label><input type="text" id="stock_email" name="stock_email" /><input type="submit" id="stock_submit" name="stock_submit"value="Let me know, when it is back in stock!" /></form> Here we have the form showing our product view, allowing the customer to enter their name and e-mail address: Tell me when it is back in stock please! Once a customer has entered their name, e-mail address, and clicked on the submit button, we need to store these details and associate them with the product. This is going to involve a new database table to maintain the relationship between products and customers who wish to be notified when they are back in stock. Stock alerts database table We need to store the following information in the database to manage a list of customers interested in being alerted when products are back in stock: Customer name Customer e-mail address Product In terms of a database, the following table structure would represent this: Field Type Description ID Integer (Primary Key, Auto Increment) The ID for the stock alert request Customer Varchar The customer's name Email Varchar The customer's e-mail address ProductID Integer The ID of the product the customer wishes to be informed about when it is back in stock The following SQL represents this table: CREATE TABLE `product_stock_notification_requests` (`ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,`customer` VARCHAR( 100 ) NOT NULL ,`email` VARCHAR( 255 ) NOT NULL ,`product` INT NOT NULL ,`processed` BOOL NOT NULL ,INDEX ( `product` , `processed` )) ENGINE = INNODB COMMENT = 'Customer notification requests fornew stock levels'ALTER TABLE `product_stock_notification_requests` ADD FOREIGN KEY ( `product` ) REFERENCES `book4`.`content` (`ID`)ON DELETE CASCADE ON UPDATE CASCADE  More controller changes Some modifications are needed to our product's controller to process the customer's form submission and save it in the stock alerts database table. In addition to the following code, we must also change our switch statement to detect that the customer is visiting the stockalert section, and that the relevant function should be called. private function informCustomerWhenBackInStock(){$pathToRemove = 'products/stockalert/';$productPath = str_replace( $pathToRemove, '', $this->registry->getURLPath() );require_once( FRAMEWORK_PATH . 'models/products/model.php');$this->model = new Product( $this->registry, $productPath ); Once we have included the model and checked that the product is valid, all we need to do is build our insert array, containing the customer's details and the product ID, and insert it into the notifications table. if( $this->model->isValid() ){ $pdata = $this->product->getData(); $alert = array(); $alert['product'] = $pdata['ID']; $alert['customer'] = $this->registry->getObject('db')-> sanitizeData( $_POST['stock_name'] ); $alert['email'] = $this->registry->getObject('db')-> sanitizeData( $_POST['stock_email'] ); $alert['processed'] = 0; $this->registry->getObject('db')-> insertRecords('product_stock_notification_requests', $alert ); // We then inform the customer that we have saved their request. $this->registry->getObject('template')->getPage()-> addTag('message_heading', 'Stock alert saved'); $this->registry->getObject('template')->getPage()-> addTag('message_heading', 'Thank you for your interest in this product, we will email you when it is back in stock.'); $this->registry->getObject('template')-> buildFromTemplates('header.tpl.php', 'message.tpl.php', 'footer.tpl.php');} If the product wasn't valid, we tell them that, so they know the notification request was not saved. else{ $this->registry->getObject('template')->getPage()-> addTag('message_heading', 'Invalid product'); $this->registry->getObject('template')->getPage()-> addTag('message_heading', 'Unfortunately, we could not find the product you requested.'); $this->registry->getObject('template')-> buildFromTemplates('header.tpl.php', 'message.tpl.php', 'footer.tpl.php');}} This code is very basic, and does not validate e-mail address formats, something which must be done before we try to send any e-mails out. It is back! Once the product is back in stock, we need to then alert those customers that the product which they were interested in is back in stock, and that they can proceed to make their purchase. This isn't something we can implement now, as we don't have an administrative interface in place yet. However, we can discuss what is involved in doing this: The administrator alters the stock level. Customers interested in that product are looked up. E-mails for each of those customers are generated with relevant details, such as their name and the name of the product being automatically inserted. E-mails are sent to the customers. The database contains a processed field, so once an e-mail is sent, we can set the processed value to 1, and then once we have alerted all of our customers, we can delete those records. This covers us in the unlikely event that all the new stock sells out while we are e-mailing customers, and a new customer completes the notification form.
Read more
  • 0
  • 0
  • 980

article-image-enhancing-user-experience-php-5-ecommerce-part-2
Packt
29 Jan 2010
6 min read
Save for later

Enhancing the User Experience with PHP 5 Ecommerce: Part 2

Packt
29 Jan 2010
6 min read
Providing wish lists Wish lists allow customers to maintain a list of products that they would like to purchase at some point, or that they would like others to purchase for them as a gift. Creating the structure To effectively maintain wish lists for customers, we need to keep a record of: The product the customer desires The quantity of the product If they are a logged-in customer, their user ID If they are not a logged-in customer, some way to identify their wish-list products for the duration of their visit to the site The date they added the products to their wish list The priority of the product in their wish lists; that is, if they really want the product, or if it is something they wouldn't mind having Let's translate that into a suitable database table that our framework can interact with: Field Type Description ID Integer (Primary Key, Auto Increment) A reference for the database Product Integer The product the user wishes to purchase Quantity Integer The number of them the user would like Date added Datetime The date they added the product to their wish list Priority Integer Relative to other products in their wish list, and how important is this one Session ID Varcharr The user's session id(so they don't need to be logged in) IP Address Varchar The user's IP address (so they don't need to be logged in) By combining the session ID and IP address of the customer, along with the timestamp of when they added the product to their wish list, we can maintain a record of their wish list for the duration of their visit. Of course, they would need to register, or log in, before leaving the site, for their wish list to be permanently saved. This also introduces an element of maintenance to this feature, as once a customer who has not logged in closes their session, their wish-list data cannot be retrieved, so we would need to implement some garbage collection functions to prune this table. The following SQL represents this table: CREATE TABLE `wish_list_products` (`ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`product` INT NOT NULL,`quantity` INT NOT NULL,`user` INT NOT NULL,`dateadded` TIMESTAMP NOT NULLDEFAULT CURRENT_TIMESTAMP,`priority` INT NOT NULL,`sessionID` VARCHAR( 50 ) NOT NULL,`IPAddress` VARCHAR( 50 ) NOT NULL,INDEX ( `product` )) ENGINE = INNODB COMMENT = 'Wish list products'ALTER TABLE `wish_list_products` ADD FOREIGN KEY ( `product` ) REFERENCES `book4`.`content` (`ID`)ON DELETE CASCADE ON UPDATE CASCADE; Saving wishes Now that we have a structure in place for storing wish-list products, we need to have a process available to save them into the database. This involves a link or button placed on the product view, and either some modifications to our product controller, or a wish-list controller, to save the wish. As wish lists will have their own controller and model for viewing and managing the lists, we may as well add the functionality into the wish-list controller. So we will need: a controller a link in our product view Wish-list controller The controller needs to detect if the user is logged in or not; if they are, then it should add products to the user's wish list; otherwise, it should be added to a session-based wish list, which lasts for the duration of the user's session. The controller also needs to detect if the product is valid; we can do this by linking it up with the products model, and if it isn't a valid product, the customer should be informed of this. Let's look through a potential addProduct() method for our wish-list controller. /** * Add a product to a user's wish list * @param String $productPath the product path * @return void */ We first check if the product is valid, by creating a new product model object, which informs us if the product is valid. private function addProduct( $productPath ){// check product path is a valid and active product$pathToRemove = 'wishlist/add/';$productPath = str_replace( $pathToRemove, '',$this->registry->getURLPath() );require_once( FRAMEWORK_PATH . 'models/products/model.php');$this->product = new Product( $this->registry, $productPath );if( $this->product->isValid(){// check if user is logged in or notif( $this->registry->getObject('authenticate')->loggedIn() == true ){//Assuming the user is logged in, we can also store their ID,// so the insert data is slightly different. Here we insert the// wish into the database.$wish = array();$pdata = $this->product->getData();$wish['product'] = $pdata['ID'];$wish['quantity'] = 1;$wish['user'] = $this->registry->getObject('authenticate')->getUserID();$this->registry->getObject('db')->insertRecords('wish_list_products', $wish );// inform the user$this->registry->getObject('template')->getPage()->addTag('message_heading', 'Product added to your wish list');$this->registry->getObject('template')->getPage()->addTag('message_heading', 'A ' . $pdata['name'].' has been added to your wish list');$this->registry->getObject('template')->buildFromTemplates('header.tpl.php', 'message.tpl.php','footer.tpl.php');} The customer isn't logged into the website, so we add the wish to the database, using session and IP address data to tie the wish to the customer. else{// insert the wish$wish = array();$wish['sessionID'] = session_id();$wish['user'] = 0;$wish['IPAddress'] = $_SERVER['REMOTE_ADDR'];$pdata = $this->product->getData();$wish['product'] = $pdata['ID'];$wish['quantity'] = 1;$this->registry->getObject('db')->insertRecords('wish_list_products', $wish );// inform the user$this->registry->getObject('template')->getPage()->addTag('message_heading','Product added to your wish list');$this->registry->getObject('template')->getPage()->addTag('message_heading', 'A ' . $pdata['name'].' has been added to your wish list');$this->registry->getObject('template')->buildFromTemplates('header.tpl.php', 'message.tpl.php','footer.tpl.php');}} The product wasn't valid, so we can't insert the wish, so we need to inform the customer of this. else{// we can't insert the wish, so inform the user$this->registry->getObject('template')->getPage()->addTag('message_heading', 'Invalid product');$this->registry->getObject('template')->getPage()->addTag('message_heading', 'Unfortunately, the product youtried to add to your wish list was invalid, and was notadded, please try again');$this->registry->getObject('template')->buildFromTemplates('header.tpl.php', 'message.tpl.php','footer.tpl.php');}} Add to wish list To actually add a product to our wish list, we need a simple link within our products view. This should be /wishlist/add/product-path. <p><a href="wishlist/add/{product_path}"title="Add {product_name} to your wishlist">Add to wishlist.</a></p> We could encase this link around a nice image if we wanted, making it more user friendly. When the user clicks on this link, the product will be added to their wish list and they will be informed of that.
Read more
  • 0
  • 0
  • 1017
article-image-shipping-modules-magento-part-1
Packt
29 Jan 2010
10 min read
Save for later

Shipping Modules in Magento: Part 1

Packt
29 Jan 2010
10 min read
What shipping modules do Shipping modules are used to define the handling of the order, before it goes through the payment method section of the order process. They take the order itself and decide how to go about charging and delivering it to the customer. Magento takes the order through each shipping module that is installed and active in the system. Each shipping module is then able to process the order currently in the cart and present any available options to the user, from what it sees in the order. For example: we have a shipping module in our system that provides free delivery to people located within the UK and ordering over £40. Let's presume that we are ordering £50 worth of goods and are located within the UK. When the order is sent through this module, it checks whether or not the user is in the UK and the order total is over £40. If these conditions are met, (which our order does), then we are presented with a free delivery option, among others, to choose during our order process. This is a very simple version of what a shipping module can do. The full range of what can be done using shipping modules can be grasped by looking at Shipping Modules on Magento Connect and finding what it has on offer. Here's a small range of what has been made public: Royal Mail UK, EU, and Worldwide Shipping module — For calculation and handling of all of Royal Mail's shipping methods using weight and distance. This module sends key product information to Royal Mail via their API, authenticating with information that the Magento store administrator has input, and outputs pricing for various shipping options on the current order. Regional Free Shipping module — Gives the Magento administrator the option to allow free shipping by region, instead of by country. This provides a choice to the store administrator of breaking down free shipping further than country. For example, this would be good for someone who runs a store based in Nottingham that wants to reward local customers in the East Midlands, as opposed to simply giving free shipping to the entire United Kingdom. Basic Store Pickup Shipping module — Enables customers to choose between picking up the item themselves and having it delivered to them. This is advantageous for companies which use Magento and have a physical store presence with stock held. Magento Connect can be accessed at the following URL:http://www.magentocommerce.com/magento-connect. The three core types of shipping module can be summarized in the following: Third-party API and/or web service integration. For integration with existing couriers that have web-based APIs or web services that offer the same for organization of your shipping. Many existing services make an API available to us for integrating into Magento. We should check Magento Connect for any existing modules that others have created. Using customer data to provide unique calculations and opportunities to certain users. Anything that the customer puts in it while checking out can be used for this type of module. Shipping methods that involve a physical store or location for additional options that compliment others. We could theoretically build up a set of stores under the Magento store company's business. We could then link them up with local computers at the locations and use the shipping module to check for stocks at each location. We should do that before suggesting the store as a location for the user to be able to pick up the item. How to begin with a shipping module Here we'll be learning about how to begin with a shipping module. This is the skeletal structure of a shipping module that we can use as a template for any shipping module which we create. We will also be using it to create a very basic shipping module at the end of this article. For the purpose of following this tutorial, we will be creating all files in /app/code/local/MagentoBook/ShippingModule/ , which will be the base directory for all files created (from this point onwards). We must make sure that this directory and sub-directory are set up before continuing onwards. This means that if the file is declared to be /hello/world.php, we place this on the end of our initial base address and it becomes /app/code/local/MagentoBook/ShippingModule/hello/world.php Please start by creating the directory MagentoBook in /app/code/local/ and a sub-directory within that called ShippingModule, creating the directory structure /MagentoBook/ShippingModule/. The configuration files We create /app/code/local/MagentoBook/ShippingModule/etc/config.xml in our module's folder. Here, we'll place the following code which will declare our new module for use, make it depend on Mage_Shipping being enabled, set it at version 0.1.0 and allow it to use the existing global database connection which is set up for our store. <?xml version="1.0"?><config> <modules> <MagentoBook_ShippingModule> <version>0.1.0</version> <depends> <Mage_Shipping /> </depends> </MagentoBook_ShippingModule> </modules> <global> <models> <shippingmodule> <class>MagentoBook_ShippingModule_Model</class> </shippingmodule> </models> <resources> <shippingmodule_setup> <setup> <module>MagentoBook_ShippingModule</module> </setup> <connection> <use>core_setup</use> </connection> </shippingmodule_setup> </resources> </global> <default> <carriers> <shippingmodule> <model>MagentoBook/carrier_ShippingModule</model> </shippingmodule> </carriers> </default></config> Let's walk back through this code and go over what each individual section does. We start by defining our XML header tag for the file, to ensure that it is accepted as an XML file when read by the XML parsing class in the system. <?xml version="1.0"?> We define the <config> tag, to ensure that everything within it is read as configuration variables to be loaded into Magento's configuration for whatever we define internally within this tag. <config> We define the <modules> tag, so that we're setting configuration variables for modules defined within this tag. <modules> <MagentoBook_ShippingModule> We set the module's version number to 0.1.0, to supply Magento with versioning for the module in the future, if we update and need to perform statements within the update portion of the module, so as to execute above a certain version number. <version>0.1.0</version> We have to make sure that our module cannot be activated, or possibly run, without the Mage_Shipping core shipping handler and module activated. This is vital because the module being a shipping module is simply going to cause fatal errors without the parent Mage_Shipping module providing the helper functions needed internally. <depends> <Mage_Shipping /></depends> Next, we close off our module declaration tag and modules tag. </MagentoBook_ShippingModule></modules> We set up our <global> tag to define global assets to Magento. <global> Next, we define the <models> tag to define global models to the system and for setting up our module's default model to be one of those global models which is automatically loaded. <models> <shippingmodule> <class>MagentoBook_ShippingModule_Model</class> </shippingmodule></models> Next, we define the <resources>tag, so that we can configure the database resources available to the module within the system. <resources> Defining the <resources> tag allows us to include a setup file with our module that accesses the database. This helps if we need to load in any variables (such as default table rate rules) for our module, or for loading additional data required locally by the module, when calculating the shipping rates. <shippingmodule_setup> <setup> <module>MagentoBook_ShippingModule</module> </setup> Here, we'll use the core database connection (the default one), and ensure that we do not overwrite the database connection set up for this particular module. <connection> <use>core_setup</use> </connection> We close off all tag pairs, besides <config>, that have been opened at this point. </shippingmodule_setup> </resources></global> Finally, we end the configuration file with a declaration that our module is a shipping module and should be processed as one, within the system. This will register the module to the system, so that it can actually display shipping methods to the user on checkout. Without this, nothing will be returned to the user from this module. <default> <carriers> <shippingmodule> <model>MagentoBook/carrier_ShippingModule</model> </shippingmodule> </carriers></default> We close the <config> tag to end the XML configuration file. </config> After we've done this, we need to declare our module to Magento by creating a configuration file in /app/etc/modules/MagentoBook_ShippingModule.xml. Next, we place the following code in our new configuration file, to allow this module to interact with Magento and be turned on/off under the System Configuration menu: <?xml version="1.0"?><config> <modules> <MagentoBook_ShippingModule> <active>true</active> <codePool>local</codePool> </MagentoBook_ShippingModule> </modules></config> We break this file down into the individual lines: <?xml version="1.0"?> The <config> wrapper tag defines the XML to be read, as a configuration of something inside Magento. <config> The <modules> wrapping tag defines this as a module to Magento. <modules> The next tag is used for defining that this is the configuration of a module entitled <MagentoBook_ShippingModule> and for applying the settings inside the tag to the module: <MagentoBook_ShippingModule> We make sure that it's active by default (this will be overwritten when activated/deactivated in the Magento administrative back-end). <active>true</active> The <code pool> tag is used for keeping this module in our local module's directory. <codePool>local</codePool> Closing tags are for closing the XML tags that we started the <config> tag with. </MagentoBook_ShippingModule> </modules></config> Now that we have the configuration set up, to allow the module to be managed within Magento and versioning control to allow for upgrades in the future, we can progress onto the module itself. It also means that we can now turn our module on/off within the administration. To do this, we go to System|Configuration , then to Advanced under the Advanced heading on the left-hand side. Once here, we will be presented Enable/Disable dropdowns for each module installed in the system. We'll set the dropdown for our module to Disable until we have completed the adaptor model and administration setup. This will prevent the module from crashing the system, while it is incomplete. We will re-activate the module once we're ready to see the output.
Read more
  • 0
  • 0
  • 2148

article-image-shipping-modules-magento-part-2
Packt
29 Jan 2010
8 min read
Save for later

Shipping Modules in Magento: Part 2

Packt
29 Jan 2010
8 min read
Appearing in the administration Once this has been done, the shipping method should appear in Shipping Methods under System->Configuration: Now, we will look at the most useful shipping module fields that are used when putting the shipping module together. These are fields with predefined names and types that have automatically processed the results that they output. Therefore, they require no additional coding in the adaptor module to take them on board; Magento performs these methods straight out of the box. Free shipping If we want to enable an automatic price-based amount for free shipping with our method, we can add in a field called free_shipping_enable and combine this with another field by the name of free_shipping_subtotal. When free_shipping_enable is set to Enabled by the Magento administrator, then Magento will automatically take free_shipping_subtotal into account and offer free shipping if the total amount is above the value of free_shipping_subtotal. If this field is disabled, Magento will simply process using the default shipping calculation behavior of the module.   The fields are set up as follows, with sort_order and show_in_ values varying: <free_shipping_enable translate="label"> <label>Free shipping with minimum order amount</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_enabledisable</source_model> <sort_order>21</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store></free_shipping_enable><free_shipping_subtotal translate="label"> <label>Minimum order amount for free shipping</label> <frontend_type>text</frontend_type> <sort_order>22</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store></free_shipping_subtotal> Handling Handling charges sometimes come into the equation and need to be added onto the overall transaction. Magento enables us to do this using the following source models to present what we want to achieve: <handling_type translate="label"> <label>Calculate Handling Fee</label> <frontend_type>select</frontend_type> <source_model>shipping/source_handlingType</source_model> <sort_order>10</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store></handling_type><handling_action translate="label"> <label>Handling Applied</label> <frontend_type>select</frontend_type> <source_model>shipping/source_handlingAction</source_model> <sort_order>11</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store></handling_action><handling_fee translate="label"> <label>Handling fee</label> <frontend_type>text</frontend_type> <sort_order>12</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store></handling_fee> Restricting a shipping method to certain countries This will allow us to present the option to the administrator for filtering the shipping method to be only accessible to certain countries. In practice, this means that if we wanted to offer only one type of delivery to the United Kingdom, then we could do so simply by selecting United Kingdom from the multi-select field created by the following declaration. The Magento administrator can choose the specific countries from the multiple select list. Only orders from those countries that we have created shipping methods for will be processed in the shipping module. This enables them to choose any number of countries for restricting this shipping method to . sallowspecific translate="label"> <label>Ship to applicable countries</label> <frontend_type>select</frontend_type> <sort_order>90</sort_order> <frontend_class>shipping-applicable-country</frontend_class><source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store></sallowspecific><specificcountry translate="label"> <label>Ship to Specific countries</label> <frontend_type>multiselect</frontend_type> <sort_order>91</sort_order><source_model>adminhtml/system_config_source_country</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store></specificcountry><showmethod translate="label"> <label>Show method if not applicable</label> <frontend_type>select</frontend_type> <sort_order>92</sort_order><source_model>adminhtml/system_config_source_yesno</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store></showmethod> Using our template to create a shipping method Now that we have our bare-bones shipping module, we continue with the creation of something that we can see an outcome from. From this we should be able to start to put together our own shipping module tailor-made for future needs. The purpose of what we are going to build is going to be very simple: we're going to create a shipping module that meets the following parameters: It has a handling fee, either per product or for the entire order It can be limited to specific countries It can set a simple flat-rate shipping cost, if 10 products or more are being ordered It can set another simple flat-rate shipping cost, if 10 products or less are being ordered All of the above can be configured via the Magento administration Before progressing, we delete the previous shipping module from our installation to make sure that it does not interfere with what we'll be building. To do this, we go back to the Magento Downloader  and select Uninstall from the module's supporting dropdown before committing the changes. The configuration files This time, we'll go with the directory MagentoBook and the name FullShippingModule. For this, our /app/code/local/MagentoBook/ShippingModule/MagentoBook/FullShippingModule/etc/config.xml file will look like: <?xml version="1.0"?><config> <modules> <MagentoBook_FullShippingModule> <version>0.1.0</version> <depends> <Mage_Shipping /> </depends> </MagentoBook_FullShippingModule></modules><global> <models> <FullShippingModule> <class>MagentoBook_FullShippingModule_Model</class> </FullShippingModule> </models><resources> <fullshippingmodule_setup> <setup> <module>MagentoBook_FullShippingModule</module> </setup> <connection> <use>core_setup</use> </connection> </fullshippingmodule_setup> </resources> </global></config> We turn on FullShippingModule, and allow it to be turned off/on from within the administration. Then, we create /app/etc/modules/MagentoBook_FullShippingModule.xml and place the following in it: <?xml version="1.0"?><config> <modules> <MagentoBook_FullShippingModule> <active>true</active> <codePool>local</codePool> </MagentoBook_FullShippingModule> </modules></config> Our adaptor For those interested in cutting down on code, unnecessary comments have been removed (which were included in the previous adaptor in this article). We place the following code in: /app/code/local/MagentoBook/FullShippingModule/Model/Carrier/FullBoneMethod.php <?phpclass MagentoBook_FullShippingModule_Model_Carrier_FullBoneMethodextends Mage_Shipping_Model_Carrier_Abstract{ protected $_code = 'fullshippingmodule'; public function collectRates(Mage_Shipping_Model_Rate_Request $request) { if (!$this->getConfigData('active')) { Mage::log('The '.$this->_code.' shipping method is not active.'); return false; } $handling = $this->getConfigData('handling'); $result = Mage::getModel('shipping/rate_result'); $method = Mage::getModel('shipping/rate_result_method'); $items = Mage::getModel('checkout/session')->getQuote()- >getAllItems(); if (count($items) >= $this->getConfigData('minimum_item_limit')) { $code = $this->getConfigData('over_minimum_code'); $title = $this->getConfigData('over_minimum_title'); $price = $this->getConfigData('over_minimum_price'); } else { $code = $this->getConfigData('under_minimum_code'); $title = $this->getConfigData('under_minimum_title'); $price = $this->getConfigData('under_minimum_price'); } $method->setCarrier($this->_code); $method->setCarrierTitle($this->getConfigData('title')); $method->setMethod($code); $method->setMethodTitle($title); $method->setPrice($price + $handling); $result->append($method); return $result; }} In short, this will check whether there are more items in the cart than the pre-configured value of minimum_item_limit and then apply a rate if it is over the set limit. If under the limit, it applies another rate.
Read more
  • 0
  • 0
  • 941

article-image-managing-your-joomla-media-files-media-manager
Packt
29 Jan 2010
6 min read
Save for later

Managing Your Joomla! Media Files with Media Manager

Packt
29 Jan 2010
6 min read
Overview of the Joomla! Media Manager The Media Manager is a useful file management tool, which is included in the Joomla! CMS. The Media Manager tool is located within your administration area and can be accessed by using the "Quick Link" icon on your Control Panel, or by going to the Menu: Site | Media Manager: One of the main purposes of the Media Manager is to easily allow site administrators, and frontend users with permissions, the ability to upload and manage files for their Joomla! site. In circumstances where you do not have FTP (File Transfer Protocol) access to your web server, the media manager might be the only available tool with which you can add new images, videos, documents, and other files to your website. Uploading media using the Media Manager During initial site development, there are usually regular requirements to upload new files to your Joomla! site. Depending on the content for your website, this process can decrease as you move into the maintenance stages, or stay as a requirement for sites which are updated often. Media Manager settings As with all software applications, the Media Manager tool contains a set of predefined settings. Before using the Media Manager for the first time, it is recommended that you take a look at these as they offer the ability to customize media handling for your website. Depending on your file requirements, adjusting the media configuration settings now may save you time and effort down the line. Your Joomla! site Media Settings can be found by going to Site | Global Configuration. Once the page has loaded, you will then need to click on the link named System. The Media Settings area not only allows you to adjust settings related to the Media Manager, but also contains general settings for the media used throughout your Joomla! website. Information regarding each setting is as follows: The fields are: Legal Extensions (File Types)This field is a comma-separated list of file types that you want to allow to be uploaded to your Joomla! website. This setting applies to the frontend of your site, as well as the backend which includes the Media Manager tool. Maximum Size (in bytes)This field holds the maximum size of the file (in bytes) to be uploaded. This can be set to "0" if you do not wish to restrict your file upload sizes. Most web servers will have their own file size limit that is usually configurable for the server by adjusting the server information file. Path to Media FolderBy default, Joomla! has a media folder called <joomlaroot>/images. This is the area where all files will be uploaded to when using the Media Manager. You can change this value to a different directory if you wish, creating a default path for managing your media. The majority of Joomla! projects would probably leave this value as default. If you do decide to use another folder name for your media directory, it is important to leave the current /images directory on the server as this can often be used by other components. Path to Image FolderThis is generally a path where you put your images for your Joomla! Content Articles. By default, it is set to <joomlaroot>/images/stories. You can change this to be what you wish. If you want to access this folder from the Media Manager, then make this a subfolder of the "Media Folder" previously mentioned. For example, <joomlaroot><mediafoldername>/<imagefoldername>. If you do decide to use another folder name for your image directory, it is important to leave the current /images/stories directory on the server as this can often be used by other components. Restrict UploadsThis feature restricts uploads by user type. The default is set to Yes, which means that users below the status of a "Manager" will only get one folder option to upload files into. That folder is your main "Media Folder". If you set this option to No, then users will also be allowed to upload to subdirectories within your main media folder. Check MIME TypesThis is a security feature, and uses MIME Magic or Fileinfo to verify your uploaded file types. By checking the MIME file information, you help ensure users don't upload malicious files to your site. Further information about Fileinfo can be found at http://www.php.net/manual/en/book.fileinfo.php. Legal Image Extensions (File Types)This is a list of legal image extensions that you and other users are allowed to upload to your Joomla! site. The default list includes bmp, gif, jpg, and png files. Adjust, if you require further image extension types. Ignored Extensions This setting checks the file types which should be ignored for MIME checking. By default, this is left blank so all files would be included if MIME checking is turned on. Legal MIME TypesThis sets the list of legal MIME types for uploading. By default, this setting includes some file types, and it is recommended that you do not adjust this setting unless you know what you are doing. Illegal MIME TypesThis sets the list of illegal MIME types for uploading. As with the legal MIME types, it is recommended that you do not adjust this setting unless you know what you are doing. Enable Flash UploaderThe Media Manager contains an integrated Flash uploader tool. If enabled, this allows you to upload multiple files at once. The default setting is No. If you do decide to enable the Flash uploader and receive uploading issues, then disable this feature again. Issues can arise from incompatible Adobe Flash settings. If you have made adjustments to the default Joomla! Media Settings, then you will need to save these by clicking on the Save button at the top right-hand side of the page in the Global Configuration section. A confirmation message to inform you that these settings have been saved should show on the following page. Now that we have configured our site's Media Settings, let's head over to take a detailed look at the Media Manager upload feature. The Media Manager tool is located within your administration area and can be accessed by using the "Quick Link" icon on your Control Panel, or by going to the Menu: Site | Media Manager.
Read more
  • 0
  • 0
  • 4413
article-image-managing-discounts-vouchers-and-referrals-php-5-ecommerce
Packt
21 Jan 2010
3 min read
Save for later

Managing Discounts, Vouchers, and Referrals with PHP 5 Ecommerce

Packt
21 Jan 2010
3 min read
Discount codes Discount codes are a great way to both entice new customers into a store, and also to help retain customers with special discounts. The discount code should work by allowing the customer to enter a code, which will then be verified by the store, and then a discount will be applied to the order. The following are discount options we may wish to have available in our store: A fixed amount deducted from the cost of the order A fixed percentage deducted from the cost of the order The shipping cost altered, either to free or to a lower amount Product-based discounts (although we won't cover this one in the article) It may also be useful to take into account the cost of the customer's basket; after all if we have a $5 discount code, we probably wouldn't want that to apply for orders of $5 or lower, and may wish to apply a minimum order amount. Discount codes data When storing discount codes in the framework, we need to store and account for: The voucher code itself, so that we can check that the customer is entering a valid code Whether the voucher code is active, as we may wish to prepare some voucher codes, but not have them usable until a certain time, or we may wish to discontinue a code A minimum value for the customer's basket, either as an incentive for the customer to purchase more or to prevent loss-making situations (for example a $10 discount on a $5 purchase!) The type of discount: Percentage: To indicate that the discount amount is a percentage to be removed from the cost Fixed amount deducted: To indicate that the discount amount is a fixed amount to be removed from the order total Fixed amount set to shipping: To indicate that the discount amount is to be the new value for the shipping cost Discount amount; that is, the amount of discount to be applied The number of vouchers issued, if we wish to limit the number of uses of a particular voucher code An expiry date, so that if we wish to have the voucher code expire, codes with a date after the stored expiry date would no longer work Discount codes database The following table illustrates this information as database fields within a table: The default value for num_vouchers is -1, which we will use for vouchers that are not limited to a set number of issues. Field Type Description ID Integer (Primary Key, Auto increment) For the framework to reference the code Vouchercode Varchar The code the customer enters into the order Active Boolean If the code can be used Min_basket_cost Float The minimum cost of the customer's basket for the code to work for them Discount_operation ENUM('-',%','s') The type of discount Num_vouchers Integer Number of times the voucher can be used Expiry timestamp The date the voucher code expires, and is no longer usable The following code represents this data in our database: CREATE TABLE `discount_codes` (`ID` INT( 11 ) NOT NULL AUTO_INCREMENT ,`vouchercode` VARCHAR( 25 ) NOT NULL ,`active` TINYINT( 1 ) NOT NULL ,`min_basket_cost` FLOAT NOT NULL ,`discount_operation` ENUM( '-', '%', 's' ) NOT NULL ,`discount_amount` FLOAT NOT NULL ,`num_vouchers` INT( 11 ) NOT NULL DEFAULT '-1',`expiry` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,PRIMARY KEY ( `ID` )) ENGINE = INNODB DEFAULT CHARSET = latin1 AUTO_INCREMENT =1;
Read more
  • 0
  • 0
  • 4492

Packt
20 Jan 2010
8 min read
Save for later

SOA Management—OSB (aka ALSB) Management

Packt
20 Jan 2010
8 min read
Introducing Oracle Service Bus (OSB) In any distributed system, components that run on a distributed platform need to communicate or exchange messages with each other. In SOA based systems, services need to interact or exchange messages with other services also. Oracle Service Bus is a product that provides a platform for interaction and message exchange between services. Integration of disparate services can be a challenge. There could be a difference in messaging models—some services may support the synchronous model, whereas other services may support the asynchronous model. Some services may support HTTP protocol, whereas other services may support JMS protocol. Oracle Service Bus provides helps in solving many of these challenges by providing the following features: Support for different protocols, such as HTTP(s), FTP, JMS, E-mail, Tuxedo, and so on Support for different messaging models, such as point-to-point model, publish-subscribe model Support for different message formats, such as SOAP, E-mail, JMS, XML, and so on Support for different content types such as XML, binary, and so on Data transformation using XLST and Xquery—data mapping from one format to another format through declarative constructs Besides the integration support, OSB provides features that help in managing runtime for the integration of services. Some features are: Load balancing: Load balancing is very important when traffic volume between services is very high. Load balancing also helps to achieve high availability. Content-based routing: Routing to appropriate service based on content is very valuable in the changing business environment. OSB provides loosely-coupled bus architecture, where all services and consumers of services can be plugged into, and OSB becomes a central place for defining mediation rules between services and consumers, as shown next: At implementation level, OSB is a set of J2EE applications that run on top of WebLogic J2EE container. It uses various J2EE constructs like Enterprise Java Bean, data source, connectors, and so on. OSB uses a database for storing the reporting data. OSB can be deployed in a single server model or clustered server model. Generally, in a production environment a clustered model is used, where multiple WebLogic Servers are used for load balancing and high-availability. In such setups, multiple WebLogic Servers are front-ended by a load balancer. The following figure depicts one such clustered deployment. OSB constructs There are some constructs specific to OSB—let's learn about those constructs. Proxy service OSB provides mediation between consumer and provider services. This mediation is loosely coupled where a consumer service makes a call to intermediate service, and the intermediate service performs some transformation and routes it to producer service. This intermediate service is hosted by OSB and called Proxy service. Business service Business service is a representation of actual producer service. Business service controls the call to business service, it knows about the business service endpoint. In case of failure in calling producer service, it can retry the operation. In case there are multiple producer services, it knows about the endpoint of each producer service and provides load balancing across those endpoints. Message flow Message flow is a set of steps that are executed by the proxy service before it routes to the business service. It includes steps for data transformation, validation, reporting, and so on. Supported versions Enterprise Manager provides OSB management from release 10.2.0.5 onwards. The following is the support matrix for EM against different versions of OSB management: EM Version OSB 2.6 OSB 2.6.1 OSB 3.0 OSB 10gR3 10.2.0.5 Yes Yes Yes Yes To manage or monitor OSB from Enterprise Manager 10.2.0.5, some patches are needed on OSB servers. The following table lists the patch number for each supported OSB release: OSB version Patch ID 2.6, 2.6.1 B8SZ 3.0 SWGQ 10gR3 7NPS The SmartUpdate patching tool that comes with WebLogic installation can be used to apply these patches. Before downloading or applying these patches, check Enterprise Manager documentation for any updates on patch Ids. Discovery of Oracle Service Bus Oracle Service Bus gets discovered as part of WebLogic domain, managed server discovery.We know how Enterprise Manager Agent discovers WebLogic domain and managed servers. Along with domain, cluster and managed server targets, OSB targets are also created and persisted in the Enterprise Manager repository. Just like WebLogic domain and server targets, OSB can also be discovered and monitored, either by remote agent or local agent. In case you want to use OSB service's provisioning feature you will need to discover/monitor OSB in the local agent mode. In the local agent mode, the agent is installed where the domain admin server is running. In the remote agent mode, the agent can be on any other host on the same network. After discovery you will see the Oracle Service Bus target on the Middleware tab of the EM homepage. The following screenshot shows the OSB target on the Middleware tab. Monitoring OSB and OSB services Under the BPEL monitoring section, we learnt about the BPEL eco system that included BPEL PM, dehydration store, database listener, host, and so on, and how Enterprise Manager provides support for modeling of BPEL eco system as system. Enterprise Manager provides similar support for managing and monitoring OSB eco system. Monitoring OSB For monitoring OSB, you can go to the OSB homepage, where you can see the status and availability of OSB. It shows some other details like the host, name of the WebLogic Server Domain where OSB is installed. It also shows some coarse-grained historical view of traffic metrics—where it shows message/error/security violation rates for all the services. On the Home page there is an option to create an infrastructure system and service. The steps for creating an infrastructure system service is exactly the same as BPEL, so we will not repeat those steps and will leave it as an exercise. The following screenshot shows one such homepage after the infrastructure system services are created. OSB uses Java Message Service (JMS) queues for receiving, scheduling, dispatching of messages, it's very important to monitor JMS queues for OSB. From the OSB homepage, click on JMS Performance, and you will see the performance of JMS queues used by OSB. The following screenshot shows one such page. You can see the metrics for message inflow and messages pending. Monitoring OSB services OSB service monitoring can be divided into two parts—proxy service that receives the requests and business service that dispatches the requests. Proxy service metrics also include the metrics in message flow, where message flow processes the request. Monitoring proxy services Performance of proxy services represents the performance seen by consumers of OSB. Besides that, proxy services are hosted by OSB servers. Enterprise Manager collects some very useful metrics for proxy services. These metrics are: Status of proxy service Throughput metrics at proxy service and endpoint level Performance metrics at proxy service level and endpoint level Error metrics at service level and end point level Security violation at proxy service level To monitor the performance of message flow, there are some fine-grained metrics available, these metrics include throughput, error rate, and performance at each step in the message flow. Let's go through the console screens for OSB service monitoring. Go to the OSB Services tab from OSB homepage, on that page you will see a listing of all the services that include proxy as well as business services. You will see every proxy and business services is part of some project. OSB provides a construct project under which different services can be created; project is just a means to categorize different services. The following screenshot shows such a page where you can see the list of all the projects and services. For each service you see metrics related to throughput, errors, violations, and performance. Once you click on one of the services, you will see a page where the metrics and other details of proxy service are listed. On this page, you can see the throughput and performance chart for the proxy service. You will also see a section for the EM service model that represents a proxy service. This model is similar to the model that we had for the BPEL process. This mode has three entities: Infrastructure service: This service represents all of the components in the OSB eco system. Availability service: This service represents all of the availability tests for an OSB proxy service endpoint, it could include SOAP tests, Web transactions etc. Aggregate service: This service is just an aggregate of the previous two services. Using this service, you can monitor all of the required metrics in one place. You can see the performance of your IT infrastructure as well as the performance of partner links in one place.
Read more
  • 0
  • 0
  • 1244