I am either adding to my table or editing an existing row.
I've looked into firstOrCreate but I can't seem to get it to work, it always creates a new row.
return $this->firstOrCreate(array('id' => $input['id'], 'title' => $input['title'], 'sell' => $input['sell'], 'article' => $input['article'], 'thumb' => $input['thumb'], 'gallery' => $input['galleryData'], 'date' => $input['date'], 'published' => $input['published']));
Things like title change when the user edits them, is there a way to search the table based on the id, if it exists then update, if not, then create?
If the title changes, then using this method is illogical. The method you mention check for an item with ALL the given specifications.
What you should be doing instead:
// find the item, given the ID
$item = Item::firstOrNew(array('id' => $input['id']));
// add the fields from your input
$item->title = $input['title'];
$item->sell = $input['sell'];
$item->article = $input['article'];
$item->thumb = $input['thumb'];
$item->gallery = $input['galleryData'];
$item->date = $input['date'];
$item->published = $input['published'];
// Save the thing
$item->save();
Related
I created I new field in my TCA. I want to list all articles and select one, to set the article as top-article.
The articles have a UID and the database a column called istoparticle.
tx_vendor_domain_model_article is the table with all infos of the article.
I added a TCAcolumn.
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tt_content', array(
'tx_test_istoparticle' => array(
'exclude' => 1,
'onChange' => 'reload',
'label' => 'Top Article',
'l10n_mode' => 'exclude',
'config' => array(
'type' => 'select',
'itemsProcFunc' => \Vendor\MyArticles\Hooks\Backend\Preview\ArticleRenderer::class . '->getArticleTitle',
)
),
));
With a userfunction
public function getTopArticles($param){
$pid = $param['row']['pid'];
$articles = $this->getArticles($pid);
foreach ($articles as $article) {
$record = BackendUtility::getRecord('tx_vendor_domain_model_article', $article->getUid());
$title = $record['header'];
$param['items'][][] = $title;
}
}
BTW:$record has all infos that I need, UID, bodytext and so on. But I can only store the header in the array!?
Now I got all the titles listed in my selectbox in the backend.
What do I have to do, to save my toparticle If I select an article in the backend?
Is there a onChange method for the TCA? And how can I get the infos like the Uid if I select one?
Items in TCA configuration should have at least two elements - first one is the label and second is the value. There are more options, but I think not needed in your case. You can read about them here: https://docs.typo3.org/typo3cms/TCAReference/8.7/ColumnsConfig/Type/Select.html#items
It means your usefFunc should look like that:
public function getTopArticles(&$param){
$pid = $param['row']['pid'];
$teasers = $this->getArticles($pid);
foreach ($articles as $article) {
$record = BackendUtility::getRecord('tx_vendor_domain_model_article', $article->getUid());
$param['items'][] = [
$record['header'],
$record['uid'],
]
}
}
And yes, there is onChange functionality in TCA:
https://docs.typo3.org/typo3cms/TCAReference/8.7/Columns/Index.html?highlight=onchange#onchange
If you are using older TYPO3 than 8.6 you would need to look for requestUpdate according to: https://docs.typo3.org/typo3cms/extensions/core/8.7/Changelog/8.6/Deprecation-78899-TCACtrlFieldRequestUpdateDropped.html
if($this->input->post('tambah')){
$kode = $this->input->post('kode');
$jumlah = $this->input->post('jumlah');
$hjual = $this->input->post('hjual');
$nama = $this->input->post('nama');
$exp = $this->input->post('tglexp');
$hpp = $this->input->post('hpp');
$temp_stok = $this->input->post('temp_stok');
$diskon = $this->input->post('diskon');
$cart = array(
'id' => $kode,
'qty' => $jumlah,
'price' => $hjual,
'name' => $nama,
'options' => array('exp' => $exp, 'hpp' => $hpp,
'temp_stok' => $temp_stok , 'diskon'=>$diskon ));
$this->cart->insert($cart);
header('location:'.base_url().'penjualan/load_input_barang_eceran');
}
I cant seem to add any more items and the latest one I add replaces the existing one.
I had like this in another controller but strangely can insert and not overwriting
I've had this.
It was non alphanumerics in the product code which caused the whole cart to behave strangely.
Try just having aaa123 etc as codes to test this
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'))
I am semi-frustrated with this Yii CGridView problem and any help or guidance would be highly appreciated.
I have two related tables shops (shop_id primary) and contacts (shop_id foreign) such that a single shop may have multiple contacts. I'm using CGridview for pulling records and sorting and my relation function in shops model is something like:
'shopscontact' => array(self::HAS_MANY, 'Shopsmodel', 'shop_id');
On the shop grid, I need to display the shop row with any one of the available contacts. My attempt to filter, search the Grid has worked pretty fine, but I'm stuck in one very strange problem. The respective grid column does not display the value that is intended.
On CGridview file, I'm doing something like
array(
'name' => 'shopscontact.contact_firstname',
'header' => 'First Name',
'value' => '$data->shopscontact->contact_firstname'
),
to display the contact's first name. However, even under circumstances that searching/sorting are both working (I found out by checking the db associations), the grid column comes out empty! :( And when I do a var_dump
array(
'name' => 'shopscontact.contact_firstname',
'header' => 'First Name',
'value' => 'var_dump($data->shopscontact)'
),
The dump shows record values in _private attributes as follows:
private '_attributes' (CActiveRecord) =>
array
'contact_firstname' => string 'rec1' (length=4)
'contact_lastname' => string 'rec1 lsname' (length=11)
'contact_id' => string '1' (length=1)
< Edit: >
My criteria code in the model is as follows:
$criteria->with = array(
'owner',
'states',
'shopscontacts' => array(
'alias' => 'shopscontacts',
'select' => 'shopscontacts.contact_firstname,shopscontacts.contact_lastname',
'together' => true
)
);
< / Edit >
How do I access the values in their respective columns? Please help! :(
Hmm, I have not used the with() and together() methods much. What's interesting is how in the 'value' part of the column, $data->shopscontacts loads up the relation fresh, based on the relations() definition (and is not based on the criteria you declared).
A cleaner way to handle the array output might be like this:
'value' => 'array_shift($data->shopscontacts)->contact_lastname'
Perhaps a better way to do this, though, would be to set up a new (additional) relation, like this in your shops model:
public function relations()
{
return array(
'shopscontacts' => array(self::HAS_MANY, 'Shopsmodel', 'shop_id'), // original
'firstShopscontact' => array(self::HAS_ONE, 'Shopsmodel', 'shop_id'), // the new relation
);
}
Then, in your CGridView you can just set up a column like so:
'columns'=>array(
'firstShopscontact.contact_lastname',
),
Cheers
Since 'shopscontact' is the name of the has-many relation, $data->shopscontact should be returning an array with all the shops related... did you modify the relation in order to return only one record (if I didn't get you wrong, you only need to display one, right?)? If you did it, may I see your filtering code?
P.S. A hunch to get a fast but temporal solution: have you tried 'value' => '$data->shopscontact['contact_firstname']'?
I have created a module which gets the comments from the nodes which the user has specified as 'favourites'. So I'm not trying to output all comments from all nodes like the recent comments block do, but just the ones from nodes specified as 'favourites'.
The queries all work, I've tested this by printing values from the different objects. So I've got the whole comment object for each comment and the corresponding node object. I've been able to create lists of the cid, nid, comment text etc. and output these with
$block['content'] = theme('item_list', array('items' => $items));
but how would I go about rendering the comment objects I've got in my module in the same layout/design as I have on my node pages? The comments on my node pages are rendered with the comment.tpl.php file which I set up with my own layout/design and I'd like my module to render these comments the same way.
So this is my hook_block_view() implementation which I believe is the correct way for output from a module:
function jf_comment_feed_block_view($delta = '') {
switch($delta){
case 'jf_comment_feed':
$block['subject'] = t('Comment feed');
if(user_access('access content')){
// Get users favourite locations
$loc_result = jf_comment_feed_locations();
$fav_loc = array();
foreach ($loc_result as $loc) {
$fav_loc[] = array(
'data' => $loc->nid,
);
}
if (empty($fav_loc)) { //No content in the last week.
$block['content'] = t('No favourite locations added.
To see what goes on at your favourite locations add locations to
+My Locations and the posts from those locations will show here.');
} else {
//Use our custom function to retrieve data.
$result = jf_comment_feed_contents($fav_loc);
// ############################################
// Here I need to create my output... I think...
// Previously I rendered my results from the query
// by using this code (this prints the comment id):
// $items = array();
// foreach ($result as $comment){
// $items[] = array(
// 'data' => comment_load($comment->cid),
// );
// }
// ############################################
if (empty($items)) { //No content in the last week.
$block['content'] = t('No posts from last week.');
} else {
// This is the code used to render the
// comment id to the block:
// $block['content'] = theme('item_list', array('items' => $items));
}
}
}
}
return $block;
}
I've also tried with:
$block['content'] = theme('comment_view', $mycomment, $mynode);
$block['content'] = theme('comment', $mycomment, $mynode);
where $mycomment is the comment object and $mynode is the node object. But this breaks the page.
Surely there must be a line of code I'm missing here, but I've now spent two days googling this and had no luck... So thanks for any help with this.
EDIT
#Clive did trigger some ideas and I tried creating my own array based on what the arrays look like on the node page. I got the structure and names for the array with the Devel Themer info module.
This array outputs the comments creators user pic and the date, but I've added a custom field, field_jf_comment, to my comments and this isn't showing, although I can see the information in the array with Devel. I don't use the standard out-of-the-box comment field because I wanted a textfield and not a scalable textarea for the input. A design decision.
Now obviously this isn't ideal as I set most of the values manually. This works for my current project, but would be cool if the module was a bit more generic so other people could use it too. When I click on a individual comment on my node page with Devel Themer info I get an array which has elements, the user object and array items such as db_is_active, is_admin among other things. If I could somehow recreate this array and then set this array to $block['content'] I believe this would work.
Here's the implementation of the array:
foreach ($result as $comment) {
$items[] = array(
'#entity_type' => 'comment',
'#bundle' => 'comment_node_location',
'#theme' => 'comment__node_location',
'#comment' => comment_load($comment->cid, FALSE),
'#node' => node_load($comment->nid),
'#view_mode' => 'full',
'field_jf_comment' => array(
'#theme' => 'field',
'#title' => 'Title',
'#access' => TRUE,
'#label_display' => 'above',
'#view_mode' => 'full',
'#language' => 'und',
'#field_name' => 'field_jf_comment',
'#field_type' => 'text',
'#entity_type' => 'comment',
'#bundle' => 'comment_node_location',
'#items' => array(
'0' => array(
// This isn't working and gives an error saying:
// Notice: Undefined property: stdClass::$field_jf_comment in
// jf_comment_feed_block_view()
'value' => $comment->field_jf_comment['und']['0']['value'],
'format' => $comment->field_jf_comment['und']['0']['format'],
'safe_value' => $comment->field_jf_comment['und']['0']['safe_value']
)
)
)
);
}
And I get it rendered with:
$block['content'] = $items;
EDIT
#Clive was right. His code does the same as mine, but in way less code. And with some modifications I managed to get my custom field in there too:
$content = '';
foreach ($items as $item) {
$single_comment = comment_load($item['cid']);
$custom_field = field_attach_view('comment', $single_comment, 'field_jf_comment');
$to_render = array(
'#theme' => 'comment',
'#comment' => $single_comment,
'#node' => node_load($item['nid']),
'field_jf_comment' => $custom_field
);
$content .= render($to_render);
}
$block['content'] = $content;
Now the only thing I'm missing is the links for each comment. The only one I'm using is the Reply to comment. Anyone got any idea of how to get that to show too?
The theme() calls probably break because you're using Drupal 7 but trying to pass the parameters in a Drupal 6 style. If you have a look at the theme_comment() documentation you can see it takes a single $variables parameter which should be an array. Try this:
$content = '';
foreach ($items as $item) {
$to_render = array(
'#theme' => 'comment',
'#comment' => comment_load($item['cid'])
);
$content .= render($to_render);
}
$block['content'] = $content;
The new Drupal 7 theme() syntax takes an array for its second argument. This array will be extracted before calling the template file so each key will become a new php var.
For example array( 'comment' => $mycomment ) will get you a $commentvariable in your template.
Hope this can help.