I need to programmatically set up a node reference field.
My module successfully creates a and associates a pair of 'CCK' fields to my nodes. One of these fields is a node_reference field. My code is a follows:
$field_ref_name = 'field_custom_reference';
$field = field_info_field($field_ref_name);
if (empty($field)) {
$field = array(
"field_name"=>$field_ref_name,
"label"=>"Custom Reference",
"type"=>"node_reference",
"cardinality"=>"1",
'locked' => TRUE,
);
field_create_field($field);
}
$instance = array(
"field_name"=>$field_ref_name,
"label"=>"Sequence Reference",
"type"=>"node_reference",
"widget"=>array(
"type"=>"node_reference_autocomplete"
),
"description" => "text describing purpose of this field",
);
$instance["entity_type"] = "node";
$instance["bundle"] = $type;
if( !in_array($type, $field['bundles']['node']) )
field_create_instance($instance);
Now, the code works but when I edit a node inputting a valid value into the node reference field and attempt to save, I get the following error:
...: this post can't be referenced.
I realized the reason for the error is because the node reference field settings does not have any selected nodes as "Content types that can be referenced".
How can I adjust my code to set referenceable content types?
The reference-able types is a field setting. So it should be put under a "settings" array in the field definition. Something like -
$field = array(
"field_name"=>$field_ref_name,
"label"=>"Custom Reference",
"type"=>"node_reference",
"cardinality"=>"1",
'locked' => TRUE,
'settings' => array(
'referenceable_types' => array('article'),
),
);
Related
I have a table in my database. I want to use the data of that table and create form of that data. I created a module and made a form.php page. Wrote select query in function but how to make form from that data?
I believe you want to create listing page of the table data. Here is how you can create a tabular listing with pagination and column sorting.
Suppose you have a table named "students" with the below fields.
id, name, email
1. Create a controller in your module in the below path.
modules/your_module/Src/Controller/StudentsController.php
<?php
namespace Drupal\your_module\Controller;
use Drupal\Core\Controller\ControllerBase;
class StudentsController extends ControllerBase {
public function __construct() {
}
public function list() {
$header = array(
array('data' => t('ID'), 'field' => 'st.id'),
array('data' => t('Name'), 'field' => 'st.name'),
array('data' => t('Email'), 'field' => 'st.email'),
);
$query = db_select('students', 'st')
->fields('st', array('id', 'name', 'email'))
->extend('Drupal\Core\Database\Query\TableSortExtender')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->orderByHeader($header);
$data = $query->execute();
$rows = array();
foreach ($data as $row) {
$rows[] = array('data' => (array) $row);
}
$build['table_pager'][] = array(
'#type' => 'table',
'#header' => $header,
'#rows' => $rows,
);
$build['table_pager'][] = array(
'#type' => 'pager',
);
return $build;
}
}
So your controller action is ready, now you have to add routing in order to create path to this listing page.
2. Create routing.yml file inside your module folder as the file name mentioned below, and the code below.
modules/your_module/your_module.routing.yml
students.list:
path: 'admin/config/students/list'
defaults:
_controller: 'Drupal\your_module\Controller\StudentsController::list'
_title: 'Students List'
requirements:
_permission: 'access students list'
3. To create permissions, you can create the followin ing file in your module.
modules/your_module/your_module.permissions.yml
access students list:
title: 'Access students list page'
Clear CMS cache
Go to People => Permissions, Enable the permission for relevant user roles.
Then, browse your page "admin/config/students/list"
I could see a lots of question on adding woocommerce product attribute. But doing so, I could see those added attributes in this screen
wp-admin/edit.php?post_type=product&page=product_attributes
My question is how can we add the attributes via PHP code to so that it appears in this above specified woocommerce attribute screen ? My intention is to make these attributes visible under 'Layered Navs' widget to filter out.
Following code will create the attribute programmatically which will be visible on the product_attributes page in the backend.
global $wpdb;
$insert = $wpdb->insert(
$wpdb->prefix . 'woocommerce_attribute_taxonomies',
array(
'attribute_label' => 'name',
'attribute_name' => 'slug',
'attribute_type' => 'type',
'attribute_orderby' => 'order_by',
'attribute_public' => 1
),
array( '%s', '%s', '%s', '%s', '%d' )
);
if ( is_wp_error( $insert ) ) {
throw new WC_API_Exception( 'woocommerce_api_cannot_create_product_attribute', $insert->get_error_message(), 400 );
}
// Clear transients
delete_transient( 'wc_attribute_taxonomies' );
Change name, slug etc with the relevant values.
I understood how to create a menu from the child elements of a specific page (e.g. id=5) like this:
$pages = \Ip\Menu\Helper::getChildItems($pageId = 5);
echo ipSlot('menu', $pages);
Works so far. Just the formatting is due to the lack of Bootstrap classes enhancable.
But how can I add custom classes to the ul of this menu?
Normally I do this like this:
$options = array(
'items' => 'menu2',
'attributes' => array('class' => 'nav nav-stacked')
);
echo ipSlot('menu', $options);
But how can I combine these two methods?
All in formation is in documentation - https://www.impresspages.org/docs/navigation ("ADD CUSTOM MENU ITEMS").
items variable supports menu objects, too.
In your case the final solution should look like this:
$pages = \Ip\Menu\Helper::getChildItems($pageId = 5);
$options = array(
'items' => $pages,
'attributes' => array('class' => 'nav nav-stacked')
);
echo ipSlot('menu', $options);
A site I'm working on has a complicated "mega menu" type navigation. I would like content editors to be able to group menu items by column in the markup. Normally if I want 6 columns I would register 6 menus and name them columns 1-6, however these are dynamic sub-menus that need to be a child of another navigation item inside another menu.
What I'd really like to do is create a new type of nav-menu item (Currently Pages, Links, Categories, as well as my other custom post types and custom taxonomies) where that item would be just for columns. (The fact that I'm using it for columns isn't important here. This could just as easily be dividers, or something else. I just need a new nav-menu item type that I can create special markup with when I'm building the menus.)
Is there a way to create a new nav-menu item type without having to create a custom post type or custom taxonomy that is used only for this purpose?
What I ended up doing for this, was adding a new post type that was hidden everywhere on the site except the nav menus. I then added just a single entry of that post type type, and hid some of the fields.
<?php
function navMenuColumns_init() {
register_post_type('menu_column',
array(
'labels' => array(
'name' => __('Menu Columns'),
'singular_name' => __('Menu Column')
),
'supports' => array('title'),
// Doesn't need to be listed most places as it's not a valid content item on it's own
'public' => false, // Base setting. More specific settings below
'exclude_from_search' => false,
'publicly_queryable' => false,
'show_ui' => false,
'show_in_menu' => false,
'show_in_nav_menus' => true, // The only thing this is used for
'show_in_admin_bar' => false,
'has_archive' => false,
)
);
$_version = (float)get_option('navMenuColumns_version', 0.0);
if ($_version < 1.0) {
navMenuColumns_install10();
}
add_action('admin_footer', 'navMenuColumns_adminFooter');
}
function navMenuColumns_install10() {
$navMenuPost = wp_insert_post(array(
'post_type' => 'menu_column',
'post_title' => 'Column',
'post_status' => 'publish'
), true);
if (!is_wp_error($navMenuPost)) {
update_option('navMenuColumns_version', 1.0);
}
}
function navMenuColumns_adminFooter() {
?><script>
jQuery(document).ready(function($) {
// Hides most of the fields when editing a Menu Column item.
$('#menu-to-edit').on('click', 'a.item-edit', function() {
var $li = $(this).parents('li.menu-item');
if ($li.find('.item-type').text() == 'Menu Column') {
$li.find('p.description').hide();
$li.find('p.link-to-original').hide();
$li.find('p.field-move').show();
}
});
});
</script><?php
}
add_action('init', 'navMenuColumns_init');
?>
This allows the user to add this as a normal menu item. This won't play well with functions that build the menu markup for you, but if you traverse the menu item and build the markup for you, you can target this post type with custom markup.
I have a problem with searching in Yii. I have two models: Teams and Workers. On website there is a page called 'Team Workers' where I want to display CGridView widget with searching that displays Workers from the team (team id is passed as a _GET parameter).
I did this in TeamsController:
public function actionWorkers($id)
{
$model = Teams::model()->findByPk($id);
$workers = Workers::model();
$workers->unsetAttributes();
if(isset($_GET['Workers']))
{
$_GET['Workers']['idTeam'] = $id;
$workers->attributes = $_GET['Workers'];
}
else {
$workers->attributes = array('idTeam' => $id);
}
$teamWorkers = $workers;
$this->render('workers', array(
'model' => $model,
'teamWorkers' => $teamWorkers
));
}
And in the view file:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'team-workers-grid',
'dataProvider'=>$teamWorkers->search(),
'filter' => $teamWorkers,
'columns'=>array(
'name',
'surname',
array(
'id' => 'idWorker',
'class' => 'CCheckBoxColumn',
'checked' => '$data->confirmer',
'selectableRows' => '2',
// 'headerTemplate' => '{item}'
)
),
)); ?>
I got the error:
CDbCommand nie zdołał wykonać instrukcji SQL: SQLSTATE[23000]: Integrity constraint
violation: 1052 Column 'idTeam' in where clause is ambiguous. The SQL statement
executed was: SELECT COUNT(DISTINCT `t`.`idWorker`) FROM `workers` `t` LEFT OUTER JOIN
`teams` `Team` ON (`t`.`idTeam`=`Team`.`idTeam`) WHERE ((idTeam=:ycp0) AND (Team.name
LIKE :ycp1))
When I dont set idTeam attribute - it works fine. It's pretty weird - at the regular CRUD admin page - idTeam attribute is passed and that works fine.
Hot to deal with it?
In Workers::search() you have something like
$criteria->compare('idTeam',$this->idTeam);
Change it to
$criteria->compare('t.idTeam',$this->idTeam);
i.e prefix sql attribute with t. if it is from current model or with relation name if from other table/model
Also instead of:
$workers->attributes = array('idTeam' => $id);
yould could keep it simpler with:
$workers->idTeam = $id;
You have defined the column idTeam in Team and Workers. By joining those tables you would have a duplicate ("ambiguous") column in the result. That's what the error message tells you.
To solve this you have to use an alias for one of the columns.