1

I have a view with several megabytes of data and I expect it to grow radically. Controller index function is implemented in a default way, with pagination. I would like to export this view to a csv without making much changes to the controller ( I'm fine to define header rows and rows to be included in a CSV but not to remove pagination as it brakes the html representation ).

The idea is simple: render csv view template, change the page, render another one. But how can I change current pagination settings in a custom view?

PS: I did take a look at the csv plugin. It doesn't work with pagination so I get out of the memory limits, it also creates a tmp file, I prefer to stream content on the fly.

hryamzik
  • 849
  • 1
  • 9
  • 16

1 Answers1

1

I wouldn't use the paginator here, just get the total amount of records then do a while() loop and fetch the data in batches to avoid memory limitations. And send it as it comes from the DB directly to the client. Use the HTTP Client that comes with CakePHP and set the proper header properties.

See these two answers how to send it as stream:

Community
  • 1
  • 1
floriank
  • 25,546
  • 9
  • 42
  • 66
  • this seem to be a controller side solution, exactly what i'm trying to avoid ( and what I've already implemented ). – hryamzik Jul 08 '15 at 16:00
  • 1
    Well, then implement it in a model method, pass the response object to that method and send the response from the controller. However you implement it, you'll have to return somehow a stream handler or something similar from the model method that you can send to the client. But sending data to the client isn't the job of the model. The model shouldn't have to be aware of the request. – floriank Jul 08 '15 at 16:24
  • That's exactly what I'm talking about. This is not about a model, not even about controller, this is about view or "view controller", and the last one is a custom view class. The other reason to avoid model/controller implementation is that I want to get this functionality on all the implemented code without modifying it ( I'm still fine to implement some individual templates code or define header rows somehow ). – hryamzik Jul 08 '15 at 20:17
  • Then create a new class, pass the query or table object as constructor and the response object, do your own pagination inside a method of this class and use it wherever you want - or make it a trait. Instead of focusing on a fancy solution (for which I don't see a reason here) focus on getting the task done instead of wasting a lot of time? Make it work then make it work better. Maybe you can explain the problem in more detail. – floriank Jul 08 '15 at 22:06
  • I've already done the CSV export with a separate code in a controller, so I'm not waisting time. Just looking for a better, more universal and portable solution. You suggest making my own pagination in a new class, that's exactly what I'm talking about, the initial question is how to make your own pagination in a custom view? =) – hryamzik Jul 09 '15 at 12:45
  • 1
    Data processing is not done in a view. You don't even really have to build a view for that when you stream your CSV data to a client. Just build the data on the fly in the while() loop and immediately send it using the response object. But do as you wish and keep spending time on your idea. I'm curious how the end result is going to look like. Mind doing a gist with the code then? – floriank Jul 09 '15 at 12:59
  • If I'll find a way to tune pagination settings on the go in a custom view I'll publish this plugin. I do stream from the controller directly right now, including setting headers, and I find this an MVC nightmare. The view should grab chunks of data from controller in a pagination way with some settings different from html view ("pages could be larger"). – hryamzik Jul 09 '15 at 17:23
  • You find it a nightmare because *you do it wrong*. ;) "The view should grab chunks of data from controller" this is totally wrong and against the MVC pattern. But do as you like and good luck with the anti-pattern. :) – floriank Jul 10 '15 at 14:19