Development

/plugins/ysfDimensionsPlugin/branches/1.0/README

You must first sign up to be able to contribute.

root/plugins/ysfDimensionsPlugin/branches/1.0/README

Revision 8587, 12.8 kB (checked in by dwhittle, 4 years ago)

ysfDimensionsPlugin: fixed typo

Line 
1 = ysfDimensionsPlugin =
2
3 ysfDimensionsPlugin allows you to customize the behavior of your symfony application based on any runtim factors.  You can adjust the configuration, template selection, and action behavior based on a combination of dimensions chosen by you.  For instance, you can have a different navigation structure based on the country of the user or a cobrand, or a different logo URL based on the current skin.  These factors that affect the behavior (in this case, the country of the user and the skin selected) are the dimensions, and you may define as many as you wish.
4
5 Dimensions work by adding another level of cascading configuration, as well as by altering the location of the template or altering the name of the action class. All of this is made easy due to the forward thinking flexibility of symfony.
6
7 == Installation ==
8
9 This is not a standard plugin and installation should not be automated since core files are altered. You must manually install this plugin by following these easy steps:
10
11 '''1. Download the plugin via subversion'''
12
13 This plugin can be downloaded and installed into the plugins directory of your project.
14
15 {{{
16 cd path/to/your/project/plugins/
17 svn export http://svn.symfony-project.org/plugins/ysfDimensionsPlugin
18 }}}
19
20 '''2. Backup Files'''
21
22 The most important part of installing this plugin is backing up your original installation. First find out where symfony is installed (in pear or in your project) and then backup the following files:
23
24 {{{
25 cp /your/path/to/symfony/lib/config/sfLoader.class.php /your/path/to/symfony/lib/config/sfLoader.class.php.original
26 cp /your/path/to/symfony/data/config/constants.php /your/path/to/symfony/data/config/constants.php.original
27 }}}
28
29 '''3. Override Files'''
30
31 Now you can safely replace the core symfony files:
32
33 {{{
34 cp /path/to/your/project/plugins/ysfDimensionsPlugin/lib/config/sfLoader.class.php /your/path/to/symfony/lib/config/sfLoader.class.php
35 cp /path/to/your/project/plugins/ysfDimensionsPlugin/config/constants.php /your/path/to/symfony/data/config/constants.php
36 }}}
37
38 == Configuration ==
39
40 Now that the sfDimensions hooks are in place, you need to configure your application, by following the steps below:
41
42 '''1. Defining Available Dimensions'''
43
44 First we need to define the different dimensions a page may have and define all available values for each dimension in project/config/dimensions.yml:
45
46 {{{
47 dimensions:
48     culture:          [en, fr, it, de]
49     theme:            [classic, corporate]
50 }}}
51
52 '''2. Setting the Current Dimension'''
53
54 Next, you need to edit your project's config.php and add the following changes below the $sf_data_dir/$sf_lib_dir definitions:
55
56 {{{
57 /**
58  *
59  * Logic for determining dimensions
60  *
61  * Remember this file is called very early on in the symfony bootstrap process
62  * so there are no symfony utilities available,
63  *
64  */
65
66 // For now static values
67 $culture = (!empty($_REQUEST['culture'])) ? $_REQUEST['culture'] : 'en';
68 $theme = (!empty($_REQUEST['theme'])) ? $_REQUEST['theme'] : 'classic';
69
70 // define dimensions
71 $dimension = array('culture' => $culture, 'theme' => $theme);
72
73 // no autoloading available this early in bootstrap, so require absolutely
74 require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.'ysfDimensionsPlugin'.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'sfDimensions.class.php');
75
76 // set dimensions
77 sfDimensions::setDimension($dimension);
78 }}}
79
80 For now we're just setting the theme and culture based on a request parameter.
81 You will likely not want to base the dimension off raw user input, but of
82 something else, like the host name or stored user preferences.
83
84 == Examples ==
85
86 So what's really going on here?  We need to vary the site behavior based upon
87 various parameters.  Above, we're using the culture of the request as the
88 parameter, but we can use other settings like theme or colo as parameters as
89 well.  We can then specify several aspects of the symfony experience by means
90 of these dimensions.  For instance, we can specify different site logos
91 depending on the theme, or different servers depending on the culture, or
92 different page content based on the culture (for example, language translations
93 of a page).  We can also inherit functionality between settings, so if culture
94 => fr is almost the same as the generic configuration, it can inherit the
95 settings and just specify the changes it needs. We will go more into how this
96 works later, first lets explain the dimension configuration.
97
98 {{{
99 dimensions:
100     culture:          [en, fr, it, de]
101     theme:            [classic, corporate]
102 }}}
103
104 Our dimensions.yml file describes two levels of dimensions. The first named
105 'culture' that has four possible values: 'en, fr, it, de', and a second
106 dimension named 'theme' that has two possible values 'classic' and 'corporate'.
107
108 Any request can be for any combination of the dimensions culture and theme.
109 Here we have configured eight posssible unique dimensions (en_classic,
110 en_corporate, fr_classic, fr_corporate, it_classic, it_corporate, de_classic,
111 de_corporate). Dimensions function by looking in special directories for
112 configuration or template files. For example, if the current dimension was set
113 as culture => en, theme => classic, then symfony would form the dimension
114 string 'en_classic'. When symfony looks for a configuration or template file it
115 will insert a new order of precedence: first it will load files from
116 'en', then 'corporate', and then 'en_corporate'.  Regardless of the dimension
117 all of these will look in the generic (non dimension-specific) location for
118 settings last.  This means that if you don't want to specialize your behavior
119 at all, you can put settings in the same locations in symfony as you did before
120 using the ysfDimensionsPlugin.
121
122 There are three parts of the system that are configured by these settings:
123 configuration, templates, and actions.  All dimensions-specific files live
124 underneath a dimension-specific directory.  For app-level configuration, the
125 directory is in apps/<app>/modules/[config, templates]/<dimension>/*.  For
126 module-level configuration, it's in apps/<app>/modules/<module>/[actions,
127 config, templates, validate]/<dimension>/*
128
129 Let's talk a little about each of these.
130
131
132 === Configuration ===
133
134 symfony makes great use of configuration files to set up your web site.  These
135 files live in various config/ directories.  The settings largely end up in the
136 sfConfig object where you can fetch them from your application.
137
138 We handle the settings.yml, app.yml, routing.yml, databases.yml, module.yml, view.yml,
139 security.yml, mailer.yml, cache.yml, i18n.yml, and validate/*.yml as well.
140
141 You should put the dimension-specific files in a dimension-specific
142 subdirectory. For instance, we would put the 'app.yml' for the dimension
143 'culture => en, theme => corporate' in apps/myapp/config/en_corporate/app.yml,
144 and module.yml in apps/myapp/modules/mymodule/config/en_corporate/module.yml.
145
146 As with all of these settings, configurations are searched for in the order
147 specified by the original dimensions.yml file.  Any setting not specified in
148 one file will cause us to look in the subsequent files down the list. The order
149 is determined by applying a cartesian iteration, thus culture => en, theme =>
150 corporate ends up as a dimension 'en_corporate'. The search order will be from
151 most specific to generic: 'en_corporate', 'corporate', 'en', generic.  If
152 multiple configuration files are found in multiple paths, they will be merged
153 with the most specific values having precedence.
154
155 Let's try this.  Let's create a setting 'site' that we'll echo for a new 'test'
156 action.  Put this into apps/myapp/modules/mymodule/templates/testSuccess.php
157 (the generic location):
158
159 {{{
160 <h1>mymodule:test</h1>
161 <p>We are in the test template now.  Site setting is <?php echo $site ?>.</p>
162 }}}
163
164
165 Now add the action:
166
167 apps/myapp/modules/mymodule/actions/actions.class.php
168
169
170 {{{
171 <?php
172 class mymoduleActions extends sfAction
173 {
174   public function executeTest()
175   {
176     $this->site = sfConfig::get('app_site');
177   }
178 }
179 ?>
180 }}}
181
182
183 Now we just need to establish the setting itself.  This is an app-level setting
184 (app_) so it belongs in the app.yml file.  Let's create a base value.  Create
185 apps/myapp/config/app.yml:
186
187
188 {{{
189 all:
190   site: base
191 }}}
192
193
194 Now clear the cache (for now you'll need to do this whenever you add new action
195 code) and load the page at http://example.com/mymodule/test (change the
196 hostname for your box). You'll see the base setting.  Now hit
197 http://example.com/mymodule/test?culture=fr.  The setting is still base even
198 though you're in the fr culture.  Let's make a fr-specific setting.  Create
199 apps/myapp/config/fr/app.yml:
200
201
202 {{{
203 all:
204   site: fr
205 }}}
206
207
208 Now clear your configuration cache (symfony cc) and reload the last page.  What about
209 a theme?  Try this URL:
210 http://example.com/mymodule/test?culture=fr&theme=corporate.  It still says fr
211 because the fr_corporate site inherits the fr settings.  Let's override this
212 value again.  Create apps/myapp/config/fr_corporate/app.yml:
213
214
215 {{{
216 all:
217   site: fr_corporate
218 }}}
219
220
221 Clear the cache, and reload.  There you go.  If you go back to the previous
222 URLs pages you'll see that they each show the appropriate value, overriding the
223 base where necessary.
224
225 Here are the configuration files that are specialized to handle dimension-specific configuration.
226
227 The application configuration files that can be overridden are:
228
229 {{{
230 app.yml
231 factories.yml
232 filters.yml
233 settings.yml
234 cache.yml
235 security.yml
236 view.yml
237 routing.yml
238 databases.yml
239 }}}
240
241 The module level configuration files that can be overridden are:
242
243 {{{
244 cache.yml
245 module.yml
246 security.yml
247 view.yml
248 }}}
249
250 For each one, symfony will load all of the dimension-specific configuration files given
251 the specialization path specified by dimensions.yml (e.g. en_corporate, corporate, en,
252 generic) with the earlier files' settings overriding the later ones.  Otherwise, the
253 configurations work just as they did before the dimension-specific specialization. See
254 [http://www.symfony-project.org/book/trunk/05-Configuring-Symfony the symfony book] for
255 more information about these files.
256
257 === Templates ===
258
259 Dimension-specific templates are placed in the templates/<dimension>/
260 directory.  They are searched for in the order specified by the dimensions.yml
261 file, and the first found of the appropriate name is used.
262
263 Let's add some dimension-specific templates for our new action.
264 apps/myapp/modules/mymodule/templates/fr/testSuccess.php:
265
266
267 {{{
268 <h1>mymodule:test for fr</h1>
269 <p>We are in the test/france template now.  Site setting is <?php echo $site ?>.</p>
270 }}}
271
272 apps/myapp/modules/mymodule/templates/fr_corporate/templates/testSuccess.php:
273
274
275 {{{
276 <h1>mymodule:test for fr/corporate</h1>
277 <p>We are in the test/france/corporate template now.  Site setting is <?php echo $site ?>.</p>
278 }}}
279
280
281 Now try the URLs from above, for base, fr, and fr_corporate settings.  You
282 should see all three templates, each showing the setting from the previous
283 section as well.
284
285 === Actions (*not yet implemented*) ===
286
287 Dimension-specific actions are placed in the actions/<dimension>/ directory.
288 Since actions are specified in classes and classes need to have unique names,
289 you need to append the standard class names with the dimension.  So
290 mymoduleActions for the en_corporate configuration would be
291 mymoduleActions_en_corporate.  This class would go in the
292 actions/en_corporate/actions.class.php file.  The same is true for individual
293 action classes as well.  fooAction_en_corporate class would go in the
294 actions/en_corporate/actions/fooAction.class.php file.  Actions can inherit
295 functionality from other actions and don't need to 'require' them.  You could
296 have '''mymoduleActions_en_corporate extends mymoduleActions''' if you want to
297 share some behavior between all sites but override a specific action for
298 'en_corporate' dimension.
299
300 For example, let's just override the action for the all sites with the
301 dimension 'fr_corporate'.
302
303 apps/myapp/modules/mymodule/actions/fr_corporate/actions.class.php:
304
305 {{{
306 <?php
307 class mymoduleActions_fr_corporate extends mymoduleActions
308 {
309   public function executeTest()
310   {
311     parent::executeTest();
312     $this->site = 'override('.$this->site.')';
313   }
314 }
315 ?>
316 }}}
317
318
319 You'll need to clear the cache.  Now reload the 'fr_corporate' url from above
320 and you will see that we've overridden the site value on this page, while
321 inheriting the behavior of the base action.
322
323
324 === Performance ===
325
326
327 Installing the ysfDimensionsPlugin adds little overhead to your project. The only overhead
328 comes from looking for the same configuration files in multiple places. This is minimized
329 significantly as the configuration files are still compiled and cached.
330
331
332 == Todo ==
333
334    * add lookup sequences, to determine order of dimension lookup via cartesian expression
335    * add action overriding / extensions / chaining
336    * apc caching + performance tweaks
337    * more documentation with examples
338    * more unit tests, full functional test
339    * cleaner integration into symfony core
340    * dimension validation via dimensions.yml
341    * better caching for each dimensions (only overridden files)
Note: See TracBrowser for help on using the browser.