Loading an attribute value without loading an entire entity - php

So I was writing a piece of functionality where I was getting the parent category ids of a category and wanted to get the url_key of one of the parents in Magento. I wanted to do this without having to load the category and found this method getAttributeRawValue, which can be found here /app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Abstract.php. Basically it seems unnecessary to load a whole entity then to just get the attribute value associated to that entity id.
It gets me what I need, but I am wondering if it is all that much better then loading the category and getting the attribute. Is loading the category essentially doing the same thing but doing it for every attribute?

My first thought would be to use the inbuilt Varien Profiler to test it quantitatively. It's an underutilized by very useful trick.
Basically, you need to turn on Profiling in the Admin (System>Config>Advanced>Developer>Debug>Profiler) and then insert the start/stop instructions with a unique string either side of the code that you want to profile. e.g.
Varien_Profiler::start('__CATEGORY_URL_KEY_RETURN__');
....
your code here
....
Varien_Profiler::stop('__CATEGORY_URL_KEY_RETURN__');
Load the page in your browser and you will see the Profiler output at the base.
Enjoy!

Related

Typo3 Plugin Inline Records in Frontend Controller

I'm trying to create a Typo3 Extension using extbase and stumbled upon a problem.
What I have done so far is this:
I created a plugin editable via flexform for the backend. The plugin allows for dynamically changing some fields, so the flexform is using inline records that can be stored successfully in the database in their own table tx_jwfrontendusermanager_editorfields. The pid for the table entries is the same as for the content object they are attached to, and an additional field in the table holds the content object's id.
The backend works fine so far, I can create/edit/delete inline records for the content objects without any problem.
Unfortunately, I can't seem to figure out how to access the inline records in the ActionController in the frontend, and I can't find any documentation about how to do so. Could anyone point me into the right direction?
What I have tried so far:
First (primitive) approach: Accessing the flexform inline field like any other field from the form. This just returns the number "7". Obviously it's not meant to be used this way.
Second approach: I created a Model/Repository for the EditorFields table, and mapped the Model class to the table using Typoscript. The mapping itself seems to work fine. Unfortunately, I cannot select just the records that are connected to the current content object. A call to Repository->findAll() returns an empty array.
I debugged the SQL query for the findAll command and found out three problems:
The query filters by the tx_jwfrontendusermanager_editorfield.pid field, but using the wrong page id. The pid used is the one I selected in the plugin's 'Record Storage Page' field, not the one of the content object.
The query does not filter for the content object id, but would show all records for all content objects on the page.
The query filters by an additional
`tx_jwfrontendusermanager_editorfield`.`type` = "\Jw301\JwFrontendusermanager\Domain\Model\EditorField"
Which doesn't make any sense, as none of the records has the type field set to something like this. The type is used by the backend to distinguish between different kinds of records. That way, the query will never have any results.
So, how can this be changed in a way that the Repository finds the correct records? Is this even the right approach?
Third approach: As the Repository approach wasn't successful, I tried to get the records myself by creating a custom SQL query. This works in general, but I still have trouble filtering the right records for me.
I can get the current page id easily using
$GLOBALS['TSFE']->page['uid']
But there seems to be no way to get the content object id in the ActionController. I found many Internet sources that said I should use
$cObj = $this->configurationManager->getContentObject();
$cObj->data['uid']
from within the ActionController to access the current content object id, but for me that didn't work. I tried this in every ActionController in my project, yet the uid field was never there. The $cObj I get is of type ContentObjectRenderer, but the data array is always empty.
How can I access the content object uid from within an ActionController?
Thanks for any help or hints that lead me into the right direction.

HMVC internal/external requests and routes?

I think I understand the concept of HMVC after reading this question and answer https://softwareengineering.stackexchange.com/questions/220480/hmvc-and-database-connections; an extract from an answer is below:
Let's assume you want to have a view that enables a user to make a
comment to a blog post. You would have fields for name, e-mail, title
and comment, but you also want to have a field country displayed as a
dropdown. In the action that displays this view you would make a
database query that loads the countries and then populate that
dropdown. Which is ok, but it forces you to duplicate the query and
the view required to display the countries if you need it in another
part of your application. A better approach would be to create
separate controller for countries with an action that returns a view
with the dropdown and then render that action whenever you need to
show a list of countries.
What I cannot wrap my head around is that if I can internally request a controller/model/view which just displays a widget (e.g. a country select box), doesn't that mean that by accessing that url from a browser will also just show that view?
How is this managed in HMVC, are routes defined as internal/external only, so matching an internal route with an external request would show a 404 page?
Is this generally how it is done and is the HMVC description/definition above satisfiable with the general use case of it in most web applications?
Showing the output of a sub-request in the browser shouldn't be a problem, so I wouldn't bother, especially that those URLs are not known by the user and it's safe to output the widgets separately.
Despite the above, you could, as #deceze mentionned, not attach those controllers to any routes. If you have a "default" route (matching all requests), then you would have to disable it.

How to add a form field to modx 2.2.14 manager pages

I'm trying to add the editiedon field to the modx manager pages so my users can edit the value using this bit of documentation as a start point:
http://rtfm.modx.com/revolution/2.x/case-studies-and-tutorials/adding-custom-fields-to-manager-forms
Which does work, but:
how can I make that a date/time field?
how can I place it in the settings tab of the given resource?
Isn't input type="date" the answer to the first question? I'm not sure how you would do the second part, unless you managed to get the rendered content and splice it in there somehow (unless theres som hidden specified method).
Otherwise, you could always solve it with regular form customization. You'll want to create a TV of type Date, and give it a custom default data through a snippet, that just fetches the current resources editedon value. I guess you only need to update the resource/update form set. Under the template variables tab of the set, make sure your TV is connected and change the region value of it to "modx-resource-settings"
There are two different ways which have their own pros & cons.
At first you can use template variable with Date type. It gives you correct ExtJS component for dates and you'll see calendar in TV's tab.
If you'll choose this method you have to create a plugin which invokes on OnBeforeDocFormSave event. There you can redefine modResource editedon property from your TV and it will be saved in proper way. Also you may invoke another event(OnLoadWebDocument). There you can set modResource editedon property from you TV if you want to see correct data.
Pros:
fast calendar integration to the one of modResource's tab
you can use Form Customization for security reasons. It's rather easy and from the box.
Cons:
Additional TV which complicates modResource updating process a little bit
Another method is more complicated (you need skills in ExtJS).
Create plugin which invokes on OnDocFormPrerender event. You can add JS to the modResource page there. Your scripts should render new custom tab to the document where you can add your special field with calendar. So there is special ExtJS component in MODX for these purposes. And of course you need events from first method for loading and updating editedon value.
Also you can just render special field to the existing tab instead of creating new tab and rendering your custom field to it.
Pros:
you don't need TV anymore
it's flexible
Cons:
it's more complicated and takes time
P.S. You can view Xlexicon github repo. There you can find example of rendering new tab and manipulation with modResource properties.
Also you can check modAvatar extra for MODX. There is an example of manupulation with existing tab.

Reusable content blocks in CakePHP

I would like to ask about optimal approach to creation of reusable content blocks in CakePHP 1.3.
Under reusable content blocks I mean partial views used to build up the page. E.g. in an eshop application the minicart summary can be considered as reusable content block - it is displayed on each page header.
In CakePHP 1.3 there are two posibilities (and both have serious disadvantages):
Creation of element /app/plugins/myeshop/elements/minicart.ctp and use $this->element('minicart) to load this reusable content e.g. in header. The disadvantage is that this beaks business of Cart entity into many places. Minicart is only some representation of Cart entity whose views are treated by controller /app/plugins/myeshop/controllers/carts_controller.php. So why to put it out of controller and keep it in element? Elements are good to keep some general reusable contents e.g. header, footer, interactive_map, ... something which is not related to application business objects/entities.
Creation of method CartsController::minicart() with corresponding view and use $this->requestAction('/myeshop/carts/minicart') to load this reusable content e.g. in header. The advantage is that now all business and views of Cart entity is treated by CartsController. There are no side-logic and side-views hidden in elements.
The disadvantage of this approach is apparent - use of requestAction() costs a lot of time.
At this point I must say that I totally agree that requestAction() must be used very carefully. To use it to call some procedural/busines logic of controller is bad application design. Such kind of logic should not be placed in controller but in model. Still, IMHO, it is legitimate to call controller action to get a partial/reusable content (view) and keep the entity business on one place.
Does the CakePHP have some optimal solution for this?
I highly suggest going the route of elements/requestActions.
Here's a great article by CakePHP Master Mark Story: "How using requestAction increased performance on my site"
We've built many large, highly-traffic sites using CakePHP and use requestActions all over, and our sites load extremely fast.
If possible I would create it as an element. I assume your controller will calculate the contents of the mini cart and the view will display it?
If so its fine to use an element. You certainly dont want additional HTTP requests as you state.
However, the element should only display the content, it should perform any business logic. You need to incldue this in a Controller or Component and set the necessary elements for the view.
If you only need it on certain pages, you can create a new layout.ctp file that includes the mini cart and then use this layout on those pages.
If this is just about displaying the content of your cart on every page I recommend this solution: Write the cart into session, if the user is not logged in and logs in sync it with the database. If a user comes back and logs in restore the session from the saved cart.
In your AppController::beforeFilter() read and set the session data to the view or if it is just read, read it using the session helper in your minicart element. You won't have additional requestAction() calls by this or any additional db queries.
I've implemented my cart like this, you can take a look at it here. https://github.com/burzum/cart a working example app is also available https://github.com/burzum/CartSampleApp

CakePHP pagination sort (by multiple criteria) issue

I am currently trying to perform pagination using CakePHP's pagination helper.
I have a series of "Listing" rows that are returned and paginated as expected. When the user clicks on the column headings however, I'd like the sort() method to be forced to prioritise certain listings (i.e. priority listings, those with ['Listing']['priority_flag'] = 1) first. However, when the user clicks on the column header, the browser url is set to
www.mysite.com/listing/index/page:1/sort:description/direction:asc
Hence, it is only sorting by description (as the user clicked on the column header for 'description'), ignoring anything to do with priority_flag.
All help appreciated!
gaioshin
I did this by writing an override paginate() function on the appropriate model. For the parameters, look carefully at the structure of the url you have pasted (you can modify it to suit your own ends, but then you would need to deviate from the pagination helper).
It's not difficult to do, but will require some thought. Look at the core to see how it works.

Categories