Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 21 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
21
Dung lượng
53,44 KB
Nội dung
Chapter2:Components-P2 This example demonstrates all the syntax possibilities for this block. First of all, we have argument types and names. The valid types are scalar, array, and hash, represented by their corresponding Perl sigil ($, @, or %), exactly as would be expected. It is possible to give an argument a default value to be used if none is provided when the component is called. Any argument without a default is considered a required argument. Calling a component without specifying all its required arguments will cause a fatal exception to be thrown. An argument's default can refer to an earlier argument, so this is completely legal: <%args> $x $y => $x * 2 > 20 ? 50 : 100 </%args> While this block looks as if it contains Perl, it is important to realize that its syntax is actually something unique to Mason. Importantly, lines should not end with a semicolon or comma, and each variable definition must be on a single line. It is possible to have comments both after an argument declaration and on their own line. Comments start with the # character and continue to the end of the line, just as in Perl. Blank lines are also allowed. <%filter> blocks A <%filter> block is called after a component has finished running. It is given the entire output of the component in the $_ variable, and any changes to this variable are reflected in the output of the component. For example, this filter uppercases all of the component's output: <%filter> s/(\w+)/\U$1/g </%filter> <%once> blocks This block is executed whenever the component is loaded into memory. It is executed before any other block (including an <%init> block). Any variables declared here remain in existence (and in scope) until the component is flushed from memory or the Perl interpreter running Mason shuts down, whichever comes first. The <%once> section is useful for things like creating database handles or instantiating large, resource- intensive objects. The universe is this big: <% $size %> <%once> my $size = calculate_size_of_universe( ); </%once> <%cleanup> blocks The cleanup block is executed right before the component exits and is the counterpart to the <%init> block. It is useful if you have created resources -- such as circular references -- that need to be freed. Technically, it is the same as placing a <%perl> block at the end of a component. <%init> my $resource = get_a_resource( ); </%init> . do something interesting with that resource <%cleanup> $resource->dispose; </%cleanup> Since cleanup code tends to be put at the end of the component anyway, <%cleanup> blocks aren't very common. Their chief advantage is that their name is cleanup . Cleanup blocks are not executed if the component dies or aborts. <%text> blocks The contents of this block are output exactly as they are, without any parsing. This if useful if you need to write a component containing text about Mason. For example: <%text> Substitution tags look like this: <% $var %>. </%text> <%doc> blocks This block is intended for use by component authors for documentation purposes. Its contents are completely ignored. In the future Mason may do something more useful with them. <%doc> =head1 My Story This is the part where I tell you what the component does. But I'd rather tell you a story about my childhood. When I was but a child, my mother said to me . </%doc> As you can see, there's no reason not to use POD (Perl's Plain Old Documentation markup language) in these blocks, and you can even run perldoc on a component file. <%flags> and <%attr> blocks These two blocks share the same syntax and are used to declare one or more key/value pairs. The key can contain only letters, numbers, and the underscore character ( _ ). The value can be any Perl expression whose results can fit into a scalar (such as a number, string, reference, or undef ). As in the <%args> block, the syntax in these blocks looks like Perl, but it is not. First, you cannot end a line with a comma or semicolon. Second, the whole key/value pair must be on a single line. The difference between these two is that the <%flags> block may contain only official Mason flags, which are used to affect the component's behavior. Currently, there is only one flag defined, inherit. This is used to specify the component's parent component. Component inheritance is discussed inChapter 3 . The <%attr> block may contain any keys that you want, as the variables defined in this block are not used by Mason but may be used in your code. Its contents are available by calling the object's attr() method and giving the desired key as the argument. See Chapter 5 for the details. <%flags> inherit => '/some/other/component' </%flags> <%attr> color => "I'm so blue" size => 'mucho grande' </%attr> My color: <% $m->base_comp->attr('color') %> There is one other important difference between flags and attributes: flags refer to only the current component, whereas attributes are part of Mason's inheritance scheme, discussed inChapter 5 . <%def> and <%method> blocks These two blocks use a syntax slightly different from any other Mason block because their contents are, in turn, components. The <%def> block contains a subcomponent, an embedded component that can be called via the normal Mason component calling syntax. A <%method> block also contains an embedded component, but one that may be inherited by a component's children. <%def> and <%method> blocks require a name in the initial tag. In the following example, a subcomponent named .make_a_link is defined: <%def .make_a_link> <a href="<% $url %>"><% $text %></a> <%args> $path %query => ( ) $text </%args> <%init> my $url = . </%init> </%def> The name of a subcomponent or method may contain alphanumerics, underscores ( _ ), dashes ( - ), or periods ( . ). Customarily, a period is the first character of subcomponent names, in order to distinguish them from nonembedded components. Methods generally do not follow this convention; they have names without leading periods. The main difference between subcomponents and methods is simply that subcomponents are visible only within the component in which they are defined, whereas methods are visible outside of the component and can be inherited via Mason's component inheritance mechanism. Subcomponents and methods are covered inChapter 5 . <%shared> blocks This block also contains Perl code. Code in this block is executed once per request, before the <%init> block, but unlike in an <%init> block, the variables declared in this block are in scope both in the component's main body and in any subcomponents or methods it may contain. This is useful for sharing a common chunk of code between all the parts of a single component. The uses of this block are discussed inChapter 5 . Escaping a Newline When using Mason, you may find that you want to suppress a newline in your text. A typical example is this: <pre> I am % if ($height < 5) { not % } elsif ( $height < 5.75 ) { not very % } elsif ( $height > 6.25 ) { very % } tall </pre> This will generate the following output if $height is less than 5: <pre> I am not tall </pre> The newlines in the output are not desirable but are unavoidable because of the need for the Perl code to exist on separate lines. Mason therefore provides the ability to get rid of a newline simply by preceding it with a backslash ( \ ). If we rewrote the preceding example with escaped newlines, it would look like this: <pre> I am\ % if ($height < 5) { not\ % } elsif ( $height < 5.75 ) { not very\ % } elsif ( $height > 6.25 ) { very\ % } tall </pre> Given this, the output for a $height less than 5 would then be: <pre> I am not tall </pre> This example could be redone on a single line using multiple <%perl> blocks, but it would be pretty hideous looking. Component Arguments Most components will expect to receive named arguments, and these can be passed in one of two ways. Components can receive arguments as the result of external requests, such as those via HTTP, or they can receive arguments when they are called from another component. These arguments are available in the called component via several mechanisms. But from a component's perspective, how it is called is largely irrelevant. <%args> Block Revisited Since we are talking about arguments, it is worth revisiting the <%args> block discussed previously. This block is used to declare the arguments that a component expects. In addition, it can also be used to specify a default value if none is given when the component is called. The block we used earlier was: <%args> $color $size => 20 @items => ( 1, 2, 'something else' ) %pairs => ( key1 => 1, key2 => 'value' ) </%args> This says, in English, that this component expects two scalars, one named color , which is mandatory, and one named size , which is not mandatory and defaults to 20. It also expects an array named items , which defaults to (1, 2, 'something else') and a hash named pairs, which defaults to (key1 => 1, key2 => 'value' ). Neither of these latter two arguments is mandatory. These arguments are all available in your component as lexically scoped variables. For example, your component will have a lexically scoped $color variable available. You do not need to declare it anywhere but in the <%args> block. If a mandatory argument (one with no default) is not provided in the call to the component, an exception is thrown. If an argument with a default is not given a value, the default is transparently assigned to the variable. Just to be [...]... of the components shown inChapter 8 Footnotes 1 For the curious, these issues are covered inChapter 3, Chapter 5, and Chapter 12 Return 2 The percent sign (%) must occur at the beginning of the line Return 3 The HTML: :Mason: :Request object provides access to several properties and methods concerning the currently executing chain of components It is treated in detail inChapter 4 Return 4 Component... detail inChapter 4 $r If Mason is running under mod _perl (as is the case in most Mason setups), all components also have access to the Apache request object via the global variable $r Mason' s special hooks into mod _perl are covered inChapter 7 Sample Component The component shown in Example 2-1 is part of our sample site and the focus of Chapter 8 The component here is responsible for displaying news... optional If you are expecting input with a large number of similarly named items, such as input1 , input2 , and so on through input20 , declaring all of them in an block may be a bit unwieldy In this case, the %ARGS hash can be quite handy %ARGS is also useful if you expect arguments with names that cannot be used for Perl variables For example, when submitting a web form by clicking on an image named... returned by several of the HTML: :Mason: :Request and HTML: :Mason: :Interp methods, covered in detail inChapter 4 and Chapter 6 Return 5 Unless the component is called with an odd number of arguments See the next section for details on this exception Return 6 We know of no browsers that actually screw it up, but surely there must be some out there Browsers have a history of simply making up their own unique... /some/component?colors=blue&colors=cyan&colors=green&colors= mint [ 'blue', 'cyan', 'green', 'mint' ] &> Now, $colors contains a reference to a four-element array, and the @colors array has four elements as well Finally, the assignment to %colors works without an error and will result in a hash containing ('blue'=>'cyan','green'=>'mint' ) $ARGS{colors} contains the same array reference as $colors... parameter will end up containing a reference to an array, as will $ARGS{foo} Future versions of Mason may provide the ability to coerce these arguments into specific data structures If a parameter is declared as an array (@foo), it will contain zero or more values depending on what is in the query string and/or POST data A hash is treated more or less like an array, except that giving a parameter declared... something else, you can add an explicit return() statement inside that component, such as this: my $size = 20; return $size; Perl' s return() function will end processing of the component, and any values specified will be the return value of $m->comp() Since Perl' s normal rules of scalar/list context apply, a component may return either a scalar or a list Special Globals All Mason components... scenarios involving argument passing, first via an HTTP URL query string and then via an internal component call Then we will see how this interacts with the component's block and the %ARGS hash Arguments submitted via POST and GET requests are treated in exactly the same way, and if both are present they are merged together before the component is called Let's assume that the component being called... /some/component, colors => { blue => 'cyan', green => 'mint' } &> This set of arguments isn't representable with a query string, because there's no way to indicate that the arguments are structured in a hash via a web request In this call, $colors contains a reference to a hash, not an array, though the @colors array contains four elements, just as in the previous example The %colors hash is likewise... are converted into component calls Specifically, we are interested in how query string and POST parameters are converted into arguments These requests are expected to be in the standard name/value pair scheme used by most web interfaces If a parameter is given only once (i.e., component?foo=1&bar=2), it will be present in the %ARGS hash as a simple scalar, regardless of how it is declared in the . placing a < %perl& gt; block at the end of a component. <%init> my $resource = get_a_resource( ); </%init> . do something interesting with. all the parts of a single component. The uses of this block are discussed in Chapter 5 . Escaping a Newline When using Mason, you may find that you want