SamC Posted September 14, 2017 Share Posted September 14, 2017 (edited) Following on from this post: I got to work in trying to make this a reality. After studying the API for a bit plus reading examples, I got a sign up form going: //views/signup.php <?php namespace ProcessWire; function createUser($user, $email, $password) { // create user $u = new User(); // set name $u->name = $user; // set email $u->email = $email; //set password $u->pass = $password; // assign role of "member" $u->addRole("member"); // save new member $u->save(); // if successful $success = true; return $u; } function createProfile($user) { // create profile page $p = new Page(); // set template (can only be child of profile-index) $p->template = "profile-entry"; // set page name $p->name = $user->name; // set page title $p->title = $user->name; // set page title $p->altTitle = "Profile page for " . $user->name; // set page reference to correpsonding user page $p->userRef = $user->id; // save page $p->save(); } // input field validation wireIncludeFile("./vendor/vlucas/valitron/src/Valitron/Validator.php"); // sanitize input field values $user = $sanitizer->userName($input->post->inputUsername); $email = $sanitizer->email($input->post->inputEmail); $password = $input->post->inputPassword; $v = new \Valitron\Validator(array( "user" => $user, "email" => $email, "password" => $password ) ); $v->rule("required", ["user", "email", "password"]); $v->rule("email", "email"); $v->rule("lengthMin", "password", 6); // if form has been submitted if($input->post->sendMe) { if ($v->validate()) { // return user if exists $u = $users->get($user); // return user if email address exists $e = $users->get("email=$email"); // if both user or email don't exist if (!($u->id) && !($e->id)) { // create user and profile createProfile(createUser($user, $email, $password)); // return result of attempted login $u = $session->login($user, $password); // check if user now exists if (!is_null($u)) { $session->redirect($pages->get(1037)->url . $user); } } else { $session->success = false; // email taken if ($e->id) { $session->flashMessage = 'Email already exists. Please use another email.'; } // user taken else { $session->flashMessage = 'User already exists. Please choose another username.'; } } } else { $session->success = false; $session->flashMessage = 'All fields must be complete.'; } } ?> <div class="container"> <div class="row justify-content-center py-5"> <div class="col-6"> <?php if($session->flashMessage):?> <div class="alert <?= $session->success ? 'alert-success' : 'alert-danger'?>" role="alert"> <?php echo $session->flashMessage;?> </div> <?php endif;?> <form action="./" method="post"> <div class="form-group <?php echo $v->errors('user') ? 'has-danger' : ''?>"> <input type="username" class="form-control" name="inputUsername" placeholder="Username" value="<?= $user; ?>"> </div> <div class="form-group <?php echo $v->errors('email') ? 'has-danger' : ''?>"> <input type="email" class="form-control" name="inputEmail" placeholder="Email" value="<?= $email; ?>"> </div> <div class="form-group <?php echo $v->errors('password') ? 'has-danger' : ''?>"> <input type="password" class="form-control" name="inputPassword" placeholder="Password"> </div> <div class="form-group"> <button type="submit" name="sendMe" value="1" class="btn btn-primary">Create account</button> </div> </form> </div> </div> </div> <?php $session->remove('flashMessage'); ?> I've got templates: profiles-index (just used in the tree to hold the profiles) profile-entry (hold the individual profiles) I put a page ref field on profile-entry, which points to the user. See question (3) below. So, I end up with a URL like 'mysite.com/profiles/beastman' So the questions I have: 1) Is there a better way of doing this: // return user if exists $u = $users->get($user); // return user if email address exists $e = $users->get("email=$email"); // if both user or email don't exist if (!($u->id) && !($e->id)) { Any advice on writing better code, then throw it my way please. I'm trying different techniques like using functions etc. for practice. 2) I haven't used this code, but what does: $u->of(false); ...do? I see this in a lot of the login forms examples. i found it in the API but still not sure why to use it. 3) Have I done this the right way round? Should the page reference be on user template pointing to the profile, or the on the profile template pointing to the user? The whole process goes something like this. Go to /signup/: Validation, fields not filled out: Validation, user already exists: Validation, email already exists: Enter some details, logs you in and redirects: Default login page: Refresh the admin login page: So now I can at last demonstrate my issues with users getting the tree view vs having a custom dashboard. Bear in mind they will only get to this page if they use the admin login form. If they go to the tree view here, I have another problem. If they click profile name (top right), then go to change the password, the rules are different from the ones I set in the initial sign up form. The built in rules are "Minimum requirements: at least 6 characters long, letter, digit." My rule was just 6 characters at least. Anyway, going off topic. The "where does the user go and how do they change their profile details once they've logged in" bit part confuses me. Presuming they could go to a dashboard or something else if they used the 'other' login form block I'm working on and avoid the admin backend entirely: So, the new user is in the system: and: Sweet! Basic, pretty useless, but a great learning experience so far --EDIT-- Added some more images to show how the form works when validation fails. I would recommend recaptcha too though to stop spam users: https://modules.processwire.com/modules/markup-google-recaptcha/ Once you've got a site key from Google, it's as simple as configuring the module in the PW admin then in your template: $captcha = $modules->get("MarkupGoogleRecaptcha"); // render the recaptcha <?= $captcha->render(); ?> For valitron, install composer then (I ran this command from inside /site/templates/): composer require vlucas/valitron ...results in '/site/templates/vendor' folder which has valitron inside. Then just include the file: wireIncludeFile("./vendor/vlucas/valitron/src/Valitron/Validator.php"); Hopefully this will help someone Edited September 14, 2017 by SamC Added more details 2 Link to comment Share on other sites More sharing options...
adrian Posted September 14, 2017 Share Posted September 14, 2017 4 minutes ago, SamC said: So the questions I have: 1) Is there a better way of doing this: // return user if exists $u = $users->get($user); // return user if email address exists $e = $users->get("email=$email"); // if both user or email don't exist if (!($u->id) && !($e->id)) { Any advice on writing better code, then throw it my way please. I'm trying different techniques like using functions etc. for practice. From what it looks like, $user is the currently logged in user - this check is outside your functions, so I don't see that this is actually doing anything. The email check looks fine This should also be ok, but remember the issue I mentioned with the first line. 7 minutes ago, SamC said: 2) I haven't used this code, but what does: $u->of(false); ...do? I see this in a lot of the login forms examples. i found it in the API but still not sure why to use it. This turns off output formatting which is important when saving fields to a page - consider a datetime - you want to save a unix timestamp, and not a formatted string like 14 September, 2017 7:17:11 am 9 minutes ago, SamC said: 3) Have I done this the right way round? Should the page reference be on user template pointing to the profile, or the on the profile template pointing to the user? Really your call - there are arguments for both approaches. You might actually find things simpler if you try this approach to user pages: https://processwire.com/blog/posts/processwire-core-updates-2.5.14/#multiple-templates-or-parents-for-users which lets you set up users with URL accessible pages directly. BTW - a great writeup of your approach here - I am sure others will learn lots! 3 Link to comment Share on other sites More sharing options...
benbyf Posted September 14, 2017 Share Posted September 14, 2017 I tend to do this sort of thing where I attach all the user based fields to the current user i.e. $user->fieldname instead fo creating a new page each time, then simply create a profile template shows those fields. which is fine if you have to be logged in, in your case you could enable page url partials in the profile tamplte and look for the partial (your user name input) to get the same effect. 1 Link to comment Share on other sites More sharing options...
SamC Posted September 14, 2017 Author Share Posted September 14, 2017 31 minutes ago, adrian said: From what it looks like, $user is the currently logged in user - this check is outside your functions, so I don't see that this is actually doing anything. $user there was supposed to be checking whether the username used in the signup form, i.e. the current value of: // sanitize input field values $user = $sanitizer->userName($input->post->inputUsername); ...is already a username in the system. I forgot to mention my form checks whether a username exists, also whether an email exists. Usernames and emails must be unique. Maybe I should have used a different variable name to avoid confusion. Or maybe it doesn't do anything, have to check that. 35 minutes ago, adrian said: This turns off output formatting which is important when saving fields to a page - consider a datetime - you want to save a unix timestamp, and not a formatted string like 14 September, 2017 7:17:11 am Ah, that's useful to know, thanks. 35 minutes ago, adrian said: Really your call - there are arguments for both approaches. You might actually find things simpler if you try this approach to user pages: https://processwire.com/blog/posts/processwire-core-updates-2.5.14/#multiple-templates-or-parents-for-users which lets you set up users with URL accessible pages directly. I'll have to test this out, can't say I fully understood the writeup on that, would have to see it in action. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now