After building some frontend stuff, I'm now exploring the internals of the admin side of Magento. I read Alan Storm's article on creating a simple model (as opposed to an EAV model, something which I am not yet ready for).
My main goal is to create a module that enables the user to upload and manage media to the Magento installation, so that it can be used in some templates I defined in the frontend. So I would create a model to keep track of the relations between certain media (pictures) and certain categories, pages, you name it. Just for the record: I don't like EAV models, they scare me, so unless it's absolutely necessary, don't push the conversation that way. Thank you :)
I've also skimmed through this article.
It's about backend models, and my question is about that:
What IS a backend model?
Is it a model that's used only in the backend (admin)? I wouldn't know what that would be good for. If someone could tell me something about it, or give me a hint on what to read to know more about it, it'd be great.
The reason I'm telling what goal I want to reach is so that someone can tell me if these "backend models" are significant to what I want.
Thanks!
Don't worry about EAV, don't worry about "backend models". You'll need some in the trenches programming experience before you can fully understand their significance. You can get a lot done with the plain-jane Magento model classes and SQL queries.
The light version: Backend models have nothing to do with the frontend-cart/backend-admin application split. A "backend model" handles loading, storing, and persisting information into a datastore (the database). A "frontend model" is PHP code that handles rendering a user interface element to display the attribute in the web browser. The terms are used in several different systems in Magento, including EAV and the System Configuration section.
The article you linked to is talking abou EAV backend models. Again, the light version: Each data property of an EAV model is, itself, an object. For example, in a simpler system you'd store the product's name as the string 'Bicycle'. In Magento you assign a product attribute object to the parent EAV model for name. This way, the code for saving "name" to the database can be kept separate from the other saving code.
Long story short, It's overkill for what you're after.
In Magento backend attribute models is used to prepare data before placing it in the database. This preparation is done by beforeSave method. A good exampe is Mage_Eav_Model_Entity_Attribute_Backend_Datetime
Related
I often get to the point in building a new Magento site where 301 rewrites need creating for all the items on the old site. Is there a way of importing them directly?
Programmatically via a urlCreate() type Magento function would be fine as then I could just cycle through a csv.
Generally it's a good idea to stick with Magento's ORM for interacting with entity data, as there may be both business logic and storage logic which is baked into the entity ORM stack (this is notoriously true for EAV entities). But, depending on the number of records to be entered, a direct-to-db approach should be fine, especially if it's a one-off import. This is because URL rewrites are flat entities stored in the core_url_rewrite table (link), and the table itself has the necessary storage logic as part of its structure (mainly, unique request_path + store_id and an FK for core_store table). In other words, manipulating this data outside of the ORM tier is okay because the logic is part of the table definition itself.
Beyond this information, it's possible to load up a core/url_rewrite collection, create core/url_rewrite instances from the CSV and add them, and then call save() on the collection, but note that each item is saved individually. It might do to refer to the convert adapters for catalog entities and for customers, which is how dataflow works.
I have programmed in Rails, Django, Zend, and CakePHP. Also, Wordpress and Drupal.
Now, I am "catching up to speed" in as fairly large application in CodeIgniter.
Typically, my experience with MVC frameworks, has led me to believe that Models represent business logic in reference to actual database tables. In the CodeIgniter docs and in the code base I'm dissecting I see models created that represent something as vague as a page. A lot of the business logic is written directly into those models and they incorporate other actual data models. I'm not sure this is ideal and following MVC.
Should models be created beyond data models?
Also, lets say I have a data model representing a user (user table in DB). In that user table there is a column called gender of the type enum('male', 'female'). Now I want to populate a dropdown with the gender options from the enum column.
Where is it most appropriate to put this logic?
The user model is an object used to represent a single user or row in the db... right? So it doesn't seem fitting to include a function in the user model/class called "get_gender_options", because, while the function is related to the user table, it is NOT relevant to a single user object. In Zend this kind of logic could be built into the form object itself.
There is not "right" answer, just one we can consider the most appropriate...
I would probably just put the "get_gender_options" in the model, rather than sticking it in the view for the form. To keep it DRY but not put it in the model, I would create a helper to hold this.
I am wondering how the models in code ignitor are suposed to be used.
Lets say I have a couple of tables in menu items database, and I want to query information for each table in different controllers. Do I make different model classes for each of the tables and layout the functions within them?
Thanks!
Models should contain all the functionality for retrieving and inserting data into your database. A controller will load a model:
$this->load->model('model_name');
The controller then fetches any data needed by the view through the abstract functions defined in your model.
It would be best to create a different model for each table although its is not essential.
You should read up about the MVC design pattern, it is used by codeigniter and many other frameworks because it is efficient and allows code reuse. More info about models can be found in the Codeigniter docs:
http://codeigniter.com/user_guide/general/models.html
CodeIgniter is flexible, and leaves this decision up to you. The user's guide does not say one way or the other how you should organize your code.
That said, to keep your code clean and easy to maintain I would recommend an approach where you try to limit each model to dealing with an individual table, or at least a single database entity. You certainly want to avoid having a single model to handle all of your database tables.
For my taste, CodeIgniter is too flexible here - I'd rather call it vague. A CI "model" has no spec, no interface, it can be things as different as:
An entity domain object, where each instance represents basically a record of a table. Sometimes it's an "anemic" domain object, each property maps directly to a DB column, little behaviour and little or no understanding of objects relationships and "graphs" (say, foreign keys in the DB are just integer ids in PHP). Or it can also be a "rich (or true) domain object", with all the business intelligence, and also knows about relations: say instead of $person->getAccountId() (returns int) we have $person->getAccount(); perhaps also knows how to persist itself (and perhaps also the full graph or related object - perhaps some notion of "dirtiness").
A service object, related to objects persistence and/or general DB querying: be a DataMapper, a DAO, etc. In this case we have typically one single instance (singleton) of the object (little or no state), typically one per DB table or per domain class.
When you read, in CI docs or forums, about , say, the Person model you can never know what kind of patter we are dealing with. Worse: frequently it's a ungly mix of those fundamentally different patterns.
This informality/vagueness is not specific to CI, rather to PHP frameworks, in my experience.
I'm talking about HUGE forms - like medical forms with 1000+ fields.
How do you logically create models for them? Do you include every single little field as seperate model? Do you have the whole form as a HUGE model with every single field? Do you have formsections as models and each formsection has few fields?
I know this might be subjective, but I really want some advice on someone who has dealt with this before and save others a lot of time down the road by avoiding mistakes at the onset.
Your data model should follow an EAV method. Medical systems are well suited to this approach as not all patients are going to have all this information filled in. This method allows you to fill in what is appropriate and populate your model. Makes organizing the data easier as well.
As for organizing it in the view, I suggest you break it up into sections where sections are logically related to each other (past history, family history or by type of information), making the information easier to digest.
I have a web application built on an MVC design.
I have a database which contains a large number of objects (forum threads) which I can't load into memory at once. I now want to display (part of) this collection with different filters in effect (kinda like what stackoverflow does with questions sorted by date, votes, tags etc).
Where do I implement the filtering logic? It seems to me that this must go into the model part of the application, as only models interact with the database (in my implementation). If I make the filtering a part of the view, then the view must access the database directly to get the list of filtered objects, right? I'd like to avoid this, because it exposes the database layout to the view. But at the same time, displaying different views of the same data should be implemented in the view part of the application, as they are just that -- different views of the same data.
So how do I resolve this? Do I create an additional model, say, FilteredThreadsList, and have it remember the filter to use, and then use a FilteredView to display the list of threads that FilteredThreadsList spits out?
Or do I have to build a ThreadQueryier that allows views to query the database for certain thread objects, so I can have the filtering logic in a view without exposing the database backend?
You should never query data from the view. I don't know what framework you are using in particular but as for Ruby on Rails (should be the same for other frameworks) we always pull the necessary data from the controller and store all that information into a variable. The variable will be accessed by the view which can help you avoid querying your database directly from the view.If the code to query the database gets too lengthy in the controller, insert that code into the model instead so it's more maintainable for your project in the future. Additionally, you can call this model method from multiple places in your application if needed. Good luck!
From an architectural point of view, the model should be having the code for filtering. This is so, because in many applications the code for filtering is not trivial and has a good amount of domain logic in it. (Think of filtering top gainers from a list of stocks). From your example as well, it looks the same since you might want to filter by vote or by date or by tags and then by answered or unanswered etc.
In some very simple applications that deal with search/list of entities and allows Create/Read/Update/Delete of an entity, the pagination, sorting and filtering logic is usually very generic and can be implemented in a controller base class that is inherited by all entity-specific controller classes.
The bottom line is this: if your filtering logic is generic put it in the controller else put it in the model.
Model, that's only bunch of entities.
View provides a visual representation of the data from model - use as much of views as you want. If your application is web based, you can fetch data into browser just once (AJAX) using and re-use them for different UI components rendered in the browser.
As for what entities and what view to use for their representation, I think it's work of Controller. If you need some support for it on "model layer", add it but avoid tight coupling.