A simple innerJoin Doctrine Query - doctrine

I tried to generate a simple SQL select:
SELECT c.com_id, c.pro_id, c.com_nombre
FROM bd_fn.fn_comuna c
inner join bd_fn.fn_provincia p
on (c.pro_id = p.pro_id)
where p.pro_nombre = 'namepro';
But the DQL throw this error:
Doctrine_Table_Exception' with message 'Unknown relation alias fn_provincia.
The doctrine version is 1.XX, the persistence was create by Visual Paradigm.
The DQL is this:
$q = Doctrine_Query::create()
->select('c.com_id')
->from('fn_comuna c')
->innerJoin('c.fn_provincia p')
->where('p.pro_nombre=?',$namepro);
the class fn_comuna.php
<?php
/**
* "Visual Paradigm: DO NOT MODIFY THIS FILE!"
*
* This is an automatic generated file. It will be regenerated every time
* you generate persistence class.
*
* Modifying its content may cause the program not work, or your work may lost.
*/
class Fn_comuna extends Doctrine_Record {
public function setTableDefinition() {
$this->setTableName('bd_fn.fn_comuna');
$this->hasColumn('com_id', 'integer', 4, array(
'type' => 'integer',
'length' => 4,
'unsigned' => false,
'notnull' => true,
'primary' => true,
'autoincrement' => false,
)
);
$this->hasColumn('pro_id', 'integer', 4, array(
'type' => 'integer',
'length' => 4,
'unsigned' => false,
'notnull' => true,
)
);
$this->hasColumn('com_nombre', 'string', 100, array(
'type' => 'string',
'length' => 100,
'fixed' => false,
'notnull' => true,
)
);
}
public function setUp() {
parent::setUp();
$this->hasOne('Fn_provincia as pro', array(
'local' => 'pro_id',
'foreign' => 'pro_id'
)
);
$this->hasMany('Fn_institucion as fn_institucion', array(
'local' => 'com_id',
'foreign' => 'com_id'
)
);
$this->hasMany('Fn_replegal as fn_replegal', array(
'local' => 'com_id',
'foreign' => 'com_id'
)
);
}
}
?>

As you can see from your model class, the relation between fn_comuna & fn_provincia is called pro.
$this->hasOne('Fn_provincia as pro', array(
'local' => 'pro_id',
'foreign' => 'pro_id'
)
);
So you have to use this name when you deal with join:
$q = Doctrine_Query::create()
->select('c.com_id')
->from('fn_comuna c')
->innerJoin('c.pro p')
->where('p.pro_nombre=?', $namepro);

Change:
p.pro_id = (SELECT p2.pro_id FROM etc..
To:
p.pro_id IN(SELECT p2.pro_id FROM etc..
Not sure why you need the subquery in the first place, why not just loose it and replace it with:
where pro_nombre = 'namepro'

Related

ZF2 simple form validation

I tried to validate a simple form in zend framework 2 for days now.
I checked the documentation and a lot of posts considering this topic but I found no solution!
I have a very simple form:
class AlimentForm extends Form
{
public function __construct($name = null)
{
parent::__construct('aliment');
$this->add(array(
'required'=>true,
'name' => 'year',
'type' => 'Text',
'options' => array(
'label' => 'Jahr',
),
));
$this->add(array(
'required'=>true,
'name' => 'number',
'type' => 'Text',
'options' => array(
'label' => 'Number',
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
I created a custom InputFilter:
namespace Application\Form;
use Zend\InputFilter\InputFilter;
class AlimentInputFilter extends InputFilter {
public function init()
{
$this->add([
'name' => AlimentForm::year,
'required' => true,
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1900,
'max' => 3000,
),
),
),
]);
}
}
and finally in my controller I try to validate the form
public function alimentAction(){
$form = new AlimentForm();
$form->setInputFilter(new AlimentInputFilter());
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$year = $form->get('year')->getValue();
$number = $form->get('number')->getValue();
return array('result' => array(
"msg" => "In the Year ".$year." you get ".$number." Points"
));
}
}
return array('form' => $form);
}
It can't be that difficult, but from all those different ways to validate a form I found in the net, I'm a bit confused...
What am I missing?
Greetings and thanks in advance
U.H.
Ok, I solved the problem.
I created a Model for the aliment Form that has a year and a number attribute
and I defined an input filter within that model:
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class Aliment implements InputFilterAwareInterface
{
public $year;
public $number;
public function exchangeArray($data){
$this->year = (!empty($data['year']))?$data['year']:null;
$this->number = (!empty($data['number']))?$data['number']:null;
}
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$inputFilter->add(array(
'name' => 'year',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1900,
'max' => 3000
)
)
),
));
$inputFilter->add(array(
'name' => 'number',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1,
'max' => 10
)
)
),
));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
In the action method of the controller I was able to set the InputFilter of the model to the form and voila! It worked!
public function alimentAction(){
$form = new AlimentForm();
$request = $this->getRequest();
if ($request->isPost()) {
$aliment = new \Application\Model\Aliment;
$form->setInputFilter($aliment->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$aliment->exchangeArray($form->getData());
$year = $form->get('year')->getValue();
return array(
'result' => array(
//your result
)
);
}
}
return array('form' => $form);
}
The form is correctly validated now and returns the corresponding error messages.
I hope, it help somebody whos got similar problems with validating!

Can't save multiselect attribute on Magento

I created a custom multiselect product attribute through installer. It works and I can save the product if I only select one option from the multiselect values. But if I select 2 values, the product still can be saved but came back up with 1 selected value again. In short, I can't save the attribute with 2 selected values.
$installer = $this;
$installer->startSetup();
$installer->addAttribute('catalog_product', 'attr_id',array(
'label' => 'Frontend Name',
'type' => 'int',
'input' => 'multiselect',
'backend' => 'eav/entity_attribute_backend_array',
'frontend' => '',
'source' => '',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'searchable' => false,
'filterable' => false,
'comparable' => false,
'option' => array (
'value' => array(
'0' => array('First Option'),
'1' => array('Second Option'),
'2' => array('Third Option'),
)
),
'visible_on_front' => false,
'visible_in_advanced_search' => false,
'unique' => false
));
$installer->endSetup();
The problem comes from the type of your attribute.
'type'=> 'int',
The values from multiselect attributes are saved concatenated by comma 1,4,6. For this you need the attribute to be varchar or text. I recommend varchar if you are not going to have hundreds of options for the attribute.
The way is configured now, when it's saved, the value 1,4,6 is converted to int and it ends up being 1.
Modify you option array from
'option' => array (
'value' => array(
'0' => array('First Option'),
'1' => array('Second Option'),
'2' => array('Third Option'),
)
),
to
'option' => array (
'value' => array(
'first_option' => array('First Option'),
'second_option' => array('Second Option'),
'third_option' => array('Third Option'),
)
),
Multiselect will accept associated array.
I have found the solution myself .
open app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php
on save action after this
$category->setAttributeSetId($category->getDefaultAttributeSetId());
Please change language is your attribute name . you can change attribute name accordingly
$ga = "";
if($data['general']['language']){
foreach($data['general']['language'] as $a){
$ga .= $a.",";
}
$category->setLanguage(substr_replace($ga, "", -1));
}
Please replace language to your attribute name and it works...**
I am using SOAP API for entering products in magento shops. here is the full code
In the case of multiselect custom attribute.
$arrProductTime = explode(',', '136,139');
$result = $client->catalogProductCreate($session, 'simple', $attributeSet->set_id, 'product_sku1234', array(
'categories' => array(36),
'websites' => array(1),
'name' => 'my_pdt1008',
'description' => 'my_pdt1',
'short_description' => 'my_pdt1000',
'weight' => '11',
'status' => '1',
'url_key' => 'product-url-key1',
'url_path' => 'product-url-path1',
'visibility' => '4',
'price' => '100',
'tax_class_id' => 1,
'meta_title' => 'Product meta title1',
'meta_keyword' => 'Product meta keyword1',
'meta_description' => 'Product meta description1',
'stock_data' => array('qty'=>'100','is_in_stock'=>1,'manage_stock'=>1),
'additional_attributes' => array('multi_data' => array(array('key' => 'product_time', 'value' => $arrProductTime)))
));
I have faced a problem in my custom category attribute. It does not save the multiselect value in data base and does not show multiselect values on the category backend admin.
<?php
require_once("app/Mage.php");
Mage::app('default');
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$entityTypeId = $installer->getEntityTypeId('catalog_category');
$attributeSetId = $installer->getDefaultAttributeSetId($entityTypeId);
$attributeGroupId = $installer->getDefaultAttributeGroupId($entityTypeId, $attributeSetId);
$installer->addAttribute('catalog_category', 'cutomcity', array(
'label' => 'Test Select',
'type' => 'varchar',
'input' => 'multiselect',
'visible' => true,
'user_defined' => true,
'required' => false,
'position' => 80,
'visible_on_front' => false,
'group' => 'General Information',
'input' => 'multiselect',
'backend_model'=>'eav/entity_attribute_backend_array'
'source' => 'GA_Multiattribute_Helper_Testsource'
// eav/entity_attribute_source_table Even if i use this untill it does not show selected value on the Multiselect
));
?>
This is my helper file code
<?php
class GA_Multiattribute_Helper_Multiattributesource extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
protected $_optionsDefault = array();
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
$collection = Mage::getModel('customer/customer')->getCollection()->addAttributeToSelect('*');;
$customers = array();
foreach($collection as $cust)
{
$fname = $cust->getFirstname();
$lname = $cust->getLastname();
$id = $cust->getId();
$customers[] = array('value'=>"$id$fname", 'label'=>"$fname $lname");
}
return $customers;
}
} ?>

PHPUnit mocks - assert method called

i'm new to phpunit and have read the documentation on mock objects but it isn't very clear.
I am trying to write a simple test that asserts a method within a class is called. With the following code, i am testing that when the Client::exchangeArray is called, a call is made to Client::getInputFilter.
class Client implements InputFilterAwareInterface
{
public function getInputFilter() {
if(!$this->_inputFilter){
$inputFactory = new InputFactory();
$inputFilter = new InputFilter();
$inputFilter->add($inputFactory->createInput(array(
'name' => 'id',
'required' => true,
'filters' => array(
array(
'name' => 'Int'
)
)
)));
$inputFilter->add($inputFactory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array(
'name' => 'StripTags'
),
array(
'name' => 'StringTrim'
),
array(
'name' => 'StripNewLines'
),
array(
'name' => 'Alpha'
)
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 2,
'max' => 100
)
)
)
)));
$inputFilter->add($inputFactory->createInput(array(
'name' => 'surname',
'required' => true,
'filters' => array(
array(
'name' => 'StripTags'
),
array(
'name' => 'StringTrim'
)
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 2,
'max' => 100
)
)
)
)));
$inputFilter->add($inputFactory->createInput(array(
'name' => 'email',
'required' => false,
'filters' => array(
array(
'name' => 'StripTags'
),
array(
'name' => 'StringTrim'
)
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 2,
'max' => 150
)
),
array(
'name' => 'EmailAddress'
)
)
)));
$this->_inputFilter = $inputFilter;
}
return $this->_inputFilter;
}
public function exchangeArray($data){
$inputFilter = $this->getInputFilter();
$inputFilter->setData($data);
if(!$inputFilter->isValid()){
throw new \Exception('Invalid client data');
}
$cleanValues = $inputFilter->getValues();
$this->_id = (isset($cleanValues['id']) ? $cleanValues['id'] : null);
$this->_name = (isset($cleanValues['name']) ? $cleanValues['name'] : null);
$this->_surname = (isset($cleanValues['surname']) ? $cleanValues['surname'] : null);
$this->_email = (isset($cleanValues['email']) ? $cleanValues['email'] : null);
}
}
Here is my test case:
public function testExchangeArrayCallsInputFilter(){
$data = array('id' => 54,
'name' => 'john',
'surname' => 'doe',
'email' => 'john.doe#domain.com'
);
$mock = $this->getMock('Client', array('exchangeArray'));
$mock->expects($this->once())
->method('getInputFilter');
$mock->exchangeArray($data);
}
...and i'm getting the following error:
Expectation failed for method name is equal to
when invoked 1 time(s). Method was expected to be called 1 times,
actually called 0 times.
Where am i going wrong?
It all depends on what you want test and what you want mock. Basing on the name of your test I assume that you want test exchangeArray method.
The getMock method takes as second argument names of methods that you want mock. It means that they will never be called.
So, if you want to test exchangeArray method and mock getInputFilter you should pass "getInputFilter" in second argument, like below:
$mock = $this->getMock('Client', array('getInputFilter'));
$mock->expects($this->once())
->method('getInputFilter');
$mock->exchangeArray($data);
But be careful. You didn't tell your mock to return anything, so it will return null value. That means that you'll get a fatal error on the second line of exchangeArray method (trying to call a method on a non-object). You should prepare some faked filter object to deal with that, eg:
// $preparedFilterObject = ...
$mock = $this->getMock('Client', array('getInputFilter'));
$mock->expects($this->once())
->method('getInputFilter')
->will($this->returnValue($preparedFilterObject);
$mock->exchangeArray($data);
And if you want to invoke the "real" getInputFilter method - then you just can't mock this method.

Magento 1.6.2.0 sales orders custom attribute is not working

I already have spent all day on this and I think I can't get this working because the possibility to add custom EAV attributes to orders was removed.
At least, I've noticed that sales_order_entity is missing.
Well, what I try to do is to add a custom field to sales orders. I thought it would work the same way as for category products, but looks like nope.
My overall point in doing all this is because I want to track who is adding products to catalog and want to relate certain order with certain user (not customer).
public function getDefaultEntities()
{
return array(
'catalog_product' => array(
'entity_model' => 'catalog/product',
'attribute_model' => 'catalog/resource_eav_attribute',
'table' => 'catalog/product',
'additional_attribute_table' => 'catalog/eav_attribute',
'entity_attribute_collection' => 'catalog/product_attribute_collection',
'attributes' => array(
'seller_id' => array(
'group' => 'MyCustom',
'label' => 'Seller ID',
'type' => 'int',
'input' => 'text',
'default' => '0',
'class' => '',
'backend' => '',
'frontend' => '',
'source' => '',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
'visible' => false,
'required' => true,
'user_defined' => true,
'searchable' => true,
'filterable' => true,
'comparable' => false,
'visible_on_front' => false,
'visible_in_advanced_search' => false,
'unique' => false,
),
),
),
'order' => array(
'entity_model' => 'sales/order',
'table' => 'sales/order',
'increment_model' => 'eav/entity_increment_numeric',
'attributes' => array(
'seller_id' => array(
'group' => 'MyCustom',
'label' => 'Seller ID',
'type' => 'int',
'input' => 'text',
'default' => '0',
'class' => '',
'backend' => '',
'frontend' => '',
'source' => '',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
'visible' => false,
'required' => true,
'user_defined' => true,
'searchable' => true,
'filterable' => true,
'comparable' => false,
'visible_on_front' => false,
'visible_in_advanced_search' => false,
'unique' => false,
),
),
),
);
}
It works for products, but not for orders. I have required entries in eav_attribute table.
I don't know if I'm doing something wrong or this is just impossible to do?
I also thought about solving this different way by creating additional table to track relations between user - order|product. This would require more work tough.
I know this is an old post but I came across it when I was looking for answers to the same problem, so thought I would share my solution.
Lets take adding an attribute to a sales order as an example.
Firstly, Magento no longer users EAV entities for Sales, if you look at core/Mage/Sales/etc/config.xml
<sales>
<class>Mage_Sales_Model</class>
<resourceModel>sales_resource</resourceModel>
</sales>
resouceModel no longer points at sales_entity(EAV), it now points at sales_resource(flat). If you look at the children of the sales_resource node, you will find the order node:
<order>
<table>sales_flat_order</table>
</order>
This means that a Mage_Sales_Model_Order has a resource model of Mage_Sales_Model_Resource_Order which has a table of sales_flat_order.
The magento developers have provided the class Mage_Sales_Model_Resource_Setup which allows you to add attributes to this new "flat" structure in pretty much the same way you would have added attributes to the EAV structure. If you take a look inside Mage_Sales_Model_Resource_Setup you will see the following function:
/**
* Add entity attribute. Overwrited for flat entities support
*
* #param int|string $entityTypeId
* #param string $code
* #param array $attr
* #return Mage_Sales_Model_Resource_Setup
*/
public function addAttribute($entityTypeId, $code, array $attr)
{
if (isset($this->_flatEntityTables[$entityTypeId]) &&
$this->_flatTableExist($this->_flatEntityTables[$entityTypeId]))
{
$this->_addFlatAttribute($this->_flatEntityTables[$entityTypeId], $code, $attr);
$this->_addGridAttribute($this->_flatEntityTables[$entityTypeId], $code, $attr, $entityTypeId);
} else {
parent::addAttribute($entityTypeId, $code, $attr);
}
return $this;
}
With this information you should now see that it is simply a case of getting an instance of Mage_Sales_Model_Resource_Setup and calling its public addAttribute method with valid parameters.
Code snippet of adding a franchise_id attribute to a sales order:
$salesResourceSetupModel = Mage::getModel('sales/resource_setup', 'core_setup');
$data=array(
'type'=>'int',
'input'=>'text',
'label'=>'Franchise',
'global'=> 1,
'is_required'=>'0',
'is_comparable'=>'0',
'is_searchable'=>'0',
'is_unique'=>'0',
'is_configurable'=>'0',
'user_defined'=>'1',
//whether it should be including in the sales order grid
'grid'=>1
);
//first param should relate to a key of the protected $_flatEntityTables array
$salesResourceSetupModel->addAttribute('order', 'franchise_id', $data);
For Versions > 1.4.1.0 you will have to create a column in the sales_flat_order table. You can take a look in this post
is magento sales eav

Add new tab page in admin category - Magento

I'm looking for to add a new tabpage under category in magento admin, which loads the category grid. Idea is to associate multiple categories to one category and on the front end, when you click on that particular category, it should show products from all the associated categories.
Is there any better solution then create a new tabpage with categories grid?
EDITTED
Right... I have realised I could add new fields in category with install script. Now in my setup script I am doing something like this:
public function getDefaultEntities()
{
return array(
'catalog_category' => array(
'entity_model' => 'catalog/category',
'attribute_model' => 'catalog/resource_eav_attribute',
'table' => 'catalog/category',
'additional_attribute_table' => 'catalog/eav_attribute',
'entity_attribute_collection' => 'catalog/category_attribute_collection',
'attributes' => array(
'men_categories' => array(
'type' => 'int',
'backend' => '',
'frontend' => '',
'label' => 'Men Categories',
'input' => 'select',
'class' => '',
'source' => 'pushon_config/config_source',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'default' => 0,
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'unique' => false,
'group' => 'Associated Categories',
),
),
),
);
}
In my source.php in doing this:
class PushOn_Config_Model_Config_Source extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
protected $_options = array();
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
$option = Mage::getResourceModel('catalog/category_collection');
foreach($option as $id){
$this->_options[] = array('value'=> $id->getData('entity_id'), 'label' => $id->getData('name'));
}
return $this->_options;
}
}
Now when I run this it shows me error message:
a:5:{i:0;s:163:"Error in file: "C:\wamp\www\vhosts\staging.domainname.com\httpdocs\app\code\local\PushOn\Config\sql\pushon_config_setup\mysql4-install-0.1.0.php" - Wrong entity ID.";i:1;s:1148:"#0 C:\wamp\www\vhosts\staging.domainname.com\httpdocs\app\code\core\Mage\Core\Model\Resource\Setup.php(390): Mage::exception('Mage_Core', 'Error in file: ...')
I am just trying to load all the categories. Any idea why this is happening?

Resources