Simply trying to store and retrieve unregistered customer data from page to page in a custom checkout template. I've stripped it down to the bare bones to try to pinpoint the issue.
This
<?php
$customer = WC()->customer;
$customer->set_billing_first_name("WORKING!!!");
$customer->save();
var_dump($customer->get_billing());
?>
Outputs this
array (size=2)
'country' => string 'US' (length=2)
'first_name' => string 'WORKING!!!' (length=10)
But then this
<?php
$customer = WC()->customer;
//$customer->set_billing_first_name("WORKING!!!");
//$customer->save();
var_dump($customer->get_billing());
?>
Outputs this
array (size=1)
'country' => string 'US' (length=2)
Even though I should still be firmly within the same session, and therefore should get the data stored before the comments. All I did was refresh the page after commenting out those two lines.
Am I completely wrong about these methods?
Checked
Environment is configured entirely correctly. Even had someone else double-check it for me. URLs, caches, etc.
It does appear to work when logged in, but the vast majority of users never do so that's not very helpful.
Have tried this on two different servers (one local, one remote) and have the same issue.
Started fresh with a new WP+WC install, created a blank theme, functions.php that does the above on init code. Same exact issue.
If $customer->save() doesn't persist the changes you made to the customer's data (e.g. $customer->set_billing_first_name('Test')), then it's likely because the customer is not registered to the site or not logged-in, where $customer->get_id() is 0.
And that is normal because the user's ID or the session's ID is required in order to properly save the changes and make it persistent across different pages.
So when the user is not registered/logged-in, WooCommerce doesn't start its session until the user logs in, or that he/she added a product into the cart.
But you can manually start the session, like so: (add the code to the active theme's functions.php file)
add_action( 'woocommerce_init', function(){
if ( ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
} );
And then, changes to the customer's data would then be carried on to other pages so long as cookies are enabled on the browser, because just like WordPress, WooCommerce stores its session ID (the user ID or an auto-generated ID/hash) in the cookies — and the session ID is used to set/retrieve the session data in the database — the table name is woocommerce_sessions if without any table prefix.
Try this after starting the WooCommerce session:
$customer = WC()->customer;
// Change 'Test' if necessary - e.g. 'Something unique 123'
if ( 'Test' !== $customer->get_billing_first_name() ) {
$customer->set_billing_first_name( 'Test' );
echo 'First name added to session<br>';
} else {
echo 'First name read from session<br>';
}
And this one — you should see a new date on each page load: (well, the one you've set previously)
echo WC()->session->get( 'test', 'None set' ) . '<br>';
WC()->session->set( 'test', current_time( 'mysql' ) );
echo WC()->session->get( 'test', 'It can\'t be empty' );
Are you using the Url set in Wordpress? It seems that it stores the cookie based on the url configured in the app rather than the actual one.
Hope this helps.
Source: https://en.blogpascher.com/wordpress-tutorial/How-correct-the-loss-of-session-on-wordpress
Related
i want to set a cookie if a specified form (Contact Form 7) was sent.
If is write the code into the init-call it works:
function process_post() {
if( isset( $_POST['kampagne'] ) ) {
setcookie('cid', get_option( 'cf7-counter', 0) + 1 , time()+3600, '/');
}
}
add_action( 'init', 'process_post' );
But that's not good, because the value of cookie is an id - stored in database, which i must get in the moment where the form will send.
So I want to set the cookie in the "wpcf7_before_send_mail" hook. But within that the cookie will not generate.
function wpcf7_do_something($WPCF7_ContactForm)
{
$submission = WPCF7_Submission :: get_instance();
if ( $submission ){
$posted_data = $submission->get_posted_data();
if ( empty( $posted_data ) ){ return; }
$changed_name = get_option( 'cf7-counter', 0) + 1;
update_option('cf7-counter', $changed_name);
$mail = $WPCF7_ContactForm->prop( 'mail' );
$new_mail = str_replace( '[cf7-counter]', '00'. $changed_name .'', $mail );
$WPCF7_ContactForm->set_properties( array( 'mail' => $new_mail ) );
return $WPCF7_ContactForm;
}
}
add_action("wpcf7_before_send_mail", "wpcf7_do_something");
I hope you can help me.
Thank you very much!
Best regards.
But that's not good, because the value of cookie is an id - stored in database, which i must get in the moment where the form will send.
So what you need is the ID that will be stored into the database when creating the cookie.
Create it
if( isset( $_POST['kampagne'] ) ) {
$cookie = 'cid';
$id = uniqid("cid:", true);
setcookie($cookie, $id, $_SERVER['REQUEST_TIME'] + HOUR_IN_SECONDS, '/', ini_get('session.cookie_domain'), (bool)ini_get('session.cookie_secure'), (bool)ini_get('session.cookie_httponly'));
$_COOKIE[$cookie] = $id;
}
; and store it
$cookie = 'cid';
$WPCF7_ContactForm->set_properties(
[
'mail' => $new_mail,
'cid' => $_COOKIE[$cookie],
]
);
.
The contact form transaction now has the id that is in the cookie.
It is independent to get_option( 'cf7-counter', 0) by binding the submission to its own identifier - like the cookie is not the cf7-counter option.
Take note on explicitly setting $_COOKIE[$cookie] = $id;, always. This is to have the ID in the request itself.
Take double note on this action, as the code does set the cookie with a new ID even if it was already set. If that is not your intention, check if the cookie is unset beforehand (later references on setting a cookie in Wordpress have it, too).
It is now more eventually consistent, up to the level of uniqueness of the uniquid() function (study it if you want to make use of it), which is an improvement over the situation where the chance of being inconsistent was much higher (that is when using the cf7-counter option).
An insecure random-unique ID normally is enough for short term transaction tagging, e.g. having it for an hour in the cookie.
Which is something you may want to put more of your attention to. And the example is less Wordpress specific, there is more to get from in Wordpress like nonces, keys, salts, cookie-paths, user-level cookies etc. pp. to adhere to that system specifically.
It requires you to study Wordpress first, which I can't take of your shoulders, and there is even more to learn first, like how cookies work. Perhaps ask the more general questions first that you have to close such gaps.
Another answer I was thinking about first is to take a more fitting action so that you have the id the moment you can do both: setting the cookie and storing to the database.
As it has been commented, such a solution would need to find the right place in time. But that is merely how cookies work.
(And not specifically Wordpress.)
As you have already seen yourself, the action you wanted to use did not work.
And even if you would find such another action, this is still Wordpress, and it would be unpredictable that it would suffice: The cookie might be set in your tests, but not when a user visits the site (or any site that is out there with Contact Form 7 which this answer should answer if it is worth it).
To set a cookie in Wordpress, there is no free choice of the action to do it in, but it first of all needs to set the cookie for which the action is invariant:
How to set a cookie in Wordpress
Setting a redirect cookie in wordpress
As the action is set in stone to set a cookie, this goes back to the answer above.
However this is not Wordpress SE, but Stackoverflow so I've put the focus more on the PHP code itself where it relates to the PHP configuration and only HOUR_IN_SECONDS is a constant from Wordpress in it. See as well my comment on it about more specific Wordpress features you may want to add to it.
It hopefully answers your question to the level you need it.
I am sharing 3 screens step by step will be through woocommerce.
I have a shop page. On selecting a product, I will go to a front end form for creating a post. After creating a post I will go to checkout page.
My question is that, can I get the middle one (front end form for creating a post) in woocommerce platform ?
Please look my shared screen for understanding it better.
Thank you
First Screen
Second Screen
Third Screen
My question is that, can I get the middle one (front end form for
creating a post) in woocommerce platform ?
Sure, but you have to save the data from step 2 in the current session (cart).
Only when an order is created, collect the session data and create the (custom_post_type) job post. You don't want to create the job post before the order is completed / paid for.
Your question is very general, so you can expect a similar answer. We do not build complete plugins here. You will need to use multiple hooks to complete this.
EDIT: some more info
# step 2, collect, sanitize and validate the form values.
I would save this data in the cart session. something like this:
// I don't know how and where you collect the step 2 data,
// so i can't provide a hook for this function.
function step_2_data_to_session() {
global $woocommerce;
$step_two_data = array();
// validate and sanitize data first
// save data to woocommerce session
$woocommerce->session->set('step_two_data', $step_two_data );
}
Then when the user pays and creates an order, use a hook to collect the session data and save it to your costom post type.
add_action('woocommerce_checkout_update_order_meta', 'new_order', 10, 2)
function new_order($order_id, $data) {
global $woocommerce;
// At this point the order is created and the session data is still alive.
if(! is_admin() ) {
$step_two_data = $woocommerce->session->get('step_two_data');
if($step_two_data) {
$args = array(
'post_author' => get_current_user_id(),
'post_title' => 'The Job title here',
'post_type' => 'job',
'post_status' => 'publish'
);
$new_job_post_id = wp_insert_post($args);
if($new_job_post_id) {
// Job post is saved now..
// Now you'll probably want to add step_two_data as meta data to the post.
}
}
}
}
NOTE: I haven't tested this code, error handling is not included, etc. This is just a pointer how to save the session data when the order is created.
You'll have to do much more, for example, i see that the job listing has a set expiration date. I would use a cron-job to daily check which jobs have to be removed, with the same cron i would also inform customers their job post 'will be removed in 2 days' etc etc ;-)
Regards, Bjorn
I have a membership site where people can sign up for an account using their name, phone number and password of choice. The information entered during registration is stored in a MySQL database table called users. The primary key in the users table is the phone number. During sign up, the user has the option to type the phone number of his referrer into the referrer field. have all these set up and working fine, but I want to enhance the site some more, by:
Creating a unique referral link for users which will have their phone number appended to their link. I want to track which user referred others to my site so I can reward them.
When they share this link, and people click on it, it will take them to the registration page (register.php). On that page he phone number of the referrer will be set (and locked) in the referrer field.
I did some digging on the internet and found this code on github:
<?php
//check for referal links
function referal()
{
$CI =& get_instance();
$cookie_value_set = $CI->input->cookie('_tm_ref', TRUE) ? $CI->input->cookie('_tm_ref', TRUE) : '';
if ($CI->input->get('ref', TRUE) AND $cookie_value_set == '') {
// referred user so set cookie to ref=username
$cookie = array(
'name' => 'ref',
'value' => $CI->input->get('ref', TRUE),
'expire' => '7776000',
);
$CI->input->set_cookie($cookie);
return TRUE;
}elseif ($cookie_value_set == '') {
$cookie = array(
'name' => 'ref',
'value' => 'sso',
'expire' => '15552000',
);
$CI->input->set_cookie($cookie);
return TRUE;
}elseif ($cookie_value_set != '') {
//already referred so ignore
return TRUE;
}else{
return TRUE;
}
}
//end of hooks file
?>
The owner of the gist only mentioned saving the file as referral.php inside the hook folder. This is not helping me with what I want to achieve, I don't know how to use the code:
1. How do I pass the referrer field to the variable username from the users table?
2. How do I load the hook file to view (register.php)?
3. How and where do I call the hook file?
So can anybody give me an insight?
Well you are new to CodeIgniter and php. This will help you to get start with codeIgniter. Start coding with CodeIgniter using PhpStorm on Ubuntu 16.04 Merge Bootstrap to your current codeIgniter project in PhpStorm on ubuntu 16.04. Even these says about ubuntu os, it can use in other os as well. I think it's better to use id otherthan phone number for the primary key and make phone number as unique. It is not good to put phone number to the url. Because it is something personal for a user. You can use the id to the url. You can add it by as QueryString. To track users who use your site, you can add Google search console and Google analytic.
I can add and remove fields in the user profile section with:
function add_remove_contactmethods($contactmethods ) {
// Remove AIM
unset($contactmethods['aim']);
//add Phone
$contactmethods['phone'] = 'Phone';
return $contactmethods;
}
add_filter( 'user_contactmethods', 'add_remove_contactmethods' );
When I view this screen in the backend, the "Phone" field comes last, after some other fields like "Email" and "Website". I guess this is because my added field was added after the default Wordpress fields. How do I sort this, for instance alphabetically, so that my "Phone" field comes in alphabetical order instead of after the default fields? How do I sort the output of $contactmethods without messing it up?
try using ksort
function add_remove_contactmethods($contactmethods ) {
// Remove AIM
unset($contactmethods['aim']);
//add Phone
$contactmethods['phone'] = 'Phone';
ksort($contactmethods);
return $contactmethods;
}
add_filter( 'user_contactmethods', 'add_remove_contactmethods' );
re
UPDATE: So I guess the answer to my original question, is to explain why and how "Website" and "Email" are stored, and how the output is controlled in the backend when you view a profile. Maybe it's an ordered action? I guess "Website" and "Email" are just user meta, but how is the output order controlled. I accept that I might have to write a custom script to sort the output, I just don't know where to begin.
Your right about that, all the new contact fields were added into user_meta table. user_email and user_url are in the users table. The problem you are going to have doing this, is that a filter does not exist to modify the information. You can check the main filters here:
http://codex.wordpress.org/Plugin_API/Filter_Reference
and also you can look at core itself. All the admin templates are in wp-admin so you can look at the variable you need to modify in user-edit.php ($profileuser). Im in no way recommending this, but you could modify the template there, it will be overwritten on the next update of course so thats a drawback to it.
There may be a hook somewhere in admin in the load template process, if you could find one, you could relocate the template location to a theme file and recreate it with the changes you want. But all this seems like a lot of work to include just 2 fields to reorder?
Another approach is to use a higher priority the other when adding the fields. For example, Yoast adding 3 contact methods, and if you want your 'phone' appear before those, set the filter to:
add_filter('user_contactmethods', 'my_contactmethods', -5, 1);
Email and Website cant be re-ordered unless deep PHP coding or javascript re-order or advanced CSS.
if you know the key(s) (check the name fields in the source code), you can add other plugin fields by yourself, and choose exact appearance. A field is only added once if they added twice (!) This is how we use:
function entex_author_contactmethods($contactmethods){
$contactmethods['mail'] = __('Public email', 'entex-theme');
$contactmethods['phone'] = __('Phone', 'entex-theme');
$contactmethods['googleplus'] = __('Google+', 'wordpress-seo');
$contactmethods['youtube'] = __('YouTube URL', 'wordpress-seo');
$contactmethods['facebook'] = __('Facebook profile URL', 'wordpress-seo');
$contactmethods['instagram'] = __('Instagram URL', 'wordpress-seo');
$contactmethods['twitter'] = __('Twitter username (without #)', 'wordpress-seo');
$contactmethods['linkedin'] = __('LinkedIn URL', 'wordpress-seo');
$contactmethods['myspace'] = __('MySpace URL', 'wordpress-seo');
$contactmethods['pinterest'] = __('Pinterest URL', 'wordpress-seo');
return $contactmethods;
}
add_filter('user_contactmethods', 'entex_author_contactmethods', -5, 1);
Happy contact-ing!
I am trying to develop a small web shop with CodeIgniter. To store the items, I use the Cart library. Most of the time, everything works great. However, sometimes the content of the cart gets lost after a redirect.
I found a couple of fixes on the web, but none of them works in my case. Here is my setup:
I use the DB for storing sessions
I don't use AJAX
There is no underscore in the name of the session cookie
Here is an example of a refresh:
public function add_item() {
$item_id = $this->input->post('item');
// Query database
$item = $this->model->find_item($item_id);
// Rewrite model info
...
$data = array(
'id' => 'item-' . $item['id'] . '-size-' . $item['sizes'][$i]['id'],
'qty' => $qty,
'price' => $item['sizes'][$i]['price'],
'name' => $item['name'],
'options' => array('short_name' => $item['short_name'])
);
$this->cart->insert($data);
usleep(10000);
redirect('shop');
}
I finally found an answer to my problem, thanks to this question: CodeIgniter Cart and Session lost when refresh page
The problem was that the data stored in the session got too big. CodeIgniter stores all the data in a cookie, which is limited to 4kB. My mistake was to think that, if I used the DB to store my sessions, I could avoid that limit. Apparently, CodeIgniter saves sessions in the database "only" for security reasons. There is still a lot of data in the cookie.
Now, I use a library called Native session. I found it here: https://github.com/EllisLab/CodeIgniter/wiki/Native-session
I just put the file in 'application/libraries', renamed the first function to '__construct()', added it to autoimport and replaced all the 'session' tags with 'native_session' in my code. I also had to change the Cart class because it was using CodeIgniter's original session.