Welcome Guest, Not a member yet? Register   Sign In
Converting my report system to a MVC pattern
#1

[eluser]D_Williams[/eluser]
I'm new to both CI and MVC. I have a bunch of code going at work and I'm continually expanding on it. I've read a bunch about CI and I really like it. I want to start converting all my current code over to CI, starting with my report system.

My report system is fairly decent, but it has problems that I feel would be helped by CI (specifically form validation, authentication, and general formatting but there's not the point of this topic).

The basic synopsis of how my report system works is as follows: I have a viewreport.php file in my root directory that serves as the report engine. I have a "reports" directory with one PHP file for each report. Each file in "reports" implements a getReportHTML() function and a displayConfig() function as well as sets some report-specific config values. It's pretty obvious what these functions do, displayConfig() outputs a form asking for what input the form requires (dates, ranges, and so forth). getReportHTML() queries the database, does the processing, and returns (not echoes) HTML for the report's table and such. viewreport.php takes a report name from GET and includes "reports/<whatever report>" then runs the report when the config has been set, giving the user the option of displaying it in-page, downloading as PDF, emailing it, or saving it on the server.

I'm a bit caught up on how to implement this in CI. It seems like what I have now is a little bit similar to the MVC pattern, but not all the way there. I was hoping somebody could help me with a basic MVC structure for this project.

So far these are my thoughts:

Models: I'm not sure what to do here really. Most (but not all) reports deal with either my accounts table or my payments table, but they usually require vastly different column names from all the other reports. "accounts" has about 75 columns and payments has around 40 (yes I know that's crazy but this database isn't normalized very well, I'm not the one who designed it and re-designing it is a bigger project than I care to undertake), so I don't want to just have some "get account row" or "get payment row" model function that returns the whole row since it's very inefficient to pull down 75 columns when I just need 4 or 5. On the other hand, I don't want to have a thousand little functions retrieving a column here and a column there, and I don't want to have a model or model function specific to any reports.

Controllers: Again my goal for most of this is to leave report-specific code out of the "report engine" itself as much as possible and have pluggable reports. What I'm thinking about doing is sticking to having a "reports" folder and put it under application/reports. I would have a "reports" controller. The index function would quite literally be an index and output a list of all reports in the reports folder and display a link to another function under the reports controller, but I'm not sure where to go from here. I need to keep the ability to have my users be able to choose what to do with their reports (display in page, PDF, email, etc), so I can't just call a single controller function to display it in a page. Right about here is where my thought process starts getting muddy.

Views: I don't see any option here other than to have multiple views for each report representing the different report destinations like report1_email report1_pdf and report1_page.


Thanks in advance to anyone who can help me clear this up Big Grin
#2

[eluser]Nick_MyShuitings[/eluser]
[quote author="D_Williams" date="1283378764"]
Models: I'm not sure what to do here really. Most (but not all) reports deal with either my accounts table or my payments table, but they usually require vastly different column names from all the other reports. "accounts" has about 75 columns and payments has around 40 (yes I know that's crazy but this database isn't normalized very well, I'm not the one who designed it and re-designing it is a bigger project than I care to undertake), so I don't want to just have some "get account row" or "get payment row" model function that returns the whole row since it's very inefficient to pull down 75 columns when I just need 4 or 5. On the other hand, I don't want to have a thousand little functions retrieving a column here and a column there, and I don't want to have a model or model function specific to any reports.[/quote] It might be nasty, but you can do dynamic functions, where you have a single get, get_by, which receives as part of its parameters the columns that you would like to select. That would allow you to maintain two clean models and not a lot of redundancy within them, and when you call the model from the controller you could pass the columns you need. With regards to updates and inserts, if you are using active record then you can already just arm the array with the pertinent fields and it will ignore the rest.
[quote author="D_Williams" date="1283378764"]Controllers: Again my goal for most of this is to leave report-specific code out of the "report engine" itself as much as possible and have pluggable reports. What I'm thinking about doing is sticking to having a "reports" folder and put it under application/reports. I would have a "reports" controller. The index function would quite literally be an index and output a list of all reports in the reports folder and display a link to another function under the reports controller, but I'm not sure where to go from here. I need to keep the ability to have my users be able to choose what to do with their reports (display in page, PDF, email, etc), so I can't just call a single controller function to display it in a page. Right about here is where my thought process starts getting muddy.[/quote]That still sounds like a monster of a hybrid. You could get it a lot cleaner if you dove fully into MVC. For example, you create the controller "Reporting.php". This has the index like you describe that is a list of the methods the controller contains. You have the method "report1". This method calls a model function which gets it the information it needs in a raw format like an array. This method also receives a parameter (or many such as fancy filters in the future to pass to the model so that the array you get back is different), this parameter is the view format to parse the array into. So your method consists of a model call, followed by an if statement that will throw that $data array into a different view file to be parsed out. The view files could hopefully be reused by more then one report at the least, if you made them dynamic enough in creating the tables etc.

Long story short doing it this way you actually start to see the benefits of MVC, such as modifying your model calls for pagination, or filters, and not having to modify the rest of the code. Adding a new report would consist of creating a new method, testing the models to make sure they work, hoping the final output is similar to an already exiting view, if not creating a new view file etc.
[quote author="D_Williams" date="1283378764"]Views: I don't see any option here other than to have multiple views for each report representing the different report destinations like report1_email report1_pdf and report1_page. [/quote] Nope, just try and be as creative as possible, and don't be nuerotic about not putting php in your view. If you're good with loops and html you could prolly reuse the same view multiple times if you make a count of the columns and create them and the headers from the array prior to looping through the rows.

Good luck
#3

[eluser]D_Williams[/eluser]
[quote author="Nick_MyShuitings" date="1283424190"]
[quote author="D_Williams" date="1283378764"]Controllers: Again my goal for most of this is to leave report-specific code out of the "report engine" itself as much as possible and have pluggable reports. What I'm thinking about doing is sticking to having a "reports" folder and put it under application/reports. I would have a "reports" controller. The index function would quite literally be an index and output a list of all reports in the reports folder and display a link to another function under the reports controller, but I'm not sure where to go from here. I need to keep the ability to have my users be able to choose what to do with their reports (display in page, PDF, email, etc), so I can't just call a single controller function to display it in a page. Right about here is where my thought process starts getting muddy.[/quote]That still sounds like a monster of a hybrid. You could get it a lot cleaner if you dove fully into MVC. For example, you create the controller "Reporting.php". This has the index like you describe that is a list of the methods the controller contains. You have the method "report1". This method calls a model function which gets it the information it needs in a raw format like an array. This method also receives a parameter (or many such as fancy filters in the future to pass to the model so that the array you get back is different), this parameter is the view format to parse the array into. So your method consists of a model call, followed by an if statement that will throw that $data array into a different view file to be parsed out. The view files could hopefully be reused by more then one report at the least, if you made them dynamic enough in creating the tables etc.

Long story short doing it this way you actually start to see the benefits of MVC, such as modifying your model calls for pagination, or filters, and not having to modify the rest of the code. Adding a new report would consist of creating a new method, testing the models to make sure they work, hoping the final output is similar to an already exiting view, if not creating a new view file etc.[/quote]

My primary concern with this is that having the report logic for every report in one controller is going to make one monstrously large controller file. I guess that's acceptable but meh.

Also another hindrance of mine is finding a way to neatly handle the report config. Again I don't particularly want to have a view file for every report's configuration options but where else can I specify which reports need what fields for configuration?

The best thing I can think of is having a very PHP-heavy "report config" view file that takes a list of requested inputs in a data array, or maybe having a helper file to cut down on the amount of PHP in the view.
#4

[eluser]Nick_MyShuitings[/eluser]
Depending on how your reports are broken down you could use something like Matchbox or Modular Separation to create a reporting module. In that module you could have controllers for each type of report, for example "user.php", "usage.php".

Then your files would be logically separated, and your urls would still be informative:

htpp://example.com/reporting/user/new following the format of http://url/module/controller/method.

I've had bad luck doing partial merges, so I'd personal retackle it as a CI project... its always helped reduce bugs and overall work in the long run for me.




Theme © iAndrew 2016 - Forum software by © MyBB