Development

/plugins/ysfDimensionsPlugin/branches/1.1/README

You must first sign up to be able to contribute.

root/plugins/ysfDimensionsPlugin/branches/1.1/README

Revision 9330, 12.3 kB (checked in by dwhittle, 5 years ago)

ysfDimensionsPlugin: fixed wiki formatting + added note about 1.0

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