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