I like to extend (own extension) eventnews (https://github.com/georgringer/eventnews) to use tt_address (https://github.com/TYPO3-extensions/tt_address) records for locations and organizers. The TCA is no problem, but XClass'ing does not work:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['GeorgRinger\\Eventnews\\Domain\\Model\\Location'] = array(
'className' => 'TYPO3\\TtAddress\\Domain\\Model\\Address',
);
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['GeorgRinger\\Eventnews\\Domain\\Model\\Organizer'] = array(
'className' => 'TYPO3\\TtAddress\\Domain\\Model\\Address',
);
Has it something to do with the PHPDoc annotations in Classes/Domain/Model/News.php ?
XClass'ing the News Model will help maybe, but i want to understand why it's not possible to use the code above
This is most likely because of the proxy class generator in the news extension. It changes the way classes are loaded in order to allow overriding and extending the news model.
https://docs.typo3.org/typo3cms/extensions/news/DeveloperManual/ExtendNews/ProxyClassGenerator/Index.html
Related
I need to add a custom column in the sales order adminhtml grid.
Since I get the data for that grid from an external REST API by asking for data to a specific increment_id, I can't use the tutorials which are using a magento database to join the needed tables.
Is there another way like:
function rendering_sales_order_row_before($rowdata) {
$columnContent = $restapi->callByIncrementId($rowdata['increment_id']);
$this->addColumn("Custom Column", $columnContent);
}
(This code should just illustrate my goal and I know that the solution will look completely different)
Is it possible to achieve that in magento in an elegant way?
EDIT: I'm using magento 1.9.2.1
Good question. I had a similiar problem. I solved it by using a custom renderer for my column.
First add your Sales Order Grid block XX_ModuleName_Block_Adminhtml_Order_Grid. Rewrite Mage_Adminhtml_Block_Sales_Order_Grid, extend it and add your column by overriding _prepareColumns() method.
$this->addColumn('my_column', array(
'header' => Mage::helper('sales')->__('My Column'),
'width' => '80px',
'index' => 'my_column',
'type' => 'text',
'order' => 'x',
));
Then add a custom renderer (XX_ModuleName_Block_Adminhtml_Sales_Order_Grid_Widget_Renderer_MyColumn) and extend Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract.
Override the render(Varien_Object $row) method. Here you can do your specific operation (do your api request, manipulate in whatever way you want) and return the string. To build your request you want to use the data by param $row.
That should work :) If you need more info, just comment.
I'm trying to use and extend the WP-API for Wordpress.
Now I might just be stupid but I really can't figure out where to start even though I've read the link above over and over. And I'm not talking code-wise but the very basics, where do I put the code? In a plugin? If so, what do I need to include to get it to work? Or is it enough to extend the class?
Sorry but I just find the info on the page to be way too little... Or have I totaly missed an perfectly structured example from top to bottom?
Here it is on GitHub.
Thanks for any help!
I don't know if the documentation was out of date or something but it's pretty simple to extend WP-API. You'll need to write a plugin first.
In the plugin, where you register the hooks like scripts and styles (functions.php, bootstrap.php) you add a new hook to register the routes.
add_filter( 'json_endpoints', array( $this, 'registerRoutes' ) );
public function registerRoutes($routes){
$editorService = $this->container["editorService"];
$routes['/newsletters'] = array(
array( array( $editorService, 'create'), \WP_JSON_Server::CREATABLE | \WP_JSON_Server::ACCEPT_JSON ),
);
$routes['/newsletters/(?P<id>\d+)'] = array(
array( array( $editorService, 'get'), \WP_JSON_Server::READABLE )
);
return $routes;
}
If you read the documentation you'll see that newsletter is the entity. In this example i inject a service and call it in the routes. Very probably you use a different approach and if you've difficulties in this point you'll have to figure out how to structure the plugin, which patterns apply, write or not your own framework, etc.
If thats the case check this skeleton, it's a great approach to MVC https://github.com/iandunn/WordPress-Plugin-Skeleton
If you want to call a function inside the same class you would do:
public function registerRoutes(){
$routes['/newsletters'] = array(
array( array( $this, 'createNewsletter'), \WP_JSON_Server::CREATABLE | \WP_JSON_Server::ACCEPT_JSON )
);
}
public function createNewsletter() {
$wpdb->prepare(); // etc etc
}
I have a few general questions about modifying Magento's admin section and would be grateful to have them answered. I'm new to Magento so please bear with me.
My goal is to add a new column with a product attribute (e.g. "Size") to the "Category Products" table within the Catalog -> Manage Cateories section (see screenshot below).
Having little Magento dev experience, I'm not quite sure where to start. I had a look in some of the Grid.php files under the adminhtml directory, and while I see a bunch of statements like addColumn(...), I'm not sure where I'd slot in my new attribute column.
Also, I assume that instead of modifying any core files directly, I'd copy them to the same path under the local folder and edit or somehow extend them there? Do I have to edit any config files or do anything else for the change to be reflected? Am I - by doing this - in effect creating my own module?
I also read that I should disable "Compilation" before I make any changes. Why is this? Is there anything else to consider?
Again I am very grateful for any help and appreciate that my questions must seem basic. Any supplementary resources you could point me towards would be appreciated. Thanks.
Indeed you should start by understanding what file to edit and how to edit it. In this case you want to modify app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php but, like you said, you should not modify the file in its current location. There are two ways to modify the file in the "correct" way.
(harder but more extensible) Create a new Module in local and tell Magento in the etc/config.xml that you are overwriting that Block (which is just a php class) with a different block in this new Module and have the new class extend the core Block class. Then you just need to overwrite one function (_prepareColumns).
(easier) Copy the file from app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php to app/code/local/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php and modify the function you want (_prepareColumns)
If you are new to Magento, I recommend going with the second option because its easier. Magento will always load the file from local before it loads from core so the file in core will no longer be used and your version in local will be used. To find out more, read this article from Alan Storm
Now in order to add the column you want, do something similar to the SKU field
$this->addColumn('size', array(
'header' => Mage::helper('catalog')->__('Size'),
'index' => 'size'
));
in the order you want it (between Product Name and SKU). I am assuming that your Products have a field called size that you can retreive with $product->getSize()
Max solution was pretty spot on but missing some important steps, I'll elaborate on his original method
Create a new local override of the Product Tab by copying app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php to app/code/local/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php
There are 2 functions involved in modifying the grid view. _prepareCollection and _prepareColumns
_prepareColumns by adding a call to the addColumn function just like:
$this->addColumn('size', array(
'header' => Mage::helper('catalog')->__('Size'),
'width' => '80',
'index' => 'size'
));
_prepareCollection, by default the product collection loaded in the grid only has a few attributes(name,sku,price) what you need to do add our now attribute by ->addAttributeToSelect('size') now if you are only working with a textfield attribute then this is the extend of the modifications you have to do however if your attribute is for example a dropdown you will need to do further changes to the prepare collection:
(optional) dropdown attributes only store the value of the option that was select so we need to provide an options array to the addColumns call so Magento can display the values correctly, we can do that in the following maner:
on your local copy of Products, add the following to the _prepareColumns functions
$attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', 'colour');
$options = array();
foreach( $attribute->getSource()->getAllOptions(true, true) as $option ) {
$options[$option['value']] = $option['label'];
}
$this->addColumn('colour', array(
'header' => Mage::helper('catalog')->__('Colour'),
'width' => '80',
'index' => 'colour',
'type' => 'options',
'options' => $options
));
While those are some very thorough question and I'm sure you will learn a lot, there is a ready-made solution; Enhanced Admin Product Grid has the ability to add arbitrary attributes as columns.
Nobody seems to have a problem with that so either I'm doing it wrong or no one ever tried:
I have a model "Infocenter" which has many "InfocenterArticle"s. To fetch data including the related stuff I attached the Containable behavior to both.
This worked well until now that I attached a "HasImageAttachment" behavior implemented by myself. The problem is that on contained models the callbacks of my behavior don't get called.
My Models:
class Infocenter extends AppModel {
...
$actsAs = array('HasImageAttachment', 'Containable');
$hasMany = array('InfocenterArticle');
...
}
class InfocenterArticle extends AppModel {
...
$actsAs = array('Containable');
$belongsTo = array('Infocenter');
...
}
In my Controller I call:
$conditions = array('InfocenterArticle.id' => $id);
if ($this->notLoggedIn()) $conditions['InfocenterArticle.freigabe'] = 1;
$article = $this->InfocenterArticle->find('first', array(
'contain' => array(
'Infocenter',
'Infocenter.InfocenterArticle' => array(
'fields' => array('id', 'title', 'freigabe'),
'order' => array(
'InfocenterArticle.order_index' => 'desc',
'InfocenterArticle.created' => 'desc',
'InfocenterArticle.title' => 'asc'
),
'conditions' => array(
'InfocenterArticle.infocenter_id' => 'Infocenter.id'
),
),
),
'conditions' => $conditions,
));
And I can see that my HasImageAttachmentBehavior::setup() method is called but the HasImageAttachmentBehavior::afterFind() (as well as beforeFind()) are not. Infocenter::afterFind() is called though, which enabled me to do some dirty hacking, good enough for now, but I hate it.
What am I doing wrong?
Edit: Additional info in reply to RichardAtHome's comment.
1) My behavior works on models that don't have Containable attached.
2) I made sure that afterFind() doesn't get called by putting a simple die(); in the first line. The script doesn't die().
3) Signature should be okay, I double checked.
4) I'm using CakePHP 1.3.
Thanks for your help.
Currently I don't believe CakePHP core supports Behavior across Contained models.
It may be due to possible recursion, if you have weird contain array the behaviors may be called incorrectly.
There is a long post on the CakePHP Lighthouse project regarding calling behaviors over associated models, with a few recommendations for workarounds.
http://cakephp.lighthouseapp.com/projects/42648/tickets/95-afterfind-and-beforefind-callbacks-not-working-on-associated-models-was-translate-behavior-should-translate-associated-model-data
I just wrote an extensive entry on how to deal with this type of scenario.
It is for CakePHP 2.x and PHP 5.4+.
Containable behavior alternative function
Apparently this was a deliberate point of design(??!?). So you have to upgrade all the way to 3.0 if you want associated models to behave fully like models. Sigh.
Here is an extensive discussion: https://github.com/cakephp/cakephp/issues/1730
and the most straightforward cookbook fix: https://schneimi.wordpress.com/2009/09/06/behavior-afterfind-on-model-associations/
I'm new to CakePHP and I'm stuck in reading a Model using other fields. I did a cake bake command to generate a simple users CRUD. I can view the user using the url CakePHP provided.
/users/view/1
I can view the user using id = 1. What if I want to view a user by name instead of id?
/users/view/username
By default the view function reads the User model by id.
$this->User->read(null, $id)
Thank you.
you can use find function or findBy<Field>() in your case findByUsername()
check this
I've never used cakePHP myself but I'm going to suggest that you will likely have to implement a new user model method, something like getUserByUsername($username)
This would then in turn interface with your DAL that would get the details of that user based on the username and return a user object that can be used however you wish...
It seems that CakePHP is focusing to deprecate some functions, such as findAll(). Perhaps soon the magic methods such as findBy<field>() will have the same fate.
I can recommend what martswite is suggesting, you should create your custom function:
function findUser($username=''){
return $this->find('first', array(
'conditions' => array(
'User.username' => $username
)
));
}
Perhaps you have a status field, maybe the profile isn't public, you can add a condition:
function findUser($username=''){
return $this->find('first', array(
'conditions' => array(
'User.username' => $username,
'User.status' => 1
)
));
}
I think that's more modular than findBy<Field>.