Hi developers,

as you might have guessed, I am not working on the sfGrid components
solely to provide them to the community ;) What I would like, is to
get feedback to improve the quality of these components, while
everyone can benefit.

At the moment I am working on/playing with the responsibilities of the
different objects in the sfGrid-plugin to transform a request into a
view, and could therefore use your insight.

Recap
=====
I guess that everyone is currently is aware of the function of
 - dataSources: providing a unified way to access and manipulate
datasets.
 - sfGrid: rendering the data from the dataSource and handling user-
interaction.

the dataSource can handle data from arrays, Propel, Doctrine, etc.
the grids in their turn can process (web)requests and render to HTML,
JavaScript, JSON, etc in any way you like.
Both components can be extended in any way you like, which should make
them flexible enough to handle everyone's usecases.


Grid Usecases
===========
Let me first provide you with some usecases:
1. a view where you have one grid. This grid shows selected columns of
your dataset, paginated and sortable.
For example a list of Countries, paginated and sortable.

2. a view where you have two grids. In this case the interaction with
the two grids should of course not conflict with each other.
For example a list of Countries and a list of Cities. You should be
able to sort both the Country-list and the City-list independently of
each other. Maybe the content in your city-list is related to your
selection in the country-list, which introduces some kind of filtering
for the city-list.

3. a view where you have some query-parameters that aren't part of the
grid, but should be handled as well.
This is slightly similar as in 2. So for example a list of cities for
a certain country.

4. a view with a filter
This is also slightly similar to 2 and 3. So for example all
countries, that start with the letter 'A'


Components
==========
Of course it will be of no surprise to any of you that (web)requests
(URLs) are transformed to (web)responses (E.G. HTML, or JavaScript,
etc).

Symfony provides several nice components to handle the different
stages of this process:
1. The Routing: Urls are matched against a routing rule, to make
routing-classes process the request.
2. The Controller: After the routing has been performed you will end
up in a controller. Here we can process user interactions and build
objects to provide to the template
3. The View. Here we present the result to the user (possibly by using
renderText, omitting templates)


THE QUESTION
=============
Enough background I think, lets start with the initial question:
What should be done where?

What we already know is:
1. The routing receives a request (URL)
2. The routing results in a specific Controller (module)
3. The Controller provides a grid to the View
4. The View renders the grid

However there are some things that need to be done before you have a
bound grid in your controller.


In my previous examples I have already shown how you can specialize
the DataSource and Grid classes:
- a CountryDataSource that knows how to get a list of countries from
the database with propel (by specializing sfDataSourcePropel)
- a CountryGrid that uses the datasource (filled with countries
preferably), and is configured with the columns you want to view from
the source.

This way you can reuse grids and datasources in different modules or
even tasks, and keep the controllers small.


But how and where are the (specialized) datasource and grid classes
1. instantiated
2. bound to the request (to handle interaction)


ROUTING
-------------
when the request is being processed, I think the routing-class can
provide the following functionality when from the controller a
getObject() method is called:

  public function execute($request)
  {
    $this->getRoute()->getObject();


1. Don't do anything at all (the router only resolves a specific
controller and does not implement a getObject method)

2. Parse the request and retrieve the start object from your model:
E.G. a (Country)DataSource for usecase 1, or a country for usecase 3
(the country class contains a method getCityDataSource to get the
cityDataSource)

3. Parse the request and retrieve all objects from your MODEL: E.G. in
usecase 2 a CountryDataSource, a CityDataSource and a CountryObject
for the selected Country.

4. Parse the request and return the Grids (that already contain the
corresponding dataSources (is construction of and linking to the
datasource done by the router, or in the constuctor of the grid, see
point 1 and 2 of the controller as well)).

5. Parse the request and return the Grids (that again already contain
the corresponding dataSources) and are bound*(possible with the help
of a container, see below) to the request (so sorting and filtering
are processed by the routing as well).


CONTROLLER
--------------------
depending on the chosen solution/responsibility for the routing, there
is some (more) work left for the Controller itself.

1. The controller instantiates a Grid and a dataSource and links the
dataSource to the grid. Then binds* (possible with the help of a
container, see below) the requests to the grid(s) the requests to the
grid(s).

2. The controller instantiates a Grid which already contains a
dataGrid, and binds* the request

3. The controller asks the route for the base object, E.G. usecase 2
the CountryDataSource. resolves if the request contains a selected
Country, retrieves this selected country from the CountryDatasource,
and from this country gets the cityDataSource. Then constructs the
CountryGrid and CityGrid, providing them their datasources and
binding* them to the request to handle interaction.

4. The controller asks the route for ALL model-classes (E.G.
Datasources and base Objects) and injects these to the constructors of
the grids, after which the grids can be bound* to the request.

5. The controller asks the route for the fully prepared grids and
passes them directly to the template (when rendered as html, or render
as text in case of json or JavaScript)


*binding with a Container
---------------------------------
When more than one grid is used in a html view, Containers that
implement a "bind"-interface can be used to delegate the binding of
the request to the grids and which define non-conflicting namespaces
to the grids, that are used in the grids to generate urls for the
actions with distinguishable parameters


Real Question
-------------------
The current base of the plain sfGrid and sfDataSource class is (I
think) well designed and capable to handle all of these different
solutions. Both classes can be specialised to keep the configuration
out of your routing/controller, allowing them to stay lean, doing only
what they should do. Since the grid is aware of the datasource-
interface, you can inject datasources; allowing you to instantiate the
datasource wherever you want however grids and datasources will always
be coupled to some degree, since a grid will probably always be
designed to represent a specific dataSource. The Grid is also
specialised by two different classes:
- the first providing context-awareness to the grid, allowing the grid
to maintain its own state in the session, although the parsing of the
request CAN be done from outside the grid.
- the second adding a bind method, so you handle request parameters by
the grid itself.


The question is what are the responsibilities of the different
elements, and in specific of the routing and controller objects? Who
should do what to handle request and transform them into rendered
grids.
1. who instantiates the correct classes (E.G. cityDataSource, not
countryDataSource, or cityGrid....)
2. who parses the request parameters to handle interaction (parsing of
parameters should probably be handled by the grids, but who calls the
handle method of the grid and providing the request(parameters))
3. how should the grid create new urls for its specific actions (go to
page, sort on this). You probably want the routing to be used here to
generate nice urls. However it should keep the current request-
parameters into account (not loosing the current Country-id when
sorting a grid with cities in a specific country)
4. should the grid handle filtering, or the controller in combination
with the datasources?



Future
=====
Once these issues are solved and the solution is agreed on next thing
on the agenda is improving the rendering/templating. I am thinking
about a way to simplify the use of widgets, maybe by using the power
of Twig

-- 
If you want to report a vulnerability issue on symfony, please send it to 
security at symfony-project.com

You received this message because you are subscribed to the Google
Groups "symfony users" group.
To post to this group, send email to symfony-users@googlegroups.com
To unsubscribe from this group, send email to
symfony-users+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/symfony-users?hl=en

Reply via email to