How to save values of an array to a table? - cakephp

I have these codes on my add view
$status = array('0' => 'Resolved', '1' => 'Assigned/Unresolved', '2' => 'Suspended', '3' => 'Closed', '4' => 'Bypassed');
echo $this->Form->input('status', array('options' => $status));
and instead of saving the value (e.g. Resolved) to the table, it saves the index of the array. Any ideas?

You should do something like this:
$status = array('resolved' => 'Resolved', 'assigned' => 'Assigned/Unresolved'...);
It saves the index of the array. But this is not a good practice, instead try using enums. Check this out:
/**
* Get Enum Values
* Snippet v0.1.3
* http://cakeforge.org/snippet/detail.php?type=snippet&id=112
*
* Gets the enum values for MySQL 4 and 5 to use in selectTag()
*/
function getEnumValues($columnName=null, $respectDefault=false)
{
if ($columnName==null) { return array(); } //no field specified
//Get the name of the table
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$tableName = $db->fullTableName($this, false);
//Get the values for the specified column (database and version specific, needs testing)
$result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");
//figure out where in the result our Types are (this varies between mysql versions)
$types = null;
if ( isset( $result[0]['COLUMNS']['Type'] ) ) { $types = $result[0]['COLUMNS']['Type']; $default = $result[0]['COLUMNS']['Default']; } //MySQL 5
elseif ( isset( $result[0][0]['Type'] ) ) { $types = $result[0][0]['Type']; $default = $result[0][0]['Default']; } //MySQL 4
else { return array(); } //types return not accounted for
//Get the values
$values = explode("','", preg_replace("/(enum)\('(.+?)'\)/","\\2", $types) );
if($respectDefault){
$assoc_values = array("$default"=>Inflector::humanize($default));
foreach ( $values as $value ) {
if($value==$default){ continue; }
$assoc_values[$value] = Inflector::humanize($value);
}
}
else{
$assoc_values = array();
foreach ( $values as $value ) {
$assoc_values[$value] = Inflector::humanize($value);
}
}
return $assoc_values;
} //end getEnumValues
Paste that method in your AppModel.
Create the column in your table as an enum with the posible values, and use that method to get them.

Can you not define the index as the value you want?
$status = array('Resolved' => 'Resolved', 'Assigned/Unresolved' => 'Assigned/Unresolved', etc etc );
echo $this->Form->input('status', array('options' => $status));

Related

Laravel - How to insert multi-dimensional Array in DB

I have the array as below;
I'd like to insert each name keys into tableName and get the inserted id.
For the steps, each of them will be inserted into another table tableSteps including the last inserted id of the name.
Like as below screenshot.
In my controller,
Here's what I've done so far.
$instructionsArrays = $request->instructions;
$max = count($instructionsArrays);
for ($x = 1; $x <= $max; $x++) {
foreach($instructionsArrays as $instructionsArray){
Instruction::updateOrCreate(
['recipe_id' => session()->get('recipeArr.id'), 'sequence' => $x],
['name' => $instructionsArray['name']],
);
}
}
I was able to save sequence numbers but for names it saves only the last name key.
And... I'm really lost..
You can achieve what you want from 2 for loops
foreach($request->instructions as $key => $val){
$id = Instruction::insertGetId(
['recipe_id' => session()->get('recipeArr.id'), 'sequence' => $key + 1],
['name' => $val['name']],
);
$data = []; //bulk insertion
$created_at = now();
foreach($val["steps"] as $step){
array_push($data, ["header_id" => $id, "name" => $step, "sequence" => $key+1, "created_at" => $created_at]); //why insert sequence when you can obtain it from the relationship?
}
Steps::insert($data);
}
With the help of the answer of #Kneegrows, I came up with the code below and it is now working. Thank you.
foreach ($request->instructions as $key => $val) {
$instruction = Instruction::updateOrCreate(
['recipe_id' => session()->get('recipeArr.id'), 'sequence' => $key + 1],
['instructions_name' => $val['name']],
);
$id = $instruction->id;
$data = []; //bulk insertion
$i = 1;
foreach ($val["steps"] as $step) {
if(!is_null($step)){
array_push($data, ["instruction_id" => $id, "steps_name" => $step, "sequence" => $i]);
$i++;
}
}
Steps::insert($data);
}

Add custom column in-between people/users admin page table drupal 7

I have created a custom column to display last user changed time, but I need this field to be insert before OPERATIONS column. Below is my code which append my custom field at the end.
function meme_user_update_form_user_admin_account_alter(&$form, &$form_state, $form_id) {
$changed_column = array('changed' => array(
'data' => 'LAST CHANGED',
'field' => 'u.changed'
));
$form['accounts']['#header'] = $form['accounts']['#header'] + $changed_column;
foreach ($form['accounts']['#options'] as $key => $row) {
$user_object = user_load($key);
$user_language = ($user_object->language) ? $user_object->language : LANGUAGE_NONE;
$form['accounts']['#options'][$key]['changed'] = $user_object->field_user_changed[$user_language][0]['value'];
}
}
Found an answer, I think this might help someone.
function meme_user_update_form_user_admin_account_alter(&$form, &$form_state, $form_id) {
$changed_column = array(
'data' => 'LAST CHANGED',
'field' => 'u.changed'
);
$operation_column = array_pop($form['accounts']['#header']);
$form['accounts']['#header']['changed'] = $changed_column;
$form['accounts']['#header']['operations'] = $operation_column;
foreach ($form['accounts']['#options'] as $key => $row) {
$user_object = user_load($key);
$user_language = ($user_object->language) ? $user_object->language : LANGUAGE_NONE;
$operation_column = array_pop($form['accounts']['#options'][$key]);
$form['accounts']['#options'][$key]['changed'] = $user_object->field_user_changed[$user_language][0]['value'];
$form['accounts']['#options'][$key]['operations']['data'] = $operation_column;
}
}

split custom archives function into columns wordpress

WordPress, you infuriate me sometimes!
What I've been trying to do for the past few hours is trying to have a way that I can display the Archive's down the sidebar with a custom date format (without changing the global options in settings), a terribly convoluted task that should really be as simple as using the_date();. I just want to make January 2013 for example, Jan 13 instead while also having one year down one column and the other in the other.
I've managed to do the custom date formatting alright by adapting this code: http://www.wpbeginner.com/wp-themes/how-to-customize-the-display-of-wordpress-archives-in-your-sidebar/ to this:
function sidebar_archive_list($arclistno = "24") {
global $wpdb;
$limit = 0;
$year_prev = null;
$months = $wpdb->get_results("SELECT DISTINCT MONTH( post_date ) AS month , YEAR( post_date ) AS year, COUNT( id ) as post_count FROM $wpdb->posts WHERE post_status = 'publish' and post_date <= now( ) and post_type = 'post' GROUP BY month , year ORDER BY post_date DESC");
foreach($months as $month) :
$year_current = $month->year;
if ($year_current != $year_prev){
if ($year_prev != null){ }
}
?>
<?php echo date("M y", mktime(0,0,0,$month->month,1,$month->year)); ?>
<?php
$year_prev = $year_current;
if(++$limit >= $arclistno) { break; }
endforeach;
}
That's worked no problems.
The trouble has now come when I've tried to split the returned content from this function into the two separate column divs. I believe I need to make the function into an array like you can get from wp_get_archives('echo=0'); (and some extra code) but my PHP skills aren't superb and I can't quite figure out how to go about recreating the same kind of thing. I think it should look something like:
array(3) { [0]=> string(86) "January 2013"
[1]=> string(90) "September 2012"
[2]=> string(82) "March 2012"
}
When var_dumped. Also it's worth bearing in mind for whatever reason the anchor links also surround the dates, but echo, rather than print out.
The code I'm using for the content split is:
<?php
$links = print(sidebar_archive_list());
$archive_n = count($links);
for ($i=0;$i<$archive_n;$i++):
if ($i<$archive_n/2):
$archive_left = $archive_left.'<li>'.$links[$i].'</li>';
elseif ($i>=$archive_n/2):
$archive_right = $archive_right.'<li>'.$links[$i].'</li>';
endif;
endfor;
?>
<div class="group">
<ul class="sb_double_column_list alignleft">
<?php echo $archive_left;?>
</ul>
<ul class="sb_double_column_list alignright">
<?php echo $archive_right;?>
</ul>
</div>
Any help or advice would be wholeheartedly appreciated. I'm in a real rut with this!
Okay after messing around a bit I managed to modify wp_get_archives into my own custom function which allowed me to pass it through the column creating code in a similar manner to how I did when trying to use wp_get_archives on its own.
The code is as follows.
function sidebar_archive_list($args = '') {
global $wpdb, $wp_locale;
$defaults = array(
'limit' => '24',
'format' => 'html', 'before' => '',
'after' => '', 'show_post_count' => false,
'echo' => 0, 'order' => 'DESC',
);
$r = wp_parse_args( $args, $defaults );
extract( $r, EXTR_SKIP );
if ( '' != $limit ) {
$limit = absint($limit);
$limit = ' LIMIT '.$limit;
}
$order = strtoupper( $order );
if ( $order !== 'ASC' )
$order = 'DESC';
//filters
$where = apply_filters( 'getarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
$join = apply_filters( 'getarchives_join', '', $r );
$output = '';
$query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date $order $limit";
$key = md5($query);
$cache = wp_cache_get( 'wp_get_archives' , 'general');
if ( !isset( $cache[ $key ] ) ) {
$arcresults = $wpdb->get_results($query);
$cache[ $key ] = $arcresults;
wp_cache_set( 'wp_get_archives', $cache, 'general' );
} else {
$arcresults = $cache[ $key ];
}
if ( $arcresults ) {
$afterafter = $after;
foreach ( (array) $arcresults as $arcresult ) {
$url = get_month_link( $arcresult->year, $arcresult->month );
$year = date("y", strtotime($arcresult->year));
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month_abbrev($wp_locale->get_month($arcresult->month)), $year);
if ( $show_post_count )
$after = ' ('.$arcresult->posts.')' . $afterafter;
$output .= get_archives_link($url, $text, $format, $before, $after);
}
}
if ( $echo ) // If "echo" has been defined as having a value (e.g: 1) then echo $output, if it has no value (0) then return the value.
echo $output;
else
return $output;
}
Just drop it into the functions.php and then use the sidebar_archive_list(). Please note that the function only supports the monthly display and I've altered the defaults slightly from wp_get_archives. So it will return the array rather than echoing it and the default limit is 24 (12 months down one column and vice versa).

Why this code add only a single data from an array into a menu table

I am able to obtain the $data array from a form and I can generate data for each item... But during the binding and storing with jTable object it saves only the latest item why... I am using native JTableMenu class to bind and save by using my own class which is extended by native one. Early trials I used database object to save items with sql syntax but some columns of table remains empty lft and rgt to fill them I used table object but it gives this issue.
The whole code is following:
function addcumulative($data){
$db = JFactory::getDBO();
$component = & JComponentHelper::getComponent('com_dratransport');
$menus = array();
$query = array();
$countries = DraTransportHelperArrays::countries();
$cities = DraTransportHelperArrays::cities();
$title = array();
$alias = array();
$path = array();
$link = array();
if(empty($data['parent_id']) && $data['parent_id'] == 0){
$data['parent_id'] = 1;
}else{
$parent_id = explode('.',$data['parent_id']);
$data['parent_id'] = $parent_id[1];
}
if(!empty($data['locationQuery'])){ //actually this part will be used
$loc = ($data['locationQuery'] == 'countries') ? $countries : $cities['Turkey'] ;
foreach($loc as $k => $c){
$query[0] = $data['general'];
foreach($data as $key => $dat){
if(!empty($dat) && strpos($key,'Query') !== false){
$v = explode('Q',$key);
if($v[0] !== 'location'){
$query[] = '&'.$v[0].'='.$dat;
}else{
$query[] = '&'.$dat.'='.$k;
}
}
}
$title[] = $data['viewQuery'].'-'.$k;
$alias[] = $data['viewQuery'].'-'.$k;
$path[] = $data['viewQuery'].'-'.$k;
$link[] = implode('',$query);
$query = array();
}
}else{
$query[0] = $data['general'];
foreach($data as $key => $dat){
if(!empty($dat) && strpos($key,'Query') !== false){
$v = explode('Q',$key);
$query[] = '&'.$v[0].'='.$dat;
}
}
$link[] = implode('',$query);
}
foreach($link as $n => $l){
$menus[] = array(
'menutype' => $data['menutype'],
'title' => $title[$n],
'alias' => $alias[$n],
'path' => $path[$n],
'link' => $link[$n],
'type' => 'component',
'published' => 1,
'parent_id' => $data['parent_id'],
'level' => 1,
'component_id' => $component->id,
'access' => $data['access'],
'params' => $data['params'],
'language' => '*'
);
}
$count = $data['count'] == 0 ? count($loc) : $data['count'];
foreach($menus as $menu){
// Bind the data.
$table = $this->getTable();
$table->bind($menu);
$table->store();
}
}
Yes you are totally right. Let say $countries=array('England','France','Germany'); then I wrote my code in model to generate links in #__menu table. So I write
foreach($countries as $country){
$link='index.php&option=com_mycomponent&view=members&type=1&countries='.$country;
$table->bind();
$table->save();
}
I am generating links like this, view and the type values in query comes from the form submitted to make parmaters same for all menus except countries;
and I assign all parametes to manu item and menu items to an array as array item...
to save database the table comes with nested.
$menus->$each menu as $menus array item->menu item parameters
while the table is first created in above code code just adds the last menu item but if I take it insede the foreach it adds all of them but parent_id and level parameters assigned to 0 bye the native code altought I set them as 1

CakePHP - how to apply translate behavior to existing database?

I have and existing application in CakePHP with a database.
The task is to apply translate behavior to its models. The problem is that i18n.php script just creates _i18n table but doesn't copy existing data to this table.
Don't you know any script that could do that?
Thanks for any help.
I extended the answers from Aziz and MarcoB and created a even more generic CakeShell out of it.
In the method _execute() simply set something like:
$this->_regenerateI18n('BlogPosts', array('title'), 'deu');
And all entries for the Model BlogPosts for the column title in the language deu will be create in the i18n table.
This is CakePHP 2.4 compatible!
<?php
class SetuptranslationsShell extends AppShell {
public function main() {
$selection = $this->in('Start to create translated entries?', array('y', 'n', 'q'), 'y');
if (strtolower($selection) === 'y') {
$this->out('Creating entries in i18n table...');
$this->_execute();
}
}
function _execute() {
$this->_regenerateI18n('BlogPosts', array('title'), 'deu');
$this->_regenerateI18n('BlogTags', array('name'), 'deu');
}
/**
* See http://stackoverflow.com/q/2024407/22470
*
*/
function _regenerateI18n($Model, $fields = array(), $targetLocale) {
$this->out('Create entries for "'.$Model.'":');
if (!isset($this->$Model)) {
$this->{$Model} = ClassRegistry::init($Model);
}
$this->{$Model}->Behaviors->disable('Translate');
$out = $this->{$Model}->find('all', array(
'recursive' => -1,
'order' => $this->{$Model}->primaryKey,
'fields' => array_merge(array($this->{$Model}->primaryKey), $fields))
);
$this->I18nModel = ClassRegistry::init('I18nModel');
$t = 0;
foreach ($out as $v) {
foreach ($fields as $field) {
$data = array(
'locale' => $targetLocale,
'model' => $this->{$Model}->name,
'foreign_key' => $v[$Model][$this->{$Model}->primaryKey],
'field' => $field,
'content' => $v[$Model][$field],
);
$check_data = $data;
unset($check_data['content']);
if (!$this->I18nModel->find('first', array('conditions' => $check_data))) {
if ($this->I18nModel->create($data) AND $this->I18nModel->save($data)) {
echo '.';
$t++;
}
}
}
}
$this->out($t." entries written");
}
}
As far as I know, there's no way to do this. Moreover, because of the way the i18n table is configured to work, I think there's a better solution. A while back, I wrote a patch for the TranslateBehavior that will keep you from having to copy existing data into the i18n table (that felt insanely redundant to me and was a huge barrier to implementing i18n). If no record for that model exists in the i18n table, it will simply read the model record itself as a fallback.
Unfortunately, the Cake team appears to have moved everything to new systems, so I can no longer find either the ticket or the patch that I submitted. My patched copy of the TranslateBehavior is in my Codaset repository at http://codaset.com/robwilkerson/scratchpad/source/master/blob/cakephp/behaviors/translatable.php.
As you might expect, all of the usual warnings apply. The patched file was developed for 1.2.x and works for my needs, by YMMV.
try to use it
function regenerate()
{
$this->Article->Behaviors->disable('Translate');
$out = $this->Article->find('all', array('recursive'=>-1, 'order'=>'id'));
$t = $b = 0;
foreach($out as $v){
$title['locale'] = 'aze';
$title['model'] = 'Article';
$title['foreign_key'] = $v['Article']['id'];
$title['field'] = 'title';
$title['content'] = $v['Article']['title'];
if($this->Article->I18n->create($title) && $this->Article->I18n->save($title)){
$t++;
}
$body['locale'] = 'aze';
$body['model'] = 'Article';
$body['foreign_key'] = $v['Article']['id'];
$body['field'] = 'body';
$body['content'] = $v['Article']['body'];
if($this->Article->I18n->create($body) && $this->Article->I18n->save($body)){
$b++;
}
}
}
Thanks Aziz. I modified your code to use it within the cakeshell
(CakePHP 2.3.8)
function execute() {
$this->out('CORE_PATH: '. CORE_PATH. "\n");
$this->out('CAKEPHP_SHELL: '. CAKEPHP_SHELL. "\n");
$this->out('Migrate BlogPosts');
$this->regenerateI18n('BlogPost', 'title', 'BlogPostI18n');
}
/**
* #param string $Model
* #param string $Field
* #param string $ModelI18n
*/
function regenerateI18n($Model = null, $Field = null, $ModelI18n = null)
{
if(!isset($this->$Model))
$this->$Model = ClassRegistry::init($Model);
if(!isset($this->$ModelI18n))
$this->$ModelI18n = ClassRegistry::init($ModelI18n);
$this->$Model->Behaviors->disable('Translate');
$out = $this->$Model->find('all', array('recursive'=>-1, 'order'=>'id'));
$t = 0;
foreach($out as $v){
$data = array(
'locale' => 'deu',
'model' => $this->$Model->name,
'foreign_key' => $v[$Model]['id'],
'field' => $Field,
'content' => $v[$Model][$Field],
);
if($this->$ModelI18n->create($data) && $this->$ModelI18n->save($data)){
echo '.';
$t++;
}
}
$this->out($t." Entries written");
}

Resources