Friday, September 14, 2007

Scaffolding and Decorating your web app with CakePHP

(Shunro Dozono / http://www.cba-japan.com )

(1)You can download 'decorate.php' from
http://cakephp.jp/decorate.zip
http://cakeforge.org/projects/decorate/
copy it to cake/scripts

copy_it_to_scripts_folder.PNG


(2)Set your DB-table

set_your_database_table.PNG

(3)Start baking [decorating] by using Windows Command Prompt.

prompt> your_php_path\php.exe path\decorate.php

start_decorate_script.PNG

(4)Script will bake all the files for you.

baked(decorated)files.PNG

(5)Goto http://localhost/cake/TABLENAME

baked_application.PNG

(6)CRUD (Create, Read, Update, Delete) features

crud(create).PNG

(7)CakePHP can handle "table associations"!

table_associations.PNG

(8)Complex Sorting feature

sorting.PNG


(9)Filtering(Search) feature

search_filtering.PNG

(10)You can make your own "template" design files. or you can download from
http://cakephp.seesaa.net/article/20355864.html

If you just drop your template file to "layout", it will be...
templates.PNG

(11)If you want "login" feature, CakePHP has already various types of authentification.

http://manual.cakephp.org/appendix/simple_user_auth

or if you just need only one username and password, you can download sd_auth from
http://cakeforge.org/snippet/detail.php?type=package&id=20

just "drop" the sd_auth file to app/controllers/components, and thtml desing file to app/view/layouts/. then,

Add following lines to app_controller.php(Copy from /cake to /app).

class AppController extends Controller {

var $components = array('SdAuth');

function beforeFilter()
{
// Auth Check.
if($this->SdAuth->isloggedin() == FALSE){
$this->layout = "login";
} else {
$this->layout = "default";
};
}

}


login.PNG

flash progress bar component

Flash Applets

Collection of Flash applets in various categories which allows you to create flash slideshows, flash menus, and flash text effects for as many web sites as you wish.



Flash Group & actionscripts[uk] - flv video controls

This is a Macromedia Flash discussion and coding forum

FlashMove Forum - Pre-made Progress Bar component in MX 2004

The helpful flash resource site for all your macromedia flash needs. Site features search engine, competitions, tutorials, forum, links, gallery, events, usergroup, newsletter and more.

Skinning the V2 ProgressBar Component, Part 2 @ MX DEVELOPER'S JOURNAL

In Part One of this two-part article ('Skinning the V2 ProgressBar component ,' MXDJ vol 3 issue 4) we did what we set out to do, but I just can't bear to leave the skinning-a-Button issue unresolved.

Welcome to Teoti Graphix | Teoti Graphix

Teoti Graphix, LLC (Tay-oh-tee Graphics) specializes in the development of innovative Macromedia Flash v2 Application Components for web developers and designers world-wide & 3dmodeling and web design services.

Loader / Progress Bar Component Issues. - kirupaForum

Thursday, September 13, 2007

Not Another C# Versus VB Article

By Nigel Shaw.

Introduction

This article explains the benefits of a Microsoft .NET application development organization coding in C# versus coding in VB.

It's common knowledge that VB.NET and C# are functionally equivalent. Hence a frequently-heard argument for choosing one or another is that because they are functionally equivalent, neither poses a clear advantage. This argument has merit, but because it attempts to be diplomatic and avoids subjective opinion, it fails to get to the heart of the matter.

This article does not simply consider objective arguments. Rather, I attempt to explore some of the highly subjective factors which influence developers working in VB versus C#. These subjective factors taken collectively over time contribute to a certain culture. The VB culture is different from the C# culture.

By examining the history of the two cultures and their current trends, we can make predictions about how the choice of one language or another might influence the production of quality code in a production shop.

The culture of Visual Basic

The purpose of Visual Basic was to create a mass market for software development tools. Prior to Visual Basic, application development languages were viewed as complex and restricted to the domain of skilled programmers. Visual Basic was syntactically simple, and it enabled virtually anyone with a few hours of time to learn how to create simple applications. In the days when software development was seen as more of a black art than an engineering discipline, the ability to be able to join the ranks of “software developers” was a powerful aphrodisiac for many computer users.

And join they did. Millions of “power users” of computers became millions of “software developers”. It happened that Visual Basic came along just as the demand for new software applications was escalating rapidly, driving demand and hence higher salaries for software developers.

The fact that Visual Basic was lacking in the fundamental building blocks of object oriented programming didn’t matter much at the time. Software was still relatively simple. Distributed application development was client-server at best. The web was so new that application development models for it had barely started to evolve—the business world didn’t even know where the web was going, so how could developers possibly know how to program for it? Web applications were hacked together, and it didn’t matter. To compound the hacking methodology, the sheer demand for web applications began to accelerate at a pace that exceeded even the wildest expectations by an order of magnitude. Application developer salaries skyrocketed, demand continued to increase, and the perceived need for a sane, sustainable application development model was left trailing far behind.

The peak of this trend coincided with the peak of the Internet boom. Vast armies of grossly under skilled developers were paid enormous sums of money and elevated to cult-like status to hack together anything that would even remotely resemble a software application. And Visual Basic, with its lack of formality and constraints that might slow down the hacking process, was just the right food for the frenzy.

Visual Basic was launched in March of 1991. In 2000 Microsoft announced .NET. in a move that swept the slate clean and replaced Visual Basic with what was in effect an entirely new development paradigm. The underlying classes against which programmers developed were completely replaced by the .NET Framework. The kludgy third party tools were swept aside and replaced by a clean third party tool model. The lack of inheritance and the limited implementation of polymorphism enforced for so many years by the underlying limitations of the Visual Basic engine architecture was overcome by throwing the old engine out completely.

With these changes, Visual Basic was reborn as a powerful new development platform, functionally equivalent to C#, J# and Java. In fact, of the Visual Basic of the 90’s, only two things remain today; the culture and the syntax. The culture of Visual Basic is the culture of the 90’s: build it fast, hype it up, sell it, and don’t worry about whether the story will hold together tomorrow, or even hold together at all.

To grasp how this culture affected trends in software development, it’s instructive to hear what Niklaus Wirth had to say about it in 1997. Niklaus Wirth is one of the most influential thinkers in the software world. A professor at ETH Institute in Zurich, Wirth designed Pascal, Modula 2 and Oberon. In the early 1970s, he was one of the people who proposed program development by stepwise refinement. He's the author of many important books, including "Algorithms + Data Structures = Programs" (Prentice Hall, 1975) and "Systematic Programming" (Prentice Hall, 1973) He was awarded the Turing Prize in 1984, and has also received five honorary doctorates and several other awards.

In a well known interview with Dr. Carlo Pescio, published in Software Development, June 1997, Pescio asks Wirth:

You probably know about the 'good enough software' concept popularized by Yourdon. In many senses, it's just a rationalization of what's happening in the software world: the first company hitting the market with a feature-rich product is more likely to win the battle than the careful, quality-seeking company. Do you think there is anything developers and software organizations can do about that? I guess many developers would be happy to be given more time to develop better software, but at the same time they are rushed in the name of corporate survival. 'Educating the users' seems more a wild dream than a possibility.

to which Wirth replies:

'Good enough software' is rarely good enough. It is a sad manifestation of the spirit of modern times, in which an individual's pride in his/her work has become rare. The idea that one might derive satisfaction from his or her successful work, because that work is ingenious, beautiful, or just pleasing, has become ridiculed. Nothing but economic success and monetary reward is acceptable. Hence our occupations have become mere jobs. But quality of work can be expected only through personal satisfaction, dedication and enjoyment. In our profession, precision and perfection are not a dispensable luxury, but a simple necessity.

Recently I read a final report of a research project funded by the Swiss National Science Foundation. The project's naive goals were identified as follows: First, how can easy programming be achieved (in particular, for non-experts)? Second, how can a mechanism be realized that allows hiding the difficult parts of parallel programming? After more than 30 years of programming we ought to know that the design of complex software is inherently difficult. This despite of the fact that, for decades, the industry has been advertising programmers' positions by claiming that programming is easy. Later on, when doubts arose even to the advertisers, they switched to promising a wide variety of tools to facilitate the arduous tasks. Tools became the slogan; the right tools, paired with clever tricks and serious management methods, would work wonders. Then Edsger Dijkstra called Software Engineering 'Programming in spite of the fact that you can't'.

Indeed, the woes of Software Engineering are not due to lack of tools, or proper management, but largely due to lack of sufficient technical competence. A good designer must rely on experience, on precise, logical thinking, and on pedantic exactness. No magic will do. In the light of all this it is particularly sad that in many informatics curricula, programming in the large is badly neglected. Design has become a non-topic. As a result, software engineering has become the El Dorado for hackers. The more chaotic a program looks, the smaller the danger that someone will take the trouble of inspecting and debunking it."

In a minute, we’ll look at how the culture of Visual Basic affects the quality of code produced, even today, and how the last remaining vestige of Visual Basic, the syntax, unfortunately continues to reinforce the culture.

But first, let’s review the culture of C#.

The culture of C#

To understand the culture of C# is to understand the story of Anders Hejlsberg, its chief architect. Hejlsberg deeply admired Niklaus Wirth. Wirth created the Pascal language from Algol, the first high-level language with a readable, structured and systematically defined syntax. Hejlsberg created the world’s first compiler for Pascal, and extended the language to include object-oriented capabilities (Object Pascal). Both were focused on the language’s elegance, at least in part because the language was designed as a teaching tool for students of programming languages to learn structured, and later object-oriented, development techniques.

Pascal was first embedded in a commercial development environment by Borland, with the release in November 1983 of Turbo Pascal, which employed Hejlsberg’s compiler on a licensing arrangement. Hejlsberg worked for Borland for thirteen years from 1983 to 1996 during which time he was the chief architect of Turbo Pascal and later Delphi.

Delphi, a direct competitor to Visual Basic, was regarded as vastly superior technically, even by Microsoft, who routinely plundered its inventions. To preview some of the features of each successive version of Visual Basic, it was generally recognized that one only had to look at the current version of Delphi.

Delphi, however, was hampered by a relatively insignificant development and advertising budget. While Microsoft plowed hundreds of millions of dollars into promoting Visual Basic, Borland had to rely primarily on technical excellence to drive usage through word of mouth. Hejlsberg knew his work would never achieve mainstream adoption while he remained at Borland. At the same time, Microsoft gradually came to realize that Visual Basic would never achieve the technical excellence of Delphi without Hejlsberg.

About the time when these two forces were starting to draw Hejlsberg and Microsoft together, a thunderbolt hit that would dramatically accelerate the fusion. That thunderbolt was Marc Andreessen’s endorsement of a brand new language (or at least one with a brand new name): Java.

Java’s precursor was developed by Sun’s Patrick Naughton, Mike Sheridan, and James Gosling in 1990-92, who had the far-reaching notion of connecting together small devices, such as video recorders and televisions, in cyberspace with a common programming language. The first version of Java was called “Oak” and was architecture-neutral, distributed, portable, object-oriented and secure. Although these qualities turned out to be just the qualities needed to develop applications for the web, the adoption of Oak for the web would have to wait until 1994. But the fact that Oak’s true potential would take several years to recognize was much less important than the culture in which it was born. For in 1990, Naughton, annoyed with the disparate directions in which Sun was heading, nearly quit and took his work to the more idealistic and focused neXT, owned by Steve Jobs. It was only because Sun’s CEO, Scott McNealy, solicited a report on the failings of Sun from Naughton, and heeded the report, that Naughton stayed. McNealy agreed Naughton would be allowed to create a small team of engineers outside of mainstream Sun in order to “do fewer things better."

Designed by a small team dedicated to technical excellence, Oak/Java was the antithesis of Visual Basic. Yes, it was more difficult to learn, but it was more powerful. And the proof was in the pudding. Java applications, when architected and built by skilled Java developers, were more powerful and feature-rich than the vast majority of Visual Basic applications.

Marc Andreessen, CEO of Netscape and therefore the “God of the Internet” at the time, was one of those who saw the potential of this new language. In 1994 he told the San Jose Mercury News: "What these guys are doing is undeniably, absolutely new. It's great stuff."

Coming from most people, such an endorsement would have been just another spark. Coming from Andreessen, it was the thunderbolt that shocked the world into a near-frenzied adoption of Java, and ultimately brought Microsoft and Hejlsberg together.

For Java was not perfect either, and by then the brilliant Hejlsberg was envisioning the next generation of application development language. Hejlsberg envisioned a language which would fully embrace the emerging component model for application development by making the three key constructs of component development—properties, methods and events—first class elements of the language.

In Java, for instance, properties don’t really exist. They’re “faked” by using the get xxx and set xxx syntax. In a property inspector they show up as “xxx” and you have to know that you put the get and set in the right places. This and other anomalies made Hejlsberg the perfectionist uncomfortable. He felt that the ideal language would require no such kludges or workarounds, but should instead roll all of the core constructs right into the syntax, giving the programmer a “one stop” experience. The problem was that this would require fundamental rewiring of the compiler, and significant research and development expense.

With Java rapidly gaining ground, by 1996 Microsoft was getting very concerned. They were taken off guard by the fact that an elegant, precise language that required a significant degree of programming skill and dedication to use effectively was making headway against Visual Basic. They also recognized that they needed more than just some reworking of the Visual Basic engine. They needed fundamental change. They made Hejlsberg an offer he couldn’t refuse. If he would come to Microsoft, he would be given a clean slate and a massive budget to create a “perfect” version of Java. In 1996 Hejlsberg began work on Microsoft’s J++ 6.0 and WFC, the Windows Foundation Classes for Java, as chief architect of both.

Microsoft J++ 6.0 and the WFC, born out of intense desire by the world’s most qualified software architect to make the very good Java even better, were the successors to Object Pascal and the Delphi Visual Component Library. And soon they would become the precursors to C# and the .NET Framework.

For in 1997, Sun sued Microsoft over the changes it was making to Java, stopping the work cold.

Undeterred, with massive financial reserves, and wanting to get even with Sun, Microsoft upped the ante. It gave Hejlsberg an even cleaner slate, the mandate to write a new language that would be better than Java, and backed by a programming toolkit that would be better than Java’s.

The result, born in a culture that puts technical excellence first, unfettered by prior constraints and guided by the wisdom not only of Hejlsberg’s years of experience with Turbo Pascal and Delphi, but also by the wisdom gleaned from Java, is the C# language.

Syntax, semantics and cultural persistence

We've seen that the cultures of VB and C# are very different. And we've seen that this is no fault of the programmers who use them. Rather this is a product of the combination of factors that collectively could be called their upbringing—business environment, target market, integrity and background of the original language developers, and a myriad other factors.

One factor, however, that seems to have a greater effect on the culture than others, is the syntax and semantics of the language.

To what extent do syntax and semantics play a part in the culture that builds up around a language and to what extent, vice versa, do the syntax and semantics depend on the culture in which the language was created?

The truth is, both—just as spoken languages both grow out of culture and influence culture. For instance, in the far north the language syntax has evolved several words for the different types of snow. Interactions then use the language to express nuances of snow, creating a more snow-centric culture.

So in Visual Basic, the decision to include in the syntax and semantics the ability to assign numbers directly to strings and vice versa was a result of the designers’ desire to attract a broad base of developers who would probably not understand the notions of strongly typed variables. Once the syntax permitted it, such assignment became widespread, reinforcing the designers’ original premise.

Once this cycle of self-reinforcement begins, the cultural habits quickly become entrenched and widespread, and are extremely resistant to change. Minds tend to gravitate to like minds. User groups tend to attract homogenous followings. Visual Basic instructors tend to propagate what their instructors taught them.

This awareness of the immense inertia of embedded culture is precisely the brilliant insight that caused Microsoft to keep Visual Basic and to make it nearly 100% backward compatible at the syntax level. They recognized that trying to get legions of developers to abandon their old cultural norms and adopt new ways was foolhardy.

The brilliant insight Microsoft had was not to support multiple languages—if this was the case then surely it would not have bothered with J#, which is syntactically so close to C# that support for language’s sake alone would be ridiculous. The insight Microsoft had was to support multiple cultures.

In concrete terms

What does this mean in concrete terms? What impact does this have on today’s application development? How does the decision to adopt Visual Basic or C# affect programs written today and tomorrow?

  1. 80% of C# programmers are good, while 80% of VB programmers are not good. This is not to say that everyone who programs in VB is less skilled than everyone who programs in C#. This is to say that:
    1. the VB syntax and semantics is designed to attract less skilled programmers and, in combination with other factors examined above, this has created a culture that is populated with less skilled programmers.
    2. and because VB syntax and semantics make it more difficult to avoid common programming errors and hence to program well.
  2. Hiring a good C# programmer is easier than hiring a good VB programmer. This is because of (1).
  3. Hiring the average C# programmer costs more than hiring the average VB programmer. This is because the average C# programmer is a better programmer than the average VB programmer, and this is because of (1).
  4. Hiring a good VB programmer costs the same as hiring a good C# programmer. There are many good VB programmers, and some of them are much better than some C# programmers. However this is the exception, not the rule.
  5. A good programmer accomplishes two to ten times what an average programmer accomplishes, and causes 90% less bugs and headaches.
  6. At the time of writing there are probably almost as many good VB programmers as there are C# programmers. This is because there are many more VB programmers than C# programmers. The 20% of VB programmers who are good is about same number as the 80% of C# programmers who are good.
  7. In the near future, there will be less good VB programmers than C# programmers. This is because many of the good VB programmers are switching to C#. This is partly because they like the language better, but mostly because they like the culture better. As the cultural separation becomes more evident and self-reinforcing, it will accelerate until there are very few good VB programmers left.
  8. VB programmers, on the average, know less about good object-oriented, distributed, loosely coupled application design and development than C# programmers, on average. This is because their language has not supported these notions, so their culture has grown without them. Although these notions are supported now in VB, they are more slowly being adopted than in the C# culture because of cultural inertia.

Propagation of the culture in .NET

Under .NET, the VB language retains constructs that support the existing (old) VB culture. This was done, of course, in order to avoid alienating the culture’s members. Many of these constructs are still used by VB programmers, even though they should be avoided. Others are not harmful except in as much as they continue to provide cultural reinforcement of habits, including those that are harmful. Examples of key differences are listed below. These are simply examples and not an exhaustive list:

  1. VB by default allows support for late binding. Although it can be turned off with Option strict, the culture is such that it’s usually left on. This leads to numerous difficulty to catch errors. C# binding is always early.
  2. VB still supports the old On error goto construct. This leads to sloppy or non-existent error handling. C# supports only the superior trycatch error handling.
  3. VB supports optional parameters. Although VB developers often list this as an advantage, it is a disadvantage because the use of optional parameters weakens the contract between the caller and the method, allowing the developer to slacken his analysis and get away with it until bugs creep in. [Note: C# param array construct is not the same as optional params]
  4. VB supports the legacy VB functions, with reference to Microsoft.VisualBasic.dll. Many of these functions are slow and they should all be avoided in favor of the .NET Framework. However many VB programmers still use them. In new VB projects, this dangerous namespace is included by default.
  5. VB allows implementation of interfaces with methods of different names, making it confusing and difficult to find the implementation. C# does not.
  6. VB supports background compilation. While this speeds the development cycle for small projects, it slows down the IDE in large projects, contributing at least in part to the culture tending to gravitate toward small projects.
  7. C# namespaces are managed in way that makes programmers aware of namespaces and their importance. VB namespaces are managed in a way that hides them from the programmers by default. Careful attention to namespace management is a fundamental tenet of strong application design and its importance cannot be overestimated.

Conclusions

Conventional arguments between Visual Basic and C# focus on the functionality differences. Since these differences are minimal, it is argued that the choice of VB or C# should remain a matter of personal preference.

These arguments fail to take into account the deep cultural differences between the VB and C# camps.

The truth is that while there are some exceptional VB teams that write exceptional quality code, this is the exception, not the rule. Most VB teams have trouble writing high quality code, and this trait is ingrained deeply into their culture by environmental factors beyond their control, and continues to be propagated by the VB syntax and semantics in Microsoft .NET.

Therefore:

  • If an organization is content to write average quality software and has average VB developers, there may be no benefit in switching to C#.
  • If an organization has an exceptional VB team and wants to continue to improve, there is a real danger in continuing in VB. The danger is that the programmers will leave for opportunities in C#. Once even one top developer does this, the polarization of the group towards the old VB culture may accelerate, thus accelerating the attrition.
  • An organization with an exceptional VB team should switch to C#. The exceptional VB team will have no problem learning the new syntax, so there is no danger. The team will then reap the benefits of the C# syntax, semantics and culture for years to come.

Revision history

  • April 19th, 2005: Minor grammar fixed and removed reference to an internal project in our shop that is meaningless to the broader audience. Clarified several sections that might be taken to be slights against VB developers to indicate that it's not VB developers that are the problem. It's the upbringing of the language in the context of the environment... i.e. its culture. Removed section of additional benefits of C# since it's orthogonal to the point.
  • April 19th, 2005. I apologize to anyone who is or was offended by this article. Please read it carefully. If after reading it carefully you think that it slights good VB developers, please let me know exactly where/how and I'll fix up the article. My intention is not to slight any good developer, or even a bad one who's trying. Criticizing the factors that lead to a culture that makes it difficult for developers to be good... now that I have no problem doing.
  • April 22nd, 2005: I'm getting so many comments about how I say that C# is a better language than VB (even though I never say this) that I edited paragraph 2 to reflect that they are functionally equivalent.
  • May 10th, 2005: DotNetRocks' Carl Franklin read my article and commented on it in a recent issue of DotNetRocks, which you can download here: .NET Rocks! - Kimberly Tripp on SQL Server 2005. Being pro-VB, Carl was pretty negative on the article. I would have no problem with that except that I thought that he also missed the point and tried to ridicule the article by taking excerpts out of context. But you be the judge. I've transcribed his comments word for word in a comment slot below, so you can read them, comment, and, of course, rate his comments.
  • May 20th, 2005: Some posters have asked me to indicate that this article, and in particular the 80/20 comment, are based on my opinion and not on empirical or statistical data. They are my opinion.

About Nigel Shaw


I grew up in a small town outside Montreal, Canada, where I grew to appreciate the Francophone culture, the hospitality of rural Quebec and the awesome skiing of the Eastern Townships. I studied Computer Science at the University of Waterloo, Classical Guitar at the University of Toronto, Electrical Engineering at the University of Ottawa, and earned an MBA at Queen's University.

I'm a partner in Exia Corp, a company that provides software solutions, training and support that increase efficiency.

Click here to view Nigel Shaw's online profile.

Wednesday, September 12, 2007

MySQL vs MS SQL Server

Performance Comparison

The Transaction Processing Performance Council is an independent organization that specifies the typical transactions (transactions used in inventory control systems, airline reservation systems and banking systems) and some general rules these transactions should satisfy. The TPC produces benchmarks that measure transaction processing and database performance in terms of how many transactions a given system and database can perform per unit of time, e.g., transactions per second or transactions per minute.

As of June 2006, SQL Server 2000 holds the third position in the OLTP Test in price by performance results and Microsoft SQL Server 2005×64 holds the first place. However MySQL does not participate in these tests, so it is difficult to make a head on comparison using TPC benchmarks.

In some benchmarks, MySQL has proven to be faster in its basic table format, MyISAM. MyISAM databases are very compact on disk and place little demand on CPU cycles and memory. MySQL can run on Windows without complaint but performs better on UNIX and UNIX-like systems. Additional performance gains can be had by using MySQL on a 64-bit processor, because MySQL uses an abundance of 64-bit integers internally. Much of the very busy Yahoo! Finance portal and Slashdot use MySQL as a back-end database.

It’s worth noting that both systems will work well within either .NET or J2EE architecture. Similarly, both will benefit from RAID, and both will perform best if the data store is on a hard drive or array that is solely dedicated to that purpose.

Given the lack of a standard benchmark upon which to compare the two databases, it’s not possible to conclusively rule on which database has the upper hand in performance.

Features Comparison

Regardless of other differences, the SQL Server 2000 and MySQL have a widely different feature set.

SQL Server 2000 and MySQL v5.0 limits

Although many of the limits placed by the database are for the purists, for example, maximum length of the column name would rarely be a problem.

Some of these built-in limitations may be crucial for database design. Varchar size especially can be problematic, as often stored data such as comments or articles may be forced into BLOBs or TEXT columns. Total row size is also important for this reason.

Feature SQL Server 2000 MySQL v5.0
Column name length 128 8
Index name length 128 8
Table name length 128 8
Max indexes per table 250 8
Index length 900 1024
Max index column length 900 255
Columns per index 16 16
Max char size 8000 255
Max varchar size 8000 65532
Max blob size 2147483647 2147483647
Max columns in GROUP BY Limited by number of bytes (8060) 64
Max columns in ORDER BY Limited by number of bytes (8060) 64
Tables per SELECT statement 256 31
Max columns per table 1024 3398
Max table row length 8036 65534
Longest SQL statement 16777216 1048574

Constant string size in SELECT 16777207 1048565

Data Storage

SQL Server with its closed, proprietary storage engine is fundamentally different from MySQL extensible, open storage engine. Its Sybase-derived database engine boasts of an adaptive algorithm that does most of the tuning that earlier needed to done manually. While SQL Server 2000 chooses the strategy of a single engine doing all the work, MySQL supports pluggable storage engines that can be chosen depending upon the facilities needed.

MySQL’s strategy is useful for various types of database use: quick read access to data without the need for transactional overhead is provided by the built in MyISAM engine, whereas InnoDB, a third party database engine owned by Oracle and licensed under the GPL is most often used for transactions and other features at the cost of some read performance. The MEMORY storage engine creates tables with contents that are stored in memory, and is useful for embedded database applications. NDB Cluster is the storage engine used by MySQL Cluster to implement tables that are partitioned over many computers.

The FEDERATED storage engine stores data in a remote database. In its current release, it works with MySQL only but its future releases will be able to connect to other data sources using other driver or client connection methods.

InnoDB engine has the most advanced database feature set. The disadvantage to MySQL’s pluggable database engine scheme is that care must be given when selecting the engine to use when designing the database before use.

MySQL database engine feature comparison

MyISAM InnoDB MEMORY NDB
Multi-statement transactions, ROLLBACK - X -X
Foreign key constraints - X - -
Locking level table row table row
BTREE indexes X X - X
FULLTEXT indexes X - - -
HASH lookups - X X X
Other in-memory tree-based index - - 4.1.0 -
GIS, RTREE indexes 4.1.0 - - -
Unicode 4.1.0 4.1.2 - -
Merge (union views) X - - -
Compress read-only storage X - - -
Relative disk use low high - low
Relative memory use low high low high

Database Features

One of the critical features of any database engine is data integrity. ACID (Atomic, Consistent, Isolated, and Durable) compliance is a qualification that assures data integrity. ACID essentially means that when a transaction is performed within a database, either the whole transaction is successful and the information is written to the database, or nothing is written. Both SQL Server 2000 and MySQL supports ACID-compliant transaction functionality. SQL Server locks are dynamically applied at various levels of granularity, in order to select the least restrictive lock required for the transaction.

InnoDB provides MySQL with a transaction-safe (ACID compliant) storage engine with commit, rollback, and crash recovery capabilities. InnoDB does locking on the row level and also provides an Oracle-style consistent non-locking read in SELECT statements. These features increase multi-user concurrency and performance. In SQL queries you can freely mix InnoDB type tables with other table types of MySQL, even within the same query.

With the new release of MySQL 5.0, it has now incorporated several features that were missing earlier, and thus some of the reasons that caused you to choose SQL Server 2000 are no longer valid, for example, the need of Views, Cursors and Procedures. One thing now lacking is the full support for triggers. Another thing in which MySQL lags behind is XML support, and with the release of Yukon, this is going to look like a big gap in functionality.

Feature
SQL Server 2000 MySQL v5.0
ACID
Yes Yes
Referential Integrity
Yes Yes
Transactions
Yes Yes
Temporary Table
Yes Yes
Views
Indexed views Updateable views
Indexes



R-/R+ tree ? MyISAM only

Hash ? MEMORY only

Expression ? No

Partial ? No

Reverse ? No

Bitmap ? No
Cursor
Yes Yes
Trigger
Yes Rudimentary
Function
Yes Yes
Procedure
Yes Yes
External routine
Yes Yes
Partitioning



Range Yes NDB only

Hash No No

Composite No No

List No No
XML support
Yes No
Unicode
Yes Yes

Database Warehousing

The data warehouses or data marts can be used for sophisticated enterprise intelligence systems that process queries required to discover trends and analyze critical factors. These systems are called online analytical processing (OLAP) systems. The data in data warehouses and data marts is organized differently than in traditional transaction processing databases.

While SQL Server 2000 provides a lot of tools for creating and managing data warehouses, MySQL does not have any significant support for it. Data Transformation Services (DTS) provides a set of services used to build a data warehouse or data mart. Analysis Services is an excellent tool for multidimensional analysis of data in SQL Server 2000 databases. Analysis Services supports multidimensional queries against cubes with hundreds of millions of dimensions and you can even control cube security down to the level of cells and members. Data mining allows you to define models containing grouping and predictive rules that can be applied to data in either a relational database or multi-dimensional OLAP cubes. These predictive models are then used to automatically perform sophisticated analysis of the data to find trends.

Application Development

SQL Server 2000 and MySQL both support ODBC and JDBC for network connectivity, as well as native database access methods. These native methods provide access via the network in both plain text methods and, for a higher level of security, SSL-encrypted methods.

Another important part of database interface methods is authentication for the database. MySQL uses a simple method to store all of its authentication information inside a table. When users attempt to access a database, MySQL compares their credentials against this database, verifying from which machines the users can connect and to what resources they have access. SQL Server 2000 also has integrated Windows authentication.

A number of programming methods also provide ways to access these databases. Both SQL Server 2000 and MySQL support access via C/C++ , Java, Perl, Python, and PHP. One thing that differentiates SQL Server 2000 is its XML capabilities. Using SQLXML package with SQL Server 2000, it is possible to query relational data using XQuery and even expose stored procedures as web services.

Installation

Hardware and Software Requirements

Installation of Microsoft SQL Server requires a Windows operating system. So, if you need to run the database on a Linux box, the comparison is clearly in favor of MySQL. MySQL has been ported to all major operating systems and can be ported to any os that has a C++ compiler and a working implementation of POSIX threads. Using GNU autoconf, MySQL happily compiles on various flavors of UNIX, Windows, Linux and Mac OS X.

Hardware cost is not as much of an issue as it once was, with RAM and hard disk space costs being low. But for the hardware conscious, SQL server can look like a hog compared to MySQL. While SQL server requires a minimum of 128 MB of RAM for reasonable performance, MySQL can easily run on a Linux with as little as 32 MB of RAM, this is likely that is the reason that the MySQL installation manual doesn’t bother specifying hardware requirements.

Although it is not too difficult to compile the MySQL source code, a ready installer is always welcome to get you up and running quickly. With the release of MySQL 4.1.5, MySQL AB has introduced an installer for the Windows version of MySQL, combined with a new GUI Configuration Wizard. This combination automatically installs MySQL, creates an option file, starts the server, and secures the default user accounts.

HardwareSQL Server 2000MySQL 5.0
Operating systemWindows XP, Windows 2000 Windows 9x, Me, NT, 2000, XP, and 2003 Linux 2.0+
Mac OSX
AIX 4.x, 5.x
BSDI 3.0, 3.1 and 4.x
FreeBSD 3.x, 4.x, 5.x
OpenBSD 2.5+
Digital Unix 4.x
HP-UX 10.20, 11.x
NetBSD 1.3/1.4 Intel, 1.3 Alpha
SCO Open Server, UnixWare 7.1
SGI Irix 6.5
Solaris 2.5
MemoryEnterprise Edition and Enterprise Evaluation Edition: 64 MB minimum, 128 MB or more recommended

Standard Edition and Developer Edition: 64 MB minimum

Personal Edition and Desktop Engine (MSDE 2000): 128 MB minimum on Windows XP 64 MB minimum on Windows 2000 32 MB minimum on other Windows
32 MB of RAM
Hard disk spaceEnterprise, Enterprise Evaluation, Standard, Developer, and Personal Editions require:

95 to 270 MB of available hard disk space for the database engine; 250 MB for a typical installation.

50 MB of available hard disk space for a minimum installation of Analysis Services; 130 MB for a typical installation.

80 MB of available hard disk space for English Query.

Desktop Engine (MSDE 2000): 44 MB minimum
60 to 85 MB depending on the components and operating system; 200 MB recommended for Windows.

Installation

Microsoft products have always been known for the painless and quick installation through intuitive wizards. MySQL, despite being an open source product is no less, and you can expect the same kind of breezy installation. The installer will even create a Windows service for the MySQL database.

Administration and Maintenance

MySQL provides two types of backup, one where the database dump is taken and another where it emits all the SQL statements required to create the database. SQL Server 2000 only provides the first option. When it comes to hot backups, or backing up your database without shutting it down, both database solutions have methods for doing so. MySQL supports incremental backup strategy for minimizing the amount of time taken if an existing database backup is present.

SQL Server 2000 failover clustering provides high availability support. For example, during an operating system failure or a planned upgrade, you can configure one failover cluster to fail over to any other node in the failover cluster configuration. In this way, you minimize system downtime, thus providing high server availability. But for this, you will need to buy the Enterprise version. MySQL also provides clustering through its NDB database engine, but it is slightly difficult to configure.

MySQL supports one-way replication. One server acts as the master, while one or more other servers act as slaves. The master server writes updates to its binary log files and the slave servers periodically connect to get updates. SQL Server 2000 offers far more facilities for replication. It offers three choices – Snapshot, Transactional and Merge. While the transactional facility is similar to the MySQL master slave replication, Snapshot is useful where data has changed a lot and so the entire snapshot is sent to the slave. Using Merge replication, two SQL servers can send updates to each other and are a perfect choice for geographically separated SQL servers.

Both products have perfectly acceptable default security mechanisms, as long as you follow the manufacturer’s directions and keep up with your security patches. Both products operate over well-known default IP ports, and, unfortunately, those ports draw intruders like flies to honey. Fortunately, both SQL Server and MySQL allow you to change that port should the default become too popular a destination for your taste.

Stability is one area where MySQL, in its MyISAM configuration, falls a little short. With MyISAM, a UPS is absolutely mandatory because MyISAM assumes uninterrupted operation. If it is shut down unexpectedly, the result could be corruption of the entire data. SQL Server, on the other hand, is far more resistant to data corruption. SQL Server’s data goes through multiple checkpoints and SQL Server remembers where it was in the process even if it happens to be shut down without warning.

SQL Server 2000 MySQL v5.0
Hot backups Yes Yes
Replication Snapshot, Transactional, Merge One-way only
Clustering Yes Yes
Security features High High
Locking and concurrency support Fully automated Row-locking (InnoDB)
Stability High High
GUI Administration Tools Yes Yes (download)

Price

When it comes to licensing costs, MySQL definitely has an edge as it is free and open source software licensed under the GPL. With SQL Server, the most popular way to get a free developer license is to purchase a license for Microsoft Office Developer or Microsoft Visual Studio, both of which give you a free “development use only” SQL Server license.

SQL Server 2000 is currently available under two licensing options:
  • Processor license
  • Server/per-seat client access license (CAL)
The processor license requires a single license for each CPU in the computer running SQL Server 2000 and includes unlimited client access. You can buy this license when you do not know the number of the clients (for example, if your users will connect to SQL Server 2000 through the internet). This license usually is cheaper than Server/Per-Seat CAL when there are many users connected to SQL Server databases.

The Server/per-seat client access license (CAL) requires a license for the server and the licenses for each client device. You can use this licensing option when the customers do not need access beyond the firewall and the number of clients is low (for example, 10-20 users for SQL Server 2000 Standard Edition or 30-40 users for SQL Server 2000 Enterprise Edition).

Lately, Microsoft Database Engine (MSDE) which is actually a scaled down version of SQL Server has been made available as a free download. It is a very attractive choice if you need an embedded database for your windows applications, but is not recommended for use as a server in production environments.

Licensing OptionsSQL Server 2000 Standard EditionSQL Server 2000 Enterprise Edition
Processor$4,999 per processor$19,999 per processor
Server/Per-Seat CALwith 5 CAL – $1,489 with 10 CAL – $2,249 with 25 CAL – $11,099

The MySQL version 5.0 is Dual Licensed. Users can choose to use the MySQL software as an Open Source/Free Software product under the terms of the GNU General Public License or can purchase a standard commercial license from MySQL AB.

The GPL license grants the user a right to use the database at no cost with the condition that any changes made to the source code of the database would have to be made available under GPL. Since most of the applications simply use the database, it is usually a zero-cost alternative.

The MySQL v5.0 Server commercial license is per database server (single installed MySQL binary). The price comparisons below were based on the MySQL Licensing Prices from MySQL AB.

Number of licensesPrice per copy (EUR)Price per copy (USD)
1..9440495
10..49315360
50..99255290
100..249195220
250..499155175

Overall, MySQL has the edge in price as it is free, and performance can’t be conclusively shown to be any worse than MS SQL—it is also used extensively for high profile web applications such as various Yahoo properties and Google’s Adwords. Certain advanced features are not bundled with MySQL, but for basic simple development without licensing cost, MySQL can be seen to have the edge.

MS SQL 2000 and now 2005, are geared towards Microsoft style development on Windows Servers. Installation and configuration may be easier in MS SQL, with advanced database features present by default. MS SQL also implements features not found in any MySQL database engine, and is not overly high in license costs compared to some high end databases. For certain mid-level uses on Windows Servers, MS SQL probably wins out.

Both databases have a wide traction in the market, but being an open source project, MySQL community is somewhat more open, and being completely free, MySQL likely has a broader base of support.

Using PHP library from C#

If you have a bunch of working PHP code forming a library you use in your PHP applications and would like to use it in C# applications as well, you'll find this tutorial useful.


First, paste the following code into file called Library.php in some directory.


<? include "ClassC.php" ;   function f ( ) { echo "Hello! \n " ; } echo "Library initialized: Now, you can use " . "classes and functions declared here. \n " ; ?>

Than paste the following class in file named ClassC.php in the same directory:


<? class C { public $array = array ( 1 , 2 , 3 ) ; function __construct ( $data ) { $this-> data = $data; } } ?>

To build the class library using Phalanger use following command:


phpc /target:dll /out:ClassLibrary.dll Library.php ClassC.php

This command builds the two scripts into an assembly called ClassLibrary . Let's create a C# and VB .NET console applications now that reference this library and call a function declared in Library.php and creates an instance of a class declared in ClassC.php .


In C#, the program using the library may look like following:


using PHP. Core ; using System;   namespace ConsoleApplication2 { class Program { static void Main ( string [ ] args ) { ScriptContext context = ScriptContext. CurrentContext ;   // redirect PHP output to the console: context. Output = Console. Out ;   // get a representative type of the ClassLibrary library: Type library_representative = typeof ( ClassLibrary ) ;   // include the Library.php script, which initializes the // whole library (it is also possible to include more // scripts if necessary by repeating this call with various // relative script paths): context. IncludeScript ( "Library.php" , library_representative ) ;   // call function f(): context. Call ( "f" ) ;   // create an instance of type C, passes array // ("a" => 1, "b" => 2) as an argument to the C's ctor: object c = context. NewObject ( "C" , PhpArray. Keyed ( "a" , 1 , "b" , 2 ) ) ;   // var_dump the object: PhpVariable. Dump ( c ) ; } } }

You can use Visual Studio to build the C# program, or if you prefer command line compiler just run the following:


C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Csc.exe /reference:"C:\Program Files\Phalanger v2.0\PhpNetCore.dll" /reference:"ClassLibrary.dll" /out:ConsoleApplication.exe /target:exe Program.cs

And that's it 8-)! If you run the resulting application you'll get:


<code> Library initialized: Now, you can use classes and functions declared here. Hello! object(C)(2) {


["array"] => array { [0] => integer(1) [1] => integer(2) [2] => integer(3) } ["data"] => array { ['a'] => integer(1) ['b'] => integer(2) }

} <code>

Zope Page Templates: Getting Started

Introduction

Page Templates are a web page generation tool. They help programmers and designers collaborate in producing dynamic web pages for Zope web applications. Designers can use them to maintain pages without having to abandon their tools, while preserving the work required to embed those pages in an application.

The goal is natural workflow. A designer will use a WYSIWYG HTML editor to create a template, then a programmer will edit it to make it part of an application. As required, the designer can load the template back into his editor and make further changes to its structure and appearance. By taking reasonable steps to preserve the changes made by the programmer, he will not disrupt her application.

Page Templates aim at this goal by adopting three principles:

  1. Play nicely with editing tools.
  2. What you see is very similar to what you get.
  3. Keep code out of templates, except for structural logic.

A Page Template is a model of the pages that it will generate. In particular, it is a valid HTML page. Since HTML is highly structured, and WYSIWYG editors carefully preserve this structure, there are strict limits on the ways in which the programmer can change a page and still respect the first principle.

Who Are They For?

Page Templates are for programmers and designers who need to work together to create dynamic web pages. If you create and edit all of your web pages with a text editor, you might not care for Page Templates. Then again, they can be simpler to use and understand than the alternatve, DTML.

Why Yet Another Template Language?

There are plenty of template systems out there, some of them quite popular, such as ASP, JSP, and PHP. Why invent another?

First, none of these template systems are aimed at HTML designers. Once a page has been converted into a template, it is invalid HTML, making it difficult to work with outside of the application. Each of them violates the first or second principle of Zope Page Templates to one degree or another. Programmers should not "hijack" the work of the designers and turn HTML into software. XMLC, part of the Enhydra project, shares our goal, but requires the programmer to write substantial amounts of Java support code for each template.

Second, all of these systems suffer from failure to separate presentation, logic, and content (data). Their violations of the third principle decrease the scalability of content management and website development efforts that use these systems.

Applying The Principles

Page Templates have a template language (TAL) that consists of special tag attributes. For example, a dynamic page title might look like this:

<pre>
<title content="here/title">Page Title</<title>

</pre> <p> The <code>tal:content</code> attribute is a TAL statement. Since it has an XML namespace (the <code>tal:</code> part) most editing tools will not complain that they don't understand it, and will not remove it. It will not change the structure or appearance of the template when loaded into a WYSIWYG editor or a web browser. The name <code>content</code> indicates that it will set the content of the <code>title</code> tag, and the value "here/title" is an expression providing the text to insert into the tag.

This example also demonstrates the second principle; When you view the template in an editor, the title text will act as a placeholder for the dynamic title text. The template acts like an example of how generated documents should look.

There are template commands for replacing entire tags, their contents, or just some of their attributes. You can repeat a tag several times or omit it entirely. You can join parts of several templates together, and specify simple error handling. All of these capabilities are used to generate document structures. You can't create subroutines or classes, write loops or multi-way tests, or easily express complex algorithms.

The template language is deliberately not as powerful and general-purpose as it could be. It is meant to be used inside of a framework (such as Zope) in which other objects handle business logic and tasks unrelated to page layout.

For instance, template language would be useful for rendering an invoice page, generating one row for each line item, and inserting the description, quantity, price, and so on into the text for each row. It would not be used to create the invoice record in a database or to interact with a credit card processing facility.

Page Template Tutorial: Template Language


Creating a Page Template


If you design pages, you will probably use FTP or WebDAV instead of the Zope Management Interface (ZMI) to create and edit Page Templates. See your Zope adminstrator for instructions. For the very small examples in this introduction, it is much easier to use the ZMI.


If you are a Zope administrator or a programmer, you will probably use the ZMI at least occasionally. You may also use emacs, cadaver, or some other client. See the Zope Administrator's Guide for instructions on setting up Zope to to work with various clients.


Use your web browser to log into the Zope management interface. Choose a Folder (the root is fine) and pick "Page Template" from the drop-down add list. Type "simple_page" in the add form's Id field, then push the "Add and Edit" button.


You should now see the main editing page for the new Page Template. The title is blank, the content-type is text/html , and the default template text is in the editing area.


Now you will create a very simple dynamic page. Type the words "a Simple Page" in the Title field. Edit the template text to look like this:


This is <b tal:replace="template/title">the Title</b>.

Now push the "Save Changes" button. The edit page should show a message confirming that your changes have been saved. If some text starting with <!-- Page Template Diagnostics is added to the template, then check to make sure you typed the example correctly and save it again. You don't need to erase the error comment: once the error is corrected it will go away.


Click on the Test tab. You should see a mostly blank page with "This is a Simple Page." at the top.


Back up, then click on the "Browse HTML source" link under the content-type field. You should see "This is the Title ." Back up again, so that you are ready to edit the example further.


Simple Expressions


The text "template/title" in your simple Page Template is a path expression . This the most commonly used of the expression types defined by the TAL Expression Syntax (TALES). It fetches the title property of the template. Here are some other common path expressions:



  • request/URL: The URL of the current web request.

  • user/getUserName: The authenticated user's login name.

  • container/objectIds: A list of Ids of the objects in the same Folder as the template.


Every path starts with a variable name. If the variable contains the value you want, you stop there. Otherwise, you add a slash ( / ) and the name of a sub-object or property. You may need to work your way through several sub-objects to get to the value you're looking for.


There is a small built in set of variables, such as request and user , that will be listed and described later. You will also learn how to define your own variables.


Inserting Text


In your "simple_page" template, you used the tal:replace statement on a bold tag. When you tested it, it replaced the entire tag with the title of the template. When you browsed the source, you saw the template text in bold. We used a bold tag in order to highlight the difference.


In order to place dynamic text inside of other text, you typically use tal:replace on a span tag. Add the following lines to your example:


<br> The URL is <span tal:replace="request/URL">URL</span>.

The span tag is structural, not visual, so this looks like "The URL is URL." when you view the source in an editor or browser. Remember to take care when editing not to destroy the span or place formatting tags such as b or font inside of it, since they would also be replaced.


If you want to insert text into a tag but leave the tag itself alone, you use tal:content . To set the title of your example page to the template's title property, add the following lines above the other text:


<head> <title tal:content="template/title">The Title</title> </head>

If you open the "Test" tab in a new window, the window's title will be "a Simple Page".


Repeating Structures


Now you will add some context to your page, in the form of a list of the objects that are in the same Folder. You will make a table that has a numbered row for each object, and columns for the id, meta-type, and title. Add these lines to the bottom of your example template:


<table border="1" width="100%"> <tr> <th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th> </tr> <tr tal:repeat="item container/objectValues"> <td tal:content="repeat/item/number">#</td> <td tal:content="item/id">Id</td> <td tal:content="item/meta_type">Meta-Type</td> <td tal:content="item/title">Title</td> </tr> </table>

The tal:repeat statement on the table row means "repeat this row for each item in my container's list of object values". The repeat statement puts the objects from the list into the item variable one at a time, and makes a copy of the row using that variable. The value of "item/id" in each row is the Id of the object for that row.


The name item is not special; You can use any name you like for the variable, as long as it starts with a letter and contains only letters, numbers, and underscores ( _ ). It only exists in the tag that the tal:repeat statement is in, in this case the tr tag; If you tried to use it above or below that tag you would get an error.


Each row in the example is numbered, which requires knowing the number of the current repetition. You might also like to know whether a particular row is the first or last row, or similar information. In each copy of the row, the variable item contains an object from the list. This object doesn't know anything about the repetition, so you can't use item/somename to get this sort of information. This is what the builtin repeat variable is for. By placing the name of the repeating variable after repeat in a path, you can access the repetition count from zero ( index ), from one ( number ), from "A" ( Letter ), and in several other ways. So, the expression repeat/item/number is 1 in the first row, 2 in the second row, and so on.


Since one tal:repeat can be placed inside of another, more than one can be active at the same time. This is why you must write repeat/item/number instead of just repeat/number to get information about the tal:repeat that creates the item variable.


Conditional Elements


View the template, and you'll notice that the table is very dull looking. Let's improve it by shading alternate rows. Copy the second row of the table, then edit it so that it looks like this:


<table border="1" width="100%"> <tr> <th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th> </tr> <tbody tal:repeat="item container/objectValues"> <tr bgcolor="#EEEEEE" tal:condition="repeat/item/even"> <td tal:content="repeat/item/number">#</td> <td tal:content="item/id">Id</td> <td tal:content="item/meta_type">Meta-Type</td> <td tal:content="item/title">Title</td> </tr> <tr tal:condition="repeat/item/odd"> <td tal:content="repeat/item/number">#</td> <td tal:content="item/id">Id</td> <td tal:content="item/meta_type">Meta-Type</td> <td tal:content="item/title">Title</td> </tr> </tbody> </table>

The tal:repeat has not changed, you have just moved it onto the new tbody tag. This is a standard HTML tag meant to group together the body rows of a table, which is how you are using it. There are two rows in the body, with identical columns, and one has a grey background.


View the template's source, and you see both rows. If you had not added the tal:condition statements to the rows, then the template would generate both rows for every item, which is not what you want. The tal:condition statement on the first row ensures that it is only included on even- indexed repetitions, while the second row's condition only lets it appear in odd-indexed repetitions.


A tal:condition statement does nothing if its expression has a true value, but removes the entire statement tag, including its contents, if the value is false. The odd and even properties of repeat/item are either zero or one. The number zero, a blank string, an empty list, and the builtin variable nothing are all false values. Nearly every other value is true, including non-zero numbers, and strings with anything in them (even spaces!).


Defining Variables


Your template will always show at least one row, since the template itself is one of the objects listed. In other circumstances, you might want to account for the possibility that the table will be empty. Suppose you want to simply omit the entire table in this case. You can do this by adding a tal:condition to the table:


<table border="1" width="100%" tal:condition="container/objectValues"

Now, when there are no objects, no part of the table will be included in the output. When there are objects, though, the expression "container/objectValues" will be evaluated twice, which is mildly inefficient. Also, if you wanted to change the expression, you would have to change it in both places.


To avoid these problems, you can define a variable to hold the list, and then use it in both the tal:condition and the tal:repeat . Change the first few lines of the table to look like this:


<table border="1" width="100%" tal:define="items container/objectValues" tal:condition="items"> <tr> <th>#</th><th>Id</th><th>Meta-Type</th><th>Title</th> </tr> <tbody tal:repeat="item items">

The tal:define statement creates the variable items , and you can use it anywhere in the table tag.


Now, suppose that instead of simply leaving the table out when there are no items, you want to show a message. To do this, you place the following above the table:


<h4 tal:condition="not:container/objectValues">There Are No Items</h4>

You can't use your items variable here, because it isn't defined yet. If you move the definition to the h4 tag, you can't use it in the table tag any more, because it becomes a local variable of the h4 tag. You could place the definition on some tag that enclosed both the h4 and the table , but there is a simpler solution. By placing the keyword global in front of the variable name, you can make the definition last from the h4 tag to the bottom of the template:


<h4 tal:define="global items container/objectValues" tal:condition="not:items">There Are No Items</h4> <table border="1" width="100%" tal:condition="items">

The not: in the first tal:condition is an expression type prefix that can be placed in front of any expression. If the expression is true, not: is false, and vice versa.


Changing Attributes


Most, if not all, of the objects listed by your template have an icon property, that contains the path to the icon for that kind of object. In order to show this icon in the meta- type column, you will need to insert this path into the src attribute of an img tag, by editing the meta-type column in both rows to look like this:


<td><img src="/misc_/OFSP/Folder_icon.gif" tal:attributes="src item/icon"> <span tal:replace="item/meta_type">Meta-Type</span> </td>

The tal:attributes statement replaces the src attribute of the image with the value of item/icon . The value of src in the template acts as a placeholder, so that the image is not broken, and is the correct size.


Since the tal:content attribute on the table cell would have replaced the entire contents of the cell, including the image, with the meta-type text, it had to be removed. Instead, you insert the meta-type inline in the same fashion as the URL at the top of the page.


peterbe (Jun 25, 2001 11:21 am; Comment #3) Editor Remark Requested Perhaps also mention how to use ( parameters ) > tal:define="items container/objectValues"

becomes


> tal:define="items python:container.objectValues( Photo )"

or if the objectpath containes . dots:


> tal:define="items container/folder.peter/objectValues"

becomes


> tal:define="itemsobj container/folder.peter/objectValues/; items python:itemsobj( Photo )"

Stop and correct me before I make a fool out of myself.


evan (Jun 25, 2001 1:29 pm; Comment #4) These are good, but belong in part 4, where Python expressions are discussed.

Page Template Tutorial: More TAL


Mixing and Matching Statements


As you have seen in the example template, you can put more than one TAL statement on the same tag. There are three limits you should be aware of, however.



  1. Only one of each kind of statement can be used on a single tag. Since HTML does not allow multiple attributes with the same name, you can't have two tal:define on the same tag.

  2. Both of tal:content and tal:replace cannot be used on the same tag, since their functions conflict.

  3. The order in which you write TAL attributes on a tag does not affect the order in which they execute. No matter how you arrange them, the TAL statements on a tag always execute in the following order: define , condition , repeat , content / replace , attributes .


To get around these limits, you can add another tag and split up the statements between the tags. If there is no obvious tag type that would fit, you can use span or div if it is appropriate for the output to contain an element, or use a tal:block element to have the start and end tags omitted from the document.


For example, if you want to define a variable for each repetition of a paragraph, you can't place the tal:define on the same tag as the tal:repeat , since the definition would happen before all of the repetitions. Instead, you would write either of the following:


<div tal:repeat="p phrases"> <p tal:define="n repeat/p/number"> Phrase number <span tal:replace="n">1</span> is "<span tal:replace="p">Phrase</span>".</p> </div> <p tal:repeat="p phrases"> <span tal:define="n repeat/p/number"> Phrase number <span tal:replace="n">1</span> is "<span tal:replace="p">Phrase</span>".</span> </p>

Statements with Multiple Parts


If you need to set multiple attributes on a tag, you can't do it by placing multiple tal:attributes statements on the tag, and splitting them across tags is useless.


Both the tal:attributes and tal:define statements can have multiple parts in a single statement. You separate the parts with semicolons ( ; ), so any semicolon appearing in an expression in one of these statements must be escaped by doubling it ( ;; ). Here is an example of setting both the src and alt attributes of an image:


<img src="default.jpg" tal:attributes="src item/icon; alt item/id">

Here is a mixture of variable definitions:


<span tal:define="global logo here/logo.gif; ids here/objectIds">

String Expressions


String expressions allow you to easily mix path expressions with text. All of the text after the leading string: is taken and searched for path expressions. Each path expression must be preceded by a dollar sign ( $ ). If it has more than one part, or needs to be separated from the text that follows it, it must be surrounded by braces ( {} ). Since the text is inside of an attribute value, you can only include a double quote by using the entity syntax """. Since dollar signs are used to signal path expressions, a literal dollar sign must be written as two dollar signs ( $$ ). For example:


"string:Just text." "string:&copy; $year, by Me." "string:Three ${vegetable}s, please." "string:Your name is ${user/getUserName}!"

Nocall Path Expressions


An ordinary path expression tries to render the object that it fetches. This means that if the object is a function, Script, Method, or some other kind of executable thing, then expression will evaluate to the result of calling the object. This is usually what you want, but not always. For example, if you want to put a DTML Document into a variable so that you can refer to its properties, you can't use a normal path expression because it will render the Document into a string.


If you put the nocall: expression type prefix in front of a path, it prevents the rendering and simply gives you the object. For example:


<span tal:define="doc nocall:here/aDoc" tal:content="string:${doc/id}: ${doc/title}"> Id: Title</span>

This expression type is also valuable when you want to define a variable to hold a function or class from a module, for use in a Python expression.


Python Expressions


A Python expression starts with python: , followed by an expression written in the Python language. See the section on writing Python expressions for more information.


Other Builtin Variables


You have already seen some examples of the builtin variables template , user , repeat , and request . Here is a complete list of the other builtin variables and their uses:



  • nothing : a false value, similar to a blank string, that you can use in tal:replace or tal:content to erase a tag or its contents. If you set an attribute to nothing , the attribute is removed from the tag (or not inserted), unlike a blank string.

  • default : a special value that doesn't change anything when used in tal:replace , tal:content , or tal:attributes . It leaves the template text in place.

  • options : the keyword arguments, if any, that were passed to the template.

  • attrs : a dictionary of attributes of the current tag in the template. The keys are the attributes names, and the values are the original values of the attributes in the template.

  • root : the root Zope object. Use this to get Zope objects from fixed locations, no matter where your template is placed or called.

  • here : the object on which the template is being called. This is often the same as the container , but can be different if you are using acquisition. Use this to get Zope objects that you expect to find in different places depending on how the template is called.

  • container : the container (usually a Folder) in which the template is kept. Use this to get Zope objects from locations relative to the template's permanent home.

  • modules : the collection of Python modules available to templates. See the section on writing Python expressions.


Alternate Paths


The path template/title is guaranteed to exist every time the template is used, although it may be a blank string. Some paths, such as request/form/x , may not exist during some renderings of the template. This normally causes an error when the path is evaluated.


When a path doesn't exist, you often have a fallback path or value that you would like to use instead. For instance, if request/form/x doesn't exist, you might want to use here/x instead. You can do this by listing the paths in order of preference, separated by vertical bar characters ( | ):


<h4 tal:content="request/form/x | here/x">Header</h4>

Two variables that are very useful as the last path in a list of alternates are nothing and default . Use nothing to blank the target if none of the paths is found, or default to leave the example text in place.


You can also test the existence of a path directly with the exists: expression type prefix. A path expression with exists: in front of it is true if the path exists, false otherwise. These examples both display an error message only if it is passed in the request:


<h4 tal:define="err request/form/errmsg | nothing" tal:condition="err" tal:content="err">Error!</h4> <h4 tal:condition="exists:request/form/errmsg" tal:content="request/form/errmsg">Error!</h4>

Dummy Elements


You can include page elements that are visible in the template but not in generated text by using the builtin variable nothing , like this:


<tr tal:replace="nothing"> <td>10213</td><td>Example Item</td><td>$15.34</td> </tr>

This can be useful for filling out parts of the page that will take up more of the generated page than of the template. For instance, a table that usually has ten rows will only have one row in the template. By adding nine dummy rows, the template's layout will look more like the final result.


Inserting Structure


Normally, the tal:replace and tal:content statements quote the text that they insert, converting '< to <', for instance. If you actually want to insert the unquoted text, you need to precede the expression with the structure keyword. Given a variable copyright , the following two lines:


<span tal:replace="copyright">Copyright 2000</span> <span tal:replace="structure copyright">Copyright 2000</span>

might generate "&copy; 2001 By <b>Me</b>" and "© 2001 By Me " respectively.


This feature is especially useful when you are inserting a fragment of HTML that is stored in a property or generated by another Zope object. For instance, you may have news items that contain simple HTML markup such as bold and italic text when they are rendered, and you want to preserve this when inserting them into a "Top News" page. In this case, you might write:


<p tal:repeat="article topnewsitems" tal:content="structure article">A News Article</p> jwm (Aug 8, 2001 7:12 pm; Comment #2) Editor Remark Requested Multiple Defines: > <span tal:define="global logo here/logo.gif; ids here/objectIds">

global is a keyword used per variable definition, so in this case logo becomes global, will ids stays local to the span. A bit like you'd expect, really :-)


Strings:


How about some examples of them in action straight after the construction examples. I find when I hit something I don't quite understand I tend to stall, and in this case I didn't see where I'd use a string construct until I read the fairly unrelated example for nocall below it.


So we'd have something like this:


> "string:Just text." > "string:� $year, by Me." > "string:Three ${vegetable}s, please." > "string:Your name is ${user/getUserName}!"

Which are used like this:


Boring text


You are logged in as someone.


Actually on further reading, I think just mentioning that we're talking about expresion type prefixes that are things that appear inside the attribute strings created when you use a statement (ie, any of tal:define, etc) just before statements would clear this up.


LRA (Jan 10, 2002 7:14 pm; Comment #3) Navigation:

benster (Jun 29, 2002 11:00 pm; Comment #4) Editor Remark Requested Under Mixing and Matching Statements: > For example, if you want to define a variable for each > repetition of a paragraph ...

Where is the paragraph defined? Is it a string variable? It's not a string expression, judging from the examples. It would be helpful to see this paragraph being defined.


FredDrake ? The paragraph is the p element shown in the example. There's nothing magical about this.

Page Template Tutorial: Advanced Concepts





Basic Python Expressions


The Python language is a simple and expressive one. If you have never encountered it before, you should read one of the excellent tutorials or introductions available at the website http://www.python.org.


A Page Template Python expression can contain anything that the Python language considers an expression. You can't use statements such as if and while , and Zope's security restrictions are applied.


Comparisons


One place where Python expressions are practically necessary is in tal:condition statements. You usually want to compare two strings or numbers, and there isn't any other way to do that. You can use the comparison operators < (less than), > (greater than), '== (equal to), and !=' (not equal to). You can also use the boolean operators and , not , and or . For example:


<p tal:repeat="widget widgets"> <span tal:condition="python:widget.type == 'gear'> Gear #<span tal:replace="repeat/widget/number>1</span>: <span tal:replace="widget/name">Name</span> </span> </p>

Sometimes you want to use choose different values inside a single statement based on one or more conditions. You can do this with the test() function, like this:


You <span tal:define="name user/getUserName" tal:replace="python:test(name=='Anonymous User', 'need to log in', default)"> are logged in as <span tal:replace="name">Name</span> </span> <tr tal:define="oddrow repeat/item/odd" tal:attributes="class python:test(oddrow, 'oddclass', 'evenclass')">

Using other Expression Types


You can use other expression types inside of a Python expression. Each type has a corresponding function with the same name, including path() , string() , exists() , and nocall() . This allows you to write expressions such as:


"python:path('here/%s/thing' % foldername)" "python:path(string('here/$foldername/thing'))" "python:path('request/form/x') or default"

The final example has a slightly different meaning than the path expression "request/form/x | default", since it will use the default text if "request/form/x" doesn't exists or if it is false.


Getting at Zope Objects


Much of the power of Zope involves tying together specialized objects. Your Page Templates can use Scripts, SQL Methods, Catalogs, and custom content objects. In order to use them, you have to know how to get access to them.


Object properties are usually attributes, so you can get a template's title with the expression "template.title". Most Zope objects support acquisition, which allows you to get attributes from "parent" objects. This means that the Python expression "here.Control_Panel" will acquire the Control Panel object from the root Folder. Object methods are attributes, as in "here.objectIds" and "request.set". Objects contained in a Folder can be accessed as attributes of the Folder, but since they often have Ids that are not valid Python identifiers, you can't use the normal notation. For example, instead of writing "here.penguin.gif", you must write "getattr(here, penguin.gif )".


Some objects, such as request , modules , and Zope Folders support item access. Some examples of this are:


request['URL'], modules['math'], and here['thing']

When you use item access on a Folder, it doesn't try to acquire the name, so it will only succeed if there is actually an object with that Id contained in the Folder.


As shown in previous chapters, path expressions allow you to ignore details of how you get from one object to the next. Zope tries attribute access, then item access. You can write "here/images/penguin.gif" instead of "python:getattr(here.images, penguin.gif )", and "request/form/x" instead of "python:request.form['x']".


The tradeoff is that path expressions don't allow you to specify those details. For instance, if you have a form variable named "get", you must write "python:request.form['get']", since "request/form/get" will evaluate to the "get" method of the form dictionary.


Using Scripts


Script objects are often used to encapsulate business logic and complex data manipulation. Any time that you find yourself writing lots of TAL statements with complicated expressions in them, you should consider whether you could do the work better in a Script.


Each Script has a list of parameters that it expects to be given when it is called. If this list is empty, then you can use the Script by writing a path expression. Otherwise, you will need to use a Python expression, like this:


"python:here.myscript(1, 2)" "python:here.myscript('arg', foo=request.form['x'])"

If you want to return more than a single bit of data from a Script to a Page Template, it is a good idea to return it in a dictionary. That way, you can define a variable to hold all the data, and use path expressions to refer to each bit. For example:


getPerson returns this: {'name': 'Fred', 'age': 25} <span tal:define="person here/getPerson" tal:replace="string:${person/name} is ${person/age}"> Name is 30</span> years old.

Calling DTML


Unlike Scripts, DTML Methods don't have an explicit parameter list. Instead, they expect to be passed a client, a mapping, and keyword arguments. They use these to construct a namespace.


When the ZPublisher ? publishes a DTML object, it passes the context of the object as the client, and the REQUEST as the mapping. When one DTML object calls another, it passes its own namespace as the mapping, and no client.


If you use a path expression to render a DTML object, it will pass a namespace with request , here , and the template's variables already on it. This means that the DTML object will be able to use the same names as if it were being published in the same context as the template, plus the variable names defined in the template.


Python Modules


The Python language comes with a large number of modules, which provide a wide variety of capabilities to Python programs. Each module is a collection of Python functions, data, and classes related to a single purpose, such as mathematical calculations or regular expressions.


Several modules, including "math" and "string", are available in Python Expressions by default. For example, you can get the value of π from the math module by writing "python:math.pi". To access it from a path expression, however, you need to use the modules variable. In this case, you would use "modules/math/pi". Please refer to the Zope Book or a DTML reference guide for more information about these modules.


The string module is hidden in Python expressions by the "string" expression type function, so you need to access it through the modules variable. You can do this directly in an expression in which you use it, or define a global variable for it, like this:


tal:define="global mstring modules/string" tal:replace="python:mstring.join(slist, ':')"

As long as you're using Python 2.0 or newer, you can avoid this in many cases using string methods:


tal:replace="python:':'.join(slist)"

Modules can be grouped into packages, which are simply a way of organizing and naming related modules. For instance, Zope's Python-based Scripts are provided by a collection of modules in the " PythonScripts " subpackage of the Zope "Products" package. In particular, the "standard" module in this package provides a number of useful formatting functions that are standard in the DTML "Var" tag. The full name of this module is "Products. PythonScripts .standard", so you could get access to it using either of the following statements:


tal:define="pps modules/Products.PythonScripts.standard" tal:define="pps python:modules['Products.PythonScripts.standard']"

Most Python modules cannot be accessed from Page Templates, DTML, or Scripts unless you add Zope security assertions to them. That's outside the scope of this document, and is covered by the Zope Security Guide.

About Me

Ordinary People that spend much time in the box
Powered By Blogger