add_row in ACF Pro isn't saving repeater values - wordpress

My Situation
I'm using Advanced Custom Fields Pro to store metadata for a post in wordpress.
My posts are created dynamically (not through the administrative interface), which means that I explicitly need to populate metadata using field keys, not field names. One of my fields is a repeater field with a single text area and another is a standard text area.
My Code
The following code is what I call (once per post). The post is created using wp_insert_post() earlier.
// Populate "Name"
update_field('field_566e360961c2f', 'John Doe', $wp_identifier);
// Populate "Sponsors"
foreach($sponsors as $sponsor) {
// Define "Sponsor Name"
$new_sponsor = array(
'field_566e32fb943a5' => 'Beats and Corn Companye'
);
add_row('field_566e32bd943a4', $new_sponsor, $wp_identifier);
}
The result of this is that standard text fields populate, and a single "sponsor" repeater item is created, but the value of the sponsor name is blank.
The relevant wp_postmeta data that is generated looks like this:
| 18226 | 71 | name | John Doe
| 19234 | 71 | sponsors | 1 |
| 19235 | 71 | _0_field_566e32fb943a5 | Beats and Corn Company |
My Question
What am I doing wrong? Looking at the documentation for add_row() this appears to be the correct approach. Is it possible that repeater fields have a different way of notating keys that I'm not aware of?

This isn't made incredibly clear in the documentation today, but it turns out add_row only works if an existing row had already been saved. When trying to populate a repeater field for the very first time you have to use update_field instead and pass an array of value arrays.
The corrected code:
// Populate "Name"
update_field('field_566e360961c2f', 'John Doe', $wp_identifier);
// Populate "Sponsors"
$new_sponsors = array();
foreach($sponsors as $sponsor) {
// Define "Sponsor Name"
$new_sponsor = array(
'field_566e32fb943a5' => 'Beats and Corn Companye'
);
$new_sponsors[] = $new_sponsor;
}
update_field('field_566e32bd943a4', $new_sponsors, $wp_identifier);

Related

ASP.NET MVC 5 One-To-Many Create View

I am a newbie with ASP.NET MVC 5 design-Pattern. Kindly look at my problem and please help me in following scenario.
Here it is my table structure:
Order
( Id
| CustomerName
| OrderDate )
OrderDetail
( Id
| OrderId
| ProductId
| Quantity )
Product
( Id
| Name )
Order can have more than one detail, mean while detail has reference to product table. I want to create a screen where user can create new order, select products and also define quantity against each product.
I was not able to get a start point for create screen of this scenario in MVC Pattern.
Thanks.

ASP.NET Query database column with array of accepted keys

I've reached a problem with query the database correctly. I can't find it answered anywhere else.
My datamaodel contains three tables one with the Image data and another with tags.
The third table joins the two tables creting a many to many relationship:
[Image] - 1 --- * ->[ImageTagJoin] <- * --- 1 - [Tag]
From a user input of a set of tags I want to get every image contaning all of the tags. The following code works for one tag
viewModel.Tags = db.Tags.Where(
s =>
s.Name == searchString)
.Include(i => i.Images.Select( ii => ii.Image));
viewModel.Images = t.Images.Select(x => x.Image);
The only solution I have is if, input is tag1, tag2, tag3, the controller iterated over each tag.
Get set of images with the tag tag1
From that set of images of tag1 get the subset of images with tag2
From that set get the subset of images with tag3
Now I have a set of images with the tags tag1, tag2 and tag3. Though that this solution works but not as elegant because it requires to search the database once for every tag and every image row gets looked up for every tag in the input.
Conclusion: How can I query a many-to-many relationship between images and tags, where I select all images that have the subset of n tags given from the user.
Thanks.
With a bit of sweat and time I solved it. What I wanted was a IEnumreble from the database, an data stream not a collection wich is divided over each tag.
Solution:
/*
* tagSet is an array of string with all the tags
*/
viewModel.Tags = db.Tags.Where(
s =>
tagSet.Contains(s.Name))
.Include(i => i.Images.Select(ii => ii.Image));
// a is the image, aa i the users inputted tag, aaa is the tag in the image
viewModel.Images = db.Images.Where( //All images..
a =>
viewModel.Tags.All( //..where every tag the user inputed ..
aa =>
a.Tags.Any(aaa => aaa.Tag.Name == aa.Name) //exist in the image set of tag
)
);
First get a IEumreble with the tags the user inputed from the database. Then for every image that contans the set of all the users inputed tags in the set of tags related to the image. It works as I described it and as I understand it crafts one sql command that then returns the set of images from the database instead of the controller doing the lookup in an ICollection type of lookup.

Use a foreign property in Symfony entity form type

I am trying to find an easy way to use an entity form type, which uses the property from a joined table. I found a work around, but I hope this can be solved better than this.
In my situation, I want to show the translated text for my options in the selectbox. Unfortunately, the database is already there with it's translation tables, so I can't use the symfony country form type. So, for example, I have these tables:
Country
+----+-------------+
| id | name |
+----+-------------+
| 1 | Netherlands |
| 2 | Germany |
+----+-------------+
CountryTranslation
+----+-------------+------------+-----------+
| id | language_id | country_id | text |
+----+-------------+------------+-----------+
| 1 | 1 | 1 | Nederland |
| 2 | 1 | 2 | Duitsland |
| 3 | 2 | 1 | ... |
+----+-------------+------------+-----------+
Flags
+----+------------+-----------------------------+
| id | country_id | img_url |
+----+------------+-----------------------------+
| 1 | 1 | http://flags.cdn.com/nl.gif |
+----+------------+-----------------------------+
Now in my CMT, I want the user to be able to manage the flags table. The CMT is multi-lingual, so it should show the countries in his own language. So in my formbuilder I would like to do something like this:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$flag = $event->getData();
$form = $event->getForm();
if (!$flag) {
$form
->add('language', 'entity', array(
'class' => 'MbDbLookupBundle:Country',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('c')
->innerJoin('c.countryTranslations', 'ct', 'WITH', 'ct.languageId = :languageId')
->leftJoin('MyCmtBundle:Flag', 'f', 'WITH', 'f.country = c')
->where('f.country IS NULL')
->setParameter('languageId', $this->lang)
},
'property' => 'ct.text', // <--------- This will not work
'label' => 'Language',
'position' => array('before' => 'title'),
));
}
}
Things i've tried
Use a 'choice' field with a Data Transformer as explained here. This seemed ok at first, but I couldn't use this in my dynamic form as explained here. This was because inside the addEventListener, I can use $form->add, but I cannot use $form->add(form->create(...)) since the create function doesn't exist on that object.
Create a custom form type. In my application I wanted the selectbox to be filled only with countries that weren't selected already. So I needed to join my "Flags" table as well, which is why I use the dynamic form. Therefore I cannot use the custom form type, because I need the query to be dynamic, based on the underlying data.
My solution
In my Country entity I added the function getNameTranslated($langId=null). When there is only one record in the array, it would return this. This way I could query the object with an inner join, making sure I already have the right translation inside the Country object. To make this function less filthy, one also has the option to fetch by the locale manually by using the parameter. So I came up with something like this:
public function getNameTranslated($langId=null) {
if (!isset($langId) && count($this->nameTranslations) > 1)
throw new \Exception('No locale given '.count($this->nameTranslations));
foreach($this->nameTranslations as $nameTranslation) {
if (!isset($langId) || ($nameTranslation->getLanguageId() == $langId))
return $nameTranslation;
}
return false;
}
Now I can use 'property' => 'nameTranslated' in my form builder, also inside the form event listener.
Somehow I still don't really like this solution. I would rather solve the problem inside my form, instead of inside the object.
What complicates things, I think, is that I am using this form event, and that I am joining my "Flags" table to rule out the languages already chosen. Otherwise I think the best options would be to go with the 'choice' field together with the Data Transformer. But I hope I am missing something and there is a better solution to use a foreign property.

drupal 7: how to access list-field's key instead of its label (field api)

I'm working on a custom theme and googled the whole day but can't find an answer to my question:
how to print out a cck list field's key instead of its label?
I think it's the right way to access fields via the field api, right?
so I try
$output = field_view_field('node', $node, 'field_list');
print render($output);
that seems to be the way to get the label value of the key|label pair. but even if i set the display options format to 'key' - it only prints the label value. what am I doing wrong?
I know there are other options to render the key but how is it possible using field api?
You can get the field value itself (which will be the allowed values array key) with field_get_items():
$items = field_get_items('node', $node, 'field_list');
$key = $items[0]['value'];
If you need to match those up again at any point you can get the full key/value list from the field metadata:
$info = field_info_field('field_list');
$values = $info['settings']['allowed_values'];
$label = $values[$key];
Here's a similar way. This example works for a Country list with ISO codes.
The idea is to render the Name of the Country that was selected because the dump returns only the key ( iso code in this case)
Format of the select list on the backend:
AR|Argentina
US|United States
Assuming you have selected United States on the backend and you want to print the country name on the node template:
$country_field = field_info_field('field_country_iso');
$country_iso = $node->field_country_iso[LANGUAGE_NONE][0]['value'];
$country_name = $country_field['settings']['allowed_values'][$country_iso];
then
print $country_name; // This will return United States, not US code
I hope this helps.

How to join two Drupal CCK content types in view without a node reference field?

Users uploaded two csv files to create nodes for two CCK content types (Delivery Note and Payment), i.e.
Delivery Payment
---------- ---------
Order No. Order No.
Recipient Charge
Address
I would like to create a view as a report for the boss:
Order No. Recipient Charge
--------- --------- -------
... ... $...
... ... $...
... ... $...
Order No. field is unique and both content types.
How's it possible to do it in Drupal's view?
i believe you are looking for view relationships. check out drupal views relationships
for a video tutorial.
I ended up using View Custom Field with a PHP code field to retrive linked result via another view:
<?php
$order_no = $data->node_data_field_order_no_field_order_no_value;
if ($order_no) {
$view = views_get_view('find_cck_node');
$view->set_arguments(array('PAYMENT', $order_no));
$view->execute();
if (count($view->result)) {
$value = $view->result[0]->node_data_field_payment_amount_field_payment_amount_value;
print($value);
}
}
?>

Resources