I'm currently writing an EPOS integration for Magento. When an order is made, it's ID is placed in a queuefile. Once a minute, a cron looks at the queue, fires the top order to the EPOS web api and then moves the ID to either a successlist file or a faillist file, depending on the outcome.
In order to display the contents of these lists to the user, I created an admin page that reads the file (containing a serialized array), creates a varien_object containing the order ID, customer name and timestamp for each order, and then stores all of these in an instance of a Varien_Data_collection. This collection is then passed to the _prepareCollection function in the grid.php for rendering the grid view.
In 1.4.1.1, the grid renders fine, but the pagination is broken and the filtering doesn't work.
In 1.3.2.4 the grid renders but says there are 'No Records Found'.
Does anybody know what could be causing these issues, and if there is a better way of going about displaying information from a file in Magento?
The reason why you can see the entries (1.4+), but can't filter is that Magento is using the collection api to modify the object. If you are just pulling values out of a model, its no big deal, but if you are searching and filtering, Magento needs the collection to be an instance of a database. It uses Varien_Db_Select objects to make queries which resolve to raw sql, so that's not going to work on an array.
I would recommend trying to deal with the data in a different way.
It sounds like you are working with a flat file, so the obvious solution of constructing a sql query to fetch everything for you won't cut it. I would try creating an instance of Zend_Db_Table, and populating the values on the fly.
Something like this:
class Foo_Bar_Model_Resource_Success_Collection extends Mage_Core_Model_Resource_Db_Abstract
{
public function _construct()
{
//declare write adapter in config
$table = new Zend_Db_Table('my_db.my_table');
foreach($this->getEposArray() as $entry)
$table->insert($entry);
$this->_init('my_table', 'id');
}
}
Admittedly, I've never done anything quite like this, but have had the custom grid filter problem crop up on me before, and know that if you want to search, you need to have your data in a table of some sort. Check out Zend's docs on the matter. I'm pretty sure that there's a way to do this inside of Magento, but I couldn't begin to think about a solution.
My advice, store your cron job data in a database, it will make pulling the data back out much easier.
Related
I have an object for a „listing“, which has attributes like id, name, description, etc. which can be loaded via load($id) method.
It has some advanced attributes, too. For example multiple products (which is a separate object). To improve performance, I load them when you try to access them with listing->getProducts().
Now I want a save method in listing, to save the values back to the MySQL db. But I‘m not sure how to do that product saving in a clean way.
The best way would be adding a save method to products object and call it from the listing object, but that only saves the values. How do I handle added/removed products? That has to be done by the listing object I think. But how do I know if all products were removed or if they weren't even loaded (because they didn’t get accessed)?
All ways, like storing a boolean loaded products seem like a stupid solution. Do you have a good idea how to handle that? I‘m not inexperienced in coding but I want to improve my structure since I always end in a lot of code mess if projects get bigger.
I assume we are talking about adding, editing, and deleting products in your database. So you are probably going to need an 'insert' method and a 'delete' method (invoked from your list view). as well as the 'save' (update) method.
But the problem, or so I understand, is that you don't know which of these to use on a particular product line.
If you are just allowing the user to type willy nilly into input fields, so that you can't tell whether this is an edit, an insert, or a delete (or indeed which product you are editing or deleting, if you allow /every/ field to be changed) then you are making your life really complicated - is this necessary, from a business requirement/UI design perspective?
Consider something like listing the existing information read only and providing edit/insert/delete buttons.
I think I found a more or less good way on my own.
For the first problem (where to save what):
Storing of basic attributes of listing in the listing->save() method,
calling listing->products[]->save() to store products details,
syncing the listing<->product associations in listing->save().
Second problem (Deleting products, just because they didn't got load):
That was pretty easy, listing->products = null -> not loaded, listing->products = array() -> loaded, but empty. (I should got this earlier, haha)
This is a long running question that gets me every time I am developing.
I suppose it is not specific to CodeIgniter, but as I am using it, I will consider it in my example.
Firstly, which is better:
function add_entry($data_array)
{
//code to add entry
}
function edit_entry($data_array)
{
//code to update entry
}
OR
function save_changes($what,$data_array)
{
//if what == update update
//otherwise insert
}
Both produce the same action, but does it really matter which one you use?
Getting onto more complicated things.
I have a page where I need to get ONE entry from the database.
I also have a page where I need to get all the entries from the same database ordered by a user specified column.
My resultant method is a function similar to
function($data_array,$order_by='',$limit='')
{
//get where $data_array
//if order_by!='' add order by
//if limit !='' add limit
}
As I develop my application and realise new places where I need 'similar' database functionality I am what feels like hacking previous methods so they work with all my case scenarios. The methods end up containing lots of conditional statements, and getting quite complex with in some cases 4 or 5 input parameters.
Have I missed the point? I don't want duplicate code, and when for the most part the functions are very similar I feel like this 'hacking' methodology works best.
Could someone advise?
Finally my admin functionality is part of the same application in an admin controller. I have an admin model which contains specific methods for admin db interaction. I however use some model functionality from 'user' models.
FOr example if on an admin page I need to get details of a db entry I may load the user model to access this function. There is nothing wrong/insecure about this..? right?
In addition to that within my admin model itself I need to get data about a user database entry so I call my user model directly from my admin model. This is strictly OK, but why? If i need data and there is already a method in my user model which gets it.. it seems a little pointless to rewrite the code in the admin model BUT each time that function is called does it load the whole user model again?
Thanks a lot all.
In order, add edit in the model vs save. Personally I have a save built in MY_Model that chooses whether it is a save or an edit depending on the existence of a primary key in the data being passed, so obviously I prefer that method it means a lot less duplication of code since I can use the save for any table without having functions in the model at all.
As to the second question I think it depends on situation. I also have a number of functions that have a ton of conditionals on them depending on where they're used and for what. In some cases I'm finding this makes the legibility of the code a little rough. If you're running them all through if statements it also could be impacting performance. DRY is a concept, not a rule and like other design concepts there are times when they just don't make sense, it's like database normalization, it's my personal opinion it's VERY easy to over normalize a database and destroy performance and usability.
Finally, using user functions in the admin code. I don't see an issue here at all, the reverse probably isn't true, but rewriting a function just because it's an "admin" function, when it's identical to a user function is utterly pointless. So you're correct there, it's a waste of time and space.
What's a good way to pass a list of items 2-3 items to a method in my controller?
I was thinking of just using the URL.... like so:
http://myserver/myapp/mycontroller/mymethod/parm1/parm2/listitem1/listitem2/listitem3
Is there a better way to do this? This data is not coming from a form, but rather from a database query and I'm building a hyperlink with it.
I guess the only part that bothers me is that I won't know in advance how many items I have when i'm parsing this url.
Its possible that I'll get none, or all 3 or some value in between. So the method that then has to parse this url will just keep looping until uri->segment() returns false, indicating that it's hit the first empty uri segment.
Any suggestions would be appreciated.
Thanks
EDIT 1:
Just in case it wasn't clear, my model is getting the data from the database and will also build the list.
The question is really about parsing an undetermined number of uri segments.
Just wondering if there's a better way to do this.
Thanks!
EDIT 2
Here's some more information to help you understand my MVC app. I don't think my issue is the way I've organized my code as far as who is doing what.. But just in case it helps...
I have methodA in my model that queries database and passes back to my controller listitem1, listitem2 and listitem2.
The controller then builds a string that represents a URL like:
http://myserver/myapp/mycontroller/methodB/parm1/parm2/listitem1/listitem2/listitem3
Then the view display a hyperlink using the url above.
When the user clicks on this hyperlink, it calls methodB.
In methodB, I since I don't know the number of items, I will just loop through all segments until I hit my first false.
As far as why I need to do this / what I'm doing... here's some background info:
I'm query a database for a list of ports on a switch that are considered trunks - ones that should not be modified.
this is what method A does.
methodB run a command against a switch and it returns a bunch of data back. the view that displays the data from methodB will allow the end user to make further changes to the switch. before I display the data from methodB, i want to filter out the list of ports I got from methodA so they cannot be tampered with.
Hope this helps.
Edit 3
I need both methodA and methodB because they serve two different purposes. methodA displays summary data about ports from my database. Think of methodA as a function that shows documentation about the switch. The view for methodA in turn, provides "live" links to communicate with the actual switch - this is where methodB comes in. methodB is triggered by one of those live links and it goes and gets a list of ports - similar to methodA - except that it represents what actual, and it doesn't include user defined information about the port.
I guess I can have methodB communicate with my database and filter its data before it displays, but if i want to treat these two functions as separate APIs... aka - one set of functions get data out of the database, the other set is a tool to communicate with switches... - then i don't think i want one talking directly to the other. I would like the GUI to tie them together. In fact, i have created two separate models and controllers for what I'll call the database interface, and then the switch interface.
So far, i think the forms idea is the most elegant solution.
Thanks everyone, for reading.
place number of listitems as parametr 3
../mymethod/parm1/parm2/numberofitems/listitem1/listitem2/listitem3
and put 1, 2, or 3 as needed. In case when 0 put nothing - null, however make sure that controller would know what to do if null happend - do not expect items.
If the data is coming from a query it should be within a model in CodeIgniter if you wish for your application to truly MVC compliant. This might mean a restructuring of your application, which may be difficult but it would really benefit you in the future to create a model for all your database queries.
You can read up on codeigniter models here:
http://codeigniter.com/user_guide/general/models.html
And you can read up on the database class here: http://codeigniter.com/user_guide/database/index.html
I really suggest you do this.
If your data is already coming from a model you can call it by including the model:
$this->load->model('model_name');
$response = $this->model_name->model_function(parameters);
Edit: This would also solve the issue of an unknown number of list items as you can simply parse the response returned from the model function instead of trying to figure out a uri hack.
After reading all of the other answers + edits over, that's definitely not the way you want to do it.
Unless I'm misunderstanding your comments, here's the issue: The list of ports is domain data stored on your server. So why then, are you going to pull that data out, send it to the presentation layer, and show it to the user who will send it right back to the application? Skip the middle-man and have "MethodB" get that data.
Your "MethodB" should get this information itself before processing what it needs to do - domain data stays in the domain layer, and the view never sees any of that information directly (the user would see a link directly to "MethodB")
Alternatively, you could do this all in one query if your DB schema is conducive to such a join.
Something that has always bothered me is doing more than one loop to manipulate an array.
What I mean is, in the controller the data is fetched from the DB via a model. Lets say we are showing a list of users, and each user has a status (1,2,3 equates to verified, unverified, banned respectively). Within each iteration of the loop the status would be checked and displayed via another Db query (forget mysql joins in this example).
Now, would you do that in the controller within a loop, and then perform another loop in the view with all the data already fetched and pre-formed ready for display (therefore resulting in 2 loops).
--OR--
Would you just do it in the view therefore resulting in the one loop but with model calls from the view. I understand that this is ok in the strict MVC pattern but its frowned upon generally.
It seems silly to loop twice but then its tidier as all the data manipulation is kept within the controller.
I would do that nor in the view or the controller but on the model.
I explain :
Your controller's job is to retrieve the expected user list, check ACL, etc...
Your view's job is to present this data in an elegant form
Your Model job's in to fetch/store data from Database and ensure integrity. Userstatus is a model too for me.
My configuration make this pretty easy, I use mustache (Php port) for view, which allow me to call methods from my models directly in view. I wrote my own ORM for my models, that way I have wrappers.
Such code would look like that for me :
// Controller
$template = new Template('pages/users.html');
$template->users = mUser::find(); // return array of mUsers instances
echo $template->render();
// View
{{#users}} <!-- For each user -->
{{getName}} has status {{#getStatus}}{{getStatusName}}{{/getStatus}}<br />
<!-- getStatus is a method from mUser model, that return a mUserStatus instance -->
{{/users}}
/* More explain on the view syntax
{{name}} = $user->getName() (return string)
{{getStatus}} = $user->getStatus() (return instance of mUserStatus);
{{statusName}} = $user->getStatus()->getStatusName();
*/
You may want to have request caching for each model instances in request level so that you never runs a request twice times if not needed.
That seems more natural to me than to delegate it to controller. I try to put business intelligence on controllers, there is no need for intelligence nor programmer intervention to retrieve a status name for each user.
I Hope it help.
In my opinion logic that manipulates the data you're returning, should be located in the controller. Logic that manipulates the representation of your data can be located in the view.
So I would go for the second option.
But, as you pointed out yourself this is a choice of implementation.
Also note that multiple round trips to your DB are bad for performance. Your example is a typical n+1 problem, meaning that you have 1 'top' select query and then N more queries for each row in your first result set. If you encounter such a problem always try to solve them on the DB level.
Another note I would like to add is that in your example you're storing status explanations in the DB. If you want to provide your applications in other languages, this might prove to be a problem. But this is beyond the scope of your question :)
Doing two loops is the clean way. That is what I would do for most cases, but I think there is no gerneral answer to this. Like if you have a lot a data and performance gets an issue it would be better to forgett about MVC and just use one loop.
A third way would be to use a helper function you can call from the view. Now that I think about it... that would probably be the best way.
I am creating a CMS and am using serialize to handle publish and rollback, which seems to work fine. Basically, The normal site tables are what gets displayed and anything not displayed is serialized in a separate table. The problem however is in making the 'Preview' functions work.
Since the front end is created using normal SQL calls, and all the pre-published/rolled back data is in a separate table it would mean updating every sql statement with some fancy code to pull the version correct to the preview. It will also get especially problematic with things like limits etc and would be a nightmare for the front end.
The only other approach I can see is a separate database/table(s) for the preview copy, but many people may be using the preview function and I am loathe to create a duplicate database for every person using preview as it will very quickly get out of hand.
Is there any way of doing this that will allow preview, and rollback preview, but will not require much from the code that displays the contents of the database and also avoid the problem of mass duplication?
I'm not sure that storing your content data in more than 1 table depending on its state is the way to go.
I would store every version of the content in the same table, having a field which purpose would be to set the state of the content (old version, current version, currently being edited, whatever you want depending on your content editing workflow). That kind of status field plus a date date, would make your content versions way easier to manage.
I used this method for various applications, and was always satisfied with how easy it was to implement rollbacks, previews and even more complex stuff (cvs-like pseudo-branches, ...).
What eWolf means is that when you have a seperate model and view you can have your model supplying different data to the view and then you don't need to copy your database, but instead simply create a standard and a preview model.
The preview model doesn't have to make queries to the database but instead delivers the data that you store in it before passing it to the view.
Consider this example:
//in the controller:
$previewPage->setTitle("foo");
...
//in the view(when previewing):
$previewPage->getTitle(); // returns whatever you stored beforehand
//in the view(regular viewing):
$livePage->getTitle(); // queries the database and returns the result
To learn more about the Model-View-Controller pattern you might want to check out this article.
I hope that helps.
If you seperate Model, View and Controller, this should be no problem: You just take the model from somewhere else in the controller and pass it on to the view.