I use drupal 7, and Entity API to develope a module. I have an entity to record client information. I wish to use image_field to let client upload their logo. So I have this function:
function silver_client_enable()
{
field_cache_clear();
field_associate_fields("silver_client");
if(field_info_field('logo'))
return;
$field = array(
'field_name' => 'logo',
'cadinality' => 1,
'type' => 'image',
);
field_create_field($field);
$instance = array(
'field_name' => 'logo',
'entity_type' => 'silver_client',
'bundle' => 'silver_client',
'label' => 'Logo',
'description' => 'Logo',
'display' => array(
'default' => array('label' => 'hidden')
),
'settings' => array(
'file_directory' => '/logo',
),
'widget' => array(
'type' => 'image_image',
),
);
field_create_instance($instance);
}
In the entity creation/edit form, I use :
field_attach_form('silver_client', $client, $form, $form_state);
to attch the field.
When I called up this form, the image upload field was corrected displayed. An i can use it to uplod file to serve.
In the form submit function, I save the entity as:
entity_save('silver_client', $client);
However, after I press the save button, the entity table is correctly saved. Field table is not. Both field_data_logo and field_revision_logo are empty.
I believer Entity API looks after the retrieving and saving of attached fields. Can someone tell me what is wrong with my code? Thank you.
You have to write the values back into your entity:
field_attach_submit('silver_client', $client, $form, $form_state);
entity_save('silver_client', $client);
http://api.drupal.org/api/drupal/modules!field!field.attach.inc/function/field_attach_submit/7
And you should validate the field values:
field_attach_validate('silver_client', $client, $form, $form_state);
http://api.drupal.org/api/drupal/modules!field!field.attach.inc/function/field_attach_validate/7
Furthermore if you don't want to declare your entity and fields by yourself you might checkout the EntityConstructionKit : http://drupal.org/project/eck which allows to export entity structures with Features just like Views.
Related
I am trying to require a handful of fields in the Admin area of WooCommerce inside of the Create New Order form. I have successfully worked out how to do this for all of the fields except for the State drop-down menus. Here is what I have so far (all of this code is functioning properly):
// Require certain fields in NEW ORDER creation via Admin
add_filter('woocommerce_admin_billing_fields', 'woocommerce_require_admin_billing_fields');
function woocommerce_require_admin_billing_fields( $fields ){
$fields['first_name']['custom_attributes'] = array( 'required' => '1' );
$fields['last_name']['custom_attributes'] = array( 'required' => '1' );
$fields['address_1']['custom_attributes'] = array( 'required' => '1' );
$fields['city']['custom_attributes'] = array( 'required' => '1' );
$fields['postcode']['custom_attributes'] = array( 'required' => '1' );
$fields['country']['custom_attributes'] = array( 'required' => '1' );
$fields['email']['custom_attributes'] = array( 'required' => '1' );
$fields['phone']['custom_attributes'] = array( 'required' => '1' );
return $fields;
}
add_filter('woocommerce_admin_shipping_fields', 'woocommerce_require_admin_shipping_fields');
function woocommerce_require_admin_shipping_fields( $fields ){
$fields['address_1']['custom_attributes'] = array( 'required' => '1' );
$fields['city']['custom_attributes'] = array( 'required' => '1' );
$fields['postcode']['custom_attributes'] = array( 'required' => '1' );
$fields['country']['custom_attributes'] = array( 'required' => '1' );
$fields['state']['custom_attributes'] = array( 'required' => '1' );
return $fields;
}
// Require fields that are not included in woocommerce_admin loops
function vic_require_admin_fields() {
echo '<script>document.getElementById("excerpt").setAttribute("required", "1")</script>'; // order notes (excerpt)
echo '<script>document.getElementById("_payment_method").setAttribute("required", "1")</script>'; // payment method
}
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'vic_require_admin_fields' );
I have tried to require the "State" drop-down field in a similar manner as the rest (through a filter targeting the "state" id) and I have also attempted to target it with a javascript action, but both efforts produced no solution. It looks like the way the form is constructed is through a boostrap drop-down? The actual tag is set to display: none, so I can't really do much with that.
I can see that when I select a selection without a state, the SELECT field turns into an INPUT field, which is I think why I am unable to target it to add the required attribute:
It's alright if I can't do this with a filter. I'm thinking I may need some javascript attached to the button for form validation maybe? I couln't seem to find the actual form id, in order to validate through javascript, though I will probably look more around this evening when I'm home.
Any ideas to help me find a solution will be much appreciated!
I have a custom module on my site. I try to install an update with a new field for my vocabulary, but the field doesn't appear.
hook_update:
function mymodule_update_7118()
{
$field_name = 'field_newfield';
if ( field_info_field( $field_name ) ) {
return;
}
$field = array(
'field_name' => $field_name,
'type' => 'list_integer',
'settings' => array(
'allowed_values' => array(
'Yes' => 1, //heard that adding a NO value may cause problems, although it doesn't work with a no value either.
),
),
);
$field = field_create_field( $field );
$instance = array(
'field_name' => $field['field_name'],
'entity_type' => 'taxonomy',
'bundle' => 'vocab_name',
'label' => 'Label',
'widget' => array(
'active' => 1,
'module' => 'options',
'settings' => array(),
'type' => 'options_select',
'weight' => '3',
),
);
field_create_instance($instance);
}
Logs contain several recordings of Internalization module creating a string to translate this field. Also all needed tables are created in the database, but they are all empty.
For creating a new custom field you must do it like a custom module. The steps can be found out at https://drupal.stackexchange.com/questions/140517/how-to-create-new-field-type
You can find the excellent field_example module from the Examples Module which is always the first place to look. Examples module can be downloaded from https://www.drupal.org/project/examples
i have created module but unablet to create table below is my code of mysubscribers.install
mysubscribers.install
function mysubscribers_schema(){
$schema['mysubscribers'] = array(
'description' => 'The table for storing the subscriber data.',
'fields' => array(
'id' => array(
'description' => 'The primary identifier for subscriber.',
'type' => 'serial',
'not null' => TRUE,
'unsigned' => TRUE,
),
),
'primary key' => array('id'),
);
return $schema;
}
/**
* Implements hook_install().
*/
function mysubscribers_install() {
if (db_table_exists('mysubscribers')) {
db_drop_table('mysubscribers'); // old table from 5.x-2.x
}
}
No issues here when running your code.
You don't need to remove the DB on install.
If you make changes to the schema add your changes to hook_update()
with something like db_change_field() or db_add_field().
As long as your naming convention is correct this should work.
assuming you have a mysubscribers.info,mysubscribers.module, and mysubscribers.install
I have an entity Product. My product can have multiple names in different languages. A name in french, a name in english, etc. I don't want to use an automatic translation.
The user will have to write the names in the Product form and select the corresponding language. He can add so many names as he wants thanks to an Add button.
All the languages are created by the admin user (in another form). So, Language is also an Entity which have a name (ex: English) and a code (ex: EN).
I created the Entity ProductName which have a name and a language (that conform to what the user writes in the Product form).
In that case, I don't need to associate Entity ProductName with Entity Language. I just want the language code. So, in my ProductName entity, I have this property :
/**
* #ORM\Column(name="Language_Code", type="string", length=2)
*/
private $language;
My Product form (ProductType) has a CollectionType field in order to add several names.
// Form/ProductType.php
->add('infos', CollectionType::class, array(
'entry_type' => ProductInfosType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'label' => false,
'mapped' => false
))
And ProductInfosType form has 2 fields :
// Form/ProductInfosType.php
->add('name', TextType::class, array(
'attr' => array('size' => 40)
))
->add('language', EntityType::class, array(
'placeholder' => '',
'class' => 'AppBundle:Language',
'choice_label' => 'code',
'attr' => array('class' => 'lang'),
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('l')->orderBy('l.code', 'ASC');
}
))
So, when I go on my form page, I have a block which contains an input text field (Name) and a select field (language). The select field is like this :
<select id="product_infos_0_language" required="required" name="product[infos][0][language]">
<option value=""></option>
<option value="DE">DE</option>
<option value="EN">EN</option>
<option value="ES">ES</option>
<option selected="selected" value="FR">FR</option>
</select>
At this point, everything works well. I created an add button so that the user can add other names, etc...
But, when I submit the form, when I check form data in my ProductController, I noticed that it does not correspond to what I want to store in database.
print_r($form->get('infos')->getData());
// returns :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[language:AppBundle\Entity\ProductName:private] => AppBundle\Entity\Language Object
(
[code:AppBundle\Entity\Language:private] => FR
[name:AppBundle\Entity\Language:private] => Français
)
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
)
)
What I would like is :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[language:AppBundle\Entity\ProductName:private] => FR
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
)
)
I don't want the language object but directly the language code !
That's why I think that I should not use EntityField in ProductNameType form but ChoiceType field.
How can I load all the languages stored in db in the choice field ?
I hope that this explanation is more understandable ;-)
I found the solution thanks to this post : Passing data to buildForm() in Symfony 2.8/3.0
ProductController.php : pass custom data as an option in the createForm() method.
// ...
// build the form
$em = $this->getDoctrine()->getManager();
$product = new Product();
$languages = $em->getRepository('AppBundle:Language')->findAllOrderedByCode();
$form = $this->createForm(ProductType::class, $product, array(
'languages' => $languages
));
ProductType form : pass custom data in the options resolver
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Product',
'languages' => null
));
}
Then, in the buildForm() function, add an entry_options option in the CollectionType field :
$builder->add('infos', CollectionType::class, array(
'entry_type' => ProductInfosType::class,
'entry_options' => array('languages' => $options['languages']),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'label' => false,
'by_reference' => false
));
ProductInfosType form : pass custom data in the options resolver (exactly the same as in the ProductForm)
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\ProductName',
'languages' => null
));
}
Now, you have two alternatives : either you want that your form returns entities or simple strings.
In my example, I just want the language code (like FR, EN, etc.).
Case 1 : return only the language code when the form is posted :
// Form/ProductInfosType.php
// ...
// Convert array of objects in an array of strings
$choices = array();
foreach ($options['languages'] as $lang) {
$code = $lang->getCode();
$choices[$code] = $code;
}
$builder->add('language', ChoiceType::class, array(
'placeholder' => '',
'choices' => $choices
));
// returns :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
[language:AppBundle\Entity\ProductName:private] => FR
)
)
Case 2 : return Language Entity when the form is posted :
// Form/ProductInfosType.php
// ...
$builder->add('language', ChoiceType::class, array(
'placeholder' => '',
'choices' => $options['languages'],
'choice_label' => 'code',
'choice_value' => 'code'
));
// returns :
Array
(
[0] => AppBundle\Entity\ProductName Object
(
[name:AppBundle\Entity\ProductName:private] => Ceinture lombaire LombaSkin
[language:AppBundle\Entity\ProductName:private] => AppBundle\Entity\Language Object
(
[code:AppBundle\Entity\Language:private] => FR
[name:AppBundle\Entity\Language:private] => Français
)
)
)
With this solution, we don't need to create our form as a service in order to pass entity manager as an argument. All is managed in the controller and form options.
You should use choice_value of EntityType.
'choice_value' => function ($language) {
return $language->getCode();
},
EDIT: After reading your edit, you're indeed right, do not use EntityType but ChoiceType. To populate choices, I think you should inject LanguageRepository inside your Form using DependencyInjection, and then create a query in your Repository to fetch all Language codes.
I'm trying to add custom fields to the user registration form. I need to save 2 of them into the Drupal User's database and 1 into my own separate database.
I'm using hook_form_alter to add the fields and then hook_form_submit to save the fields.
How do I submit the first/last name fields into drupal's user table and then save the SSN into my own? I have a function to switch between the 2 databases already but am just not sure how to use hook_submit_form to save some in one database and some in another?
function myModule_form_alter(&$form, &$form_state, $form_id){
if($form_id == 'user_registration_form'){
$form['f_name'] = array(
'#type' => 'textfield',
'#title' => t('First Name'),
'#required' => TRUE,
'#attributes' => array('class' => array('fname'))
);
$form['l_name'] = array(
'#type' => 'textfield',
'title' => t('Last Name'),
'#required' => TRUE,
'#attributes' => array('class' => array('lname'))
);
$form['ssn'] = array(
'#type' => 'textfield',
'#title' => t('Social Security Number')
'#maxlength' => 11,
'#required' => TRUE,
'#attributes' => array('class' => array('ssn'), 'placeholder' => '999-99-9999')
);
Would it be something like this?
function myModule_form_submit($form, &$form_state){
//Array of information to save into drupal user's table
$edit = array(
'f_name' => $form_state['values']['f_name'],
'l_name' => $form_state['values']['l_name'],
'second_email' => $form_state['values']['second_email'],
);
user_save(drupal_anonymous_user(), $edit);
drupal_set_message(t('The form has been submitted.'));
}
I'm not sure if I can use drupal's user_save() function and pass it this new information to save or if I have to do something in the .install file to add these new columns and then target them in the form_submit?
In what field will you save the custom field data? You should create a custom table for those fields and save data in there. When you load the user, you should also load those details from that table. There is no way you can directly load those custom field data when user object is loaded.