cakephp 2.1 contain second level different field name - cakephp-2.1

I can't get the values from a second level contain using different field name as link.
Asistencia model:
var $belongsTo = array('Employee');
Horario model:
var $belongsTo = array('Employee');
Employee model:
var $hasMany = array(
'Horario' => array(
'foreignKey' => 'employee_id',
'dependent' => true
),
'Asistencia' => array(
'foreignKey' => 'employee_id',
'dependent' => true
)
);
I'll explain using these values on my example record:
Asistencia: employee_id = 3701
Employee : id = 3701
In my find() from Asistencia, I get to contain Employee by switching Employee primaryKey just fine:
$this->Asistencia->Employee->primaryKey = 'id';
$this->paginate = array(
'contain' => array(
'Employee' => array(
'foreignKey' => 'employee_id',
//'fields' => array('id', h('emp_ape_pat'), h('emp_ape_mat'), h('name')),
'Horario' => array(
'foreignKey' => 'employee_id',
//'fields' => array('id' )
))
),
'conditions' => $conditions,
'order' => 'Asistencia.employee_id');
However, my Horario record is linked to Employees via another field: emp_appserial
Employee : emp_appserial = 373
Horario : employee_id = 373
How can my Employee array contain Horario array? (they do share the value just mentioned).
Currently, the Horario contain is using the value on Asistencia.employee_id and Employee.id (3701). (checked the sql_dump and is trying to get the Horario via
"WHERE `Horario`.`employee_id` = (3701)"
but for the Employee to contain Horario, it should use the value on Employee.emp_appserial and Horario.employee_id (373).
This is what i get (empty array at bottom)
array(
(int) 0 => array(
'Asistencia' => array(
'id' => '5',
'name' => null,
'employee_id' => '3701',
'as_date' => '2012-11-19',
),
'Employee' => array(
'id' => '3701',
'emp_appserial' => '373',
'emp_appstatus' => '8',
'AgentFullName' => '3701 PEREZ LOMELI JORGE LORENZO',
'FullNameNoId' => 'PEREZ LOMELI JORGE LORENZO',
'Horario' => array()
)))
Please notice:
'employee_id' => '3701', (Asistencia)
and
'emp_appserial' => '373', (Employee)
my Horario has 'employee_id' = 373.
How could I make the switch so the relation Employee<->Horario is based on emp_appserial?
Thank you in advance for any help.

Firstly you may be getting problems because you're using Spanish words for your Model names and I suspect you're also using them for Controllers.
This is a very bad practice since CakePHP's idea is:
Convention over configuration.
This is achieved through the Inflector class which "takes a string and can manipulate it to handle word variations such as pluralizations or camelizing and is normally accessed statically". But this works ONLY WITH English words. What this means for you is that you may be missing the data because Cake is not able to build the DB queries right, since you're using Spanish words. By doing so you're making the use of CakePHP's flexible persistence layer obsolete - you will have to make all the configurations by hand. Also most likely pagination will NOT WORK. Other parts of the framework may also not work properly:
HtmlHelper, FormHelper, Components, etc. ...
These problems will expand if you try to use more complex Model associations such as HABTM or "hasMany through the Join Model".
So I do not know why exactly you aren't seeing the Horario record, but what I just explained most likely is your problem.
What you're trying to do is against the core principles of CakePHP and you'd save yourself a lot of problems if you refactor a bit and use English words. Your other option is NOT TO use Cake.

Related

CakePHP paginator isn't sorting

In CakePHP, I would like to sort my index list (created by the paginator component) on sequence ASC, but it won't work. If I see the query setup in the CakePHP docs (http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html#query-setup), my paginator settings should look like this:
public function index()
{
$this->Paginator->settings = array(
'Attraction' => array(
'conditions' => array(
'Attraction.deleted' => null
),
'order' => array(
'Attraction.sequence ASC',
'Attraction.id ASC'
),
'limit' => 15
)
);
$attractions = $this->Paginator->paginate('Attraction');
$this->set('attractions', $attractions);
}
But every time I load my index file, the list is sorted on ID and ignores the "order" setting. Can anybody tell me if there's anything wrong with my "order" item in my paginator settings? ;)
Thx!
try
'order' => array(
'Attraction.sequence' => 'asc',
'Attraction.id' => 'asc'
),
edit:
The sorting direction must be in the array value, while the field name should be the index. The examles I found in the documentations are always showing that
I don't think you should have that Attraction index in your options array - in other words, I think your options array should look like this:
$this->Paginator->settings = array(
'conditions' => array(
'Attraction.deleted' => null
),
'order' => array(
'Attraction.sequence ASC',
'Attraction.id ASC'
),
'limit' => 15
);

Magento Admin formfield multiselect selected

I´m currently developing a custom module for magento thats going to list employees.
I have figured out almost everything. The only thing I got left is how the selected values is going to be highlighted.
The problem I´m having is for the backend.
I got 2 tabs per employee, one for employee data and one tab for magento categories.
1 employee can have 1 or more categories.
The database table that the categories are stored in are a non-eav table.
So my question is
What in a multiselect determines which values are selected? As it is now, only one value is selected.
I think you can do this by simply passing in an array of the id's to be selected into the 'value' attribute of the field being added for the multiselect in the _prepareForm() method. Something like the following.
$fieldset->addField('category_id', 'multiselect', array(
'name' => 'categories[]',
'label' => Mage::helper('cms')->__('Store View'),
'title' => Mage::helper('cms')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('mymodule/mymodel')->getMymodelValuesForForm(),
'value' => array(1,7,10),
));
The id of the form element (e.g. category_id) must not be an attribute in your model, otherwise when the form values get set with $form->setValues() later on, the attribute value will be overwritten.
I normally store multiple selections as a text column separated by commas much like most magento modules handles stores which requires a slightly different approach as shown below.
In the form block for the tab with the multiselect, you firstly define the element to be displayed like so in the _prepareForm() method. You then get the values from the model and set put them into the form data.
protected function _prepareForm()
{
...
$fieldset->addField('store_id', 'multiselect', array(
'name' => 'stores[]',
'label' => Mage::helper('cms')->__('Store View'),
'title' => Mage::helper('cms')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true),
));
...
if ( Mage::getSingleton('adminhtml/session')->getMymodelData() )
{
$data = Mage::getSingleton('adminhtml/session')->getMymodelData();
} elseif ( Mage::registry('mymodel_data') ) {
$data = Mage::registry('mymodel_data')->getData();
}
$data['store_id'] = isset($data['stores']) ? explode(',', $data['stores']) : array();
$form->setValues($data);
}
I normally store the selected stores (categories as in your case) in the main model as a text column and comma separated values of ids, hence the explode.
In the controller for for the edit action, I put the model being edited into the mage registry so we can load it and it's values in the step above.
Mage::register('mymodel_data', $model);
Thanks for answering.
This is how my field looks like:
$fieldset->addField('npn_CatID', 'multiselect', array(
'label' => Mage::helper('employeelist')->__('Kategori'),
'class' => 'required-entry',
'required' => true,
'name' => 'npn_CatID',
'values' => $data,
'value' => array(3,5)
));
npn_CatID is the value in my db where the category id is saved.
I have tried to change the name and field ID but cant get it working.
When its the field id is like above ONE value is selected and its the last one inserted for the chosen employee
My data array looks likes
array(array('value' => '1', 'label' => 'USB'), array('value' => '2', 'label' => 'Memories'))

How to get the custom values and image in Magento in Topmenu?

I'm using magento 1.7.0.2. I have add the custom value in database. But how to retrive the custom value and image in Topmanu. I have tried in below mentioned code in the palce of 'my_attribute' to replace my attribute, but i din't get the result.
Model: Mage_Catalog_Model_Observer
Method: _addCategoriesToMenu()
$categoryData = array(
'name' => $category->getName(),
'id' => $nodeId,
//'url' => Mage::helper('catalog/category')->getCategoryUrl($category),
'is_active' => $this->_isActiveMenuCategory($category),
'my_attribute' => $category->getData('my_attribute') // Add our data in...
);
When i print the array i'll get this,
Array ( [name] => Matelas [id] => category-node-31 [is_active] => 1 [my_attribute] => )
Can any one guide me, Thanks in advance...
I am guessing you mean you have added a new custom attribute to the Category entity?
Becuase you are dealing with a Node_collection the full category object won't be loaded, try loading the full object to get what you're after:
$cat = Mage::getModel('catalog/category')->load($category->getId());
$categoryData = array(
name' => $category->getName(),
'id' => $nodeId,
//'url' => Mage::helper('catalog/category')->getCategoryUrl($category),
'is_active' => $this->_isActiveMenuCategory($category),
'my_attribute' => $cat->getData('my_attribute') // Add our data in...
);

How to add categories in Joomla 2.5

Does anyone know how to properly insert new content categories to the DB programatically?
For each post in the categories table, there is also a post saved in the assets table with lft and rgt set.
Is there any native Joomla class I can use for this instead of plain SQL?
Please Please Only use the native classes, which categories will handle for you seamlessly. As soon as you add categories the whole thing will be handled automagically. Just look at any core component to see how.
It is not easy to update the assets table using sql, it is all very specifically managed and part of a complex series of foreign keyed tables.
Extend JTable or JTableContent to handle this.
Here is some code I just whipped together that just uses the JTableCategory class, so it can be used simply on the front or admin side of Joomla
$table = JTable::getInstance('category');
$data = array();
// name the category
$data['title'] = $title;
// set the parent category for the new category
$data['parent_id'] = $parent_id;
// set what extension the category is for
$data['extension'] = $extension;
// Set the category to be published by default
$data['published'] = 1;
// setLocation uses the parent_id and updates the nesting columns correctly
$table->setLocation($data['parent_id'], 'last-child');
// push our data into the table object
$table->bind($data);
// some data checks including setting the alias based on the name
if ($table->check()) {
// and store it!
$table->store();
// Success
} else {
// Error
}
Naturally you would want to get the data pieces set correctly, but these are the core ones to set.
Here is a function I've created just for this purpose, after some digging & experimenting.
It uses core classes, so it needs an access to them (for me it's basically a part of Joomla component).
Mind, it's for Joomla 3, for Joomla 2.5 and before, you need to change JModelLegacy to JModel.
function createCategory( $name, $parent_id, $note )
{
JTable::addIncludePath( JPATH_ADMINISTRATOR . '/components/com_categories/tables' );
$cat_model = JModelLegacy::getInstance( 'Category', 'CategoriesModel' );
$data = array (
'id' => 0,
'parent_id' => $parent_id,
'extension' => 'com_content',
'title' => $name,
'alias' => '',
'note' => $note,
'description' => '',
'published' => '1',
'access' => '1',
'metadesc' => '',
'metakey' => '',
'created_user_id' => '0',
'language' => '*',
'rules' => array(
'core.create' => array(),
'core.delete' => array(),
'core.edit' => array(),
'core.edit.state' => array(),
'core.edit.own' => array(),
),
'params' => array(
'category_layout' => '',
'image' => '',
),
'metadata' => array(
'author' => '',
'robots' => '',
),
);
if( !$cat_model->save( $data ) )
{
return NULL;
}
$categories = JCategories::getInstance( 'Content' );
$subcategory = $categories->get( $cat_model->getState( "category.id" ) );
return $subcategory;
}
You can perhaps use the save() in category.php file.
File location: root\administrator\components\com_categories\models\category.php
It saves the form data supplied to it!
The JOS_assets table is to store the ACL for each asset that is created.
If you do not update this table while programatically creating the category, the default ACL will apply. And when later you open and save the category in the administrative panel, the ACL will be updated as it should have been by core Joomla!.
You can create an SQL query very easily though and update the asset table as well. Its easy to understand once you open the table's content in phpmyadmin.

Cakephp 2.0: How to provide ORDER BY instructions for data retrieved recursively through find()?

I am trying to set up a model with a lot of hasMany/hasOne relationships, and I'd like for the owned models to be presented, alphabetically, in a drop-down menu within the "Add" view. I am not sure how to provide ORER BY instructions to models that are retrieved recursively. This is what I've tried:
$services = $this->service->find('all', array(
'order'=>array(
'Service.start_year DESC',
'Servicecat.title DESC'
),
'recursive'=>0
) );
But of course this yields no change. I have a suspicion it's not very complicated, I just can't find a solution in the cookbook/api. Ideas?
You could do this a few ways. I prefer to use the containable behavior for models and then it allows you to finely control how the models are retrieved. You could also setup order in your model's relationship definition.
Model Way
$hasMany = array(
'Servicecat' => array(
'order' => array(
'Servicecat.title DESC'
)
)
);
Containable Way
In your models, set them to use the containable behavior:
public $actsAs = array('Containable');
Then, when you find from your controller, you can explicitly state which models are linked. You can use multidimensional arrays to determine the depth of recursion.
$services = $this->Service->find(
'all',
array(
'contains' => array(
'Servicecat' => array(
'order' => array('Servicecat.title' => 'DESC')
)
),
'order' => array('Services.start_year' => 'DESC')
)
);

Resources