Concatenate two variables - php

Here's what I'm trying to do:
$errmsg_1 = 'Please make changes to your post';
$errmsg_2 = 'Please make changes to your post image';
$error = 1;
echo $errmsg_.$error; //'Please make changes to your post';
Nothing will work, and there are many error messages like these ones that I have to echo.
Can anyone help?

What you're asking for is known as a variable variable -- see http://uk.php.net/manual/en/language.variables.variable.php for more info.
But please don't do that; it's considered very poor coding practice.
What you actually need is an array:
$errmsg = array(
'Please make changes to your post', //this will be $errmsg[0]
'Please make changes to your post image' //this will be $errmsg[1]
);
$error = 0; //nb: arrays start at item number 0, not 1.
echo $errmsg[$error];
That's much better coding practice than messing around with variable variables.

Store error messages in array:
$errmsg[1] = 'Please make changes to your post';
$errmsg[2] = 'Please make changes to your post image';
// and so on
$error = 1;
echo $errmsg[$error];

Try
echo {'$errmsg_' . $error};
Although you're doing this really rather incorrectly. You should be using an array instead; concatenating variable names is bad practice and leads to messy/unreadable/broken code. Using an array would work like this:
$errors = array(
'Please make changes to your post',
'Please make changes to your post image'
);
echo $errors[$error];
Although bear in mind that $error starts from 0 as arrays are 0-index based.

Off the top of my head I think you want $errmsg_{$error}, but I'm not in a position to test/double check that right now.

This should work:
$errmsg_1 = 'Please make changes to your post';
$errmsg_2 = 'Please make changes to your post image';
$error = 1;
echo ${'errmsg_ ' . $error};

No offence meant but what you're doing is bad design.
A small but no means perfect solution would be store your errors as an Array.
$errors = array('Please make changes to your post', 'Please make changes to your post image');
$error = 0;
echo $errors[$error];

Try using this ${$errmsg_.$error}
This is a variable variable: http://php.net/manual/en/language.variables.variable.php

You're trying to do this:
function errorMsg($code)
{
$msg;
switch($code)
{
case 1:
$msg = 'Please make changes to your post';
break;
case 2:
$msg = 'Please make changes to your post image';
break;
}
return $msg;
}
echo errorMsg(1);

$error_msg = 'Please make changes to your ';
$error[1] = 'post';
$error[2] = 'post image';
for($i=1; $i<=count($error); $i++)
echo $error_msg . $error[$i];

Use arrays. keep the indexes for easy future reference, as well as easy error message changing and organized API.
$errmsg = array(
1 => 'Please make changes to your post',
2 => 'Please make changes to your post image'
);
$error = 1;
echo $errmsg[$error]; //'Please make changes to your post';

Related

Check if session data isset and apply error to each item

I have to do the following for a large amount of session variables, is there a way I can shorten this code to apply to all the variables rather than repeatedly writing out if(!isset($_SESSION['whatever'])) and adding the apropriate error to the errors array.
if(!isset($_SESSION['fiat'])) {
$errors[fiat] = 'Please enter valid amount';
}
if(!isset($_SESSION['contact'])) {
$errors[contact] = 'Please enter valid contact';
}
if(!isset($_SESSION['name'])) {
$errors[name] = 'Please enter valid name';
}
I have tried some things with for loops and arrays but am really struggling even after some serious googling, so any help much appreciated.
Thanks!
I have now made the following array but am unsure how to use it:
$errors = array(
$_SESSION['fiat'] => 'Please enter valid amount',
$_SESSION['contact'] => 'Please enter valid contact',
$_SESSION['name'] => 'Please enter valid name',
);
Do i do something like the following? Not sure what goes inbetween.
for(!isset($errors)){
}
What you can do is the following:
$errors = array();
// List all session parameters and error messages you want to check here
$valuesToCheck = array(
'fiat' => 'Please enter valid amount',
'contact' => 'Please enter valid contact'
// and so on...
);
// Loop through all values you want to check and validate it. if validation doesn't pass add error message to $errors array.
foreach ($valuesToCheck as $k => $v) {
if(!isset($_SESSION[$k])) {
$errors[$k] = $v;
}
}
// Check if after the validation array with errors is not empty then deal with it.
if (!empty($errors)) {
// Do something with errors here
}
PS: I think you should learn more about software development basics before start writing a code. This will be useful in your further career.

Multiple IF statements in simple form validation

I am a newbie and trying to implement a simple validation script after reading up, but I can't see how I can have multiple Ifs that will only do an sql insert if all required fields are met. Rather than having the multiple else statements, what is a syntax approach for having all the form validation Ifs together and if one of them fails, then the correct error is shown and the sql is not execute?
if(isset($_POST ['submit'])){
$user_ID = get_current_user_id();
$catErr = $ratingErr = $titleErr = $textErr = "";
if (empty($_POST["category"])) {
$catErr = "Category is required";
} else {
//DO THE INSERT BELOW!
}
if (empty($_POST["rating"])) {
$ratingErr = "Rating is required";
} else {
//DO THE INSERT BELOW!
}
if (empty($_POST["post_name"])) {
$postErr = "Title is required";
} else {
//DO THE INSERT BELOW!
}
if (empty($_POST["text"])) {
$textErr = "Text is required";
} else {
//DO THE INSERT BELOW!
}
//PDO query begins here...
$sql = "INSERT INTO forum(ID,
category,
rating,
post_name,
text
Use one variable for all the error messages and concatenate to it in the branches, so in the end if that variable is still empty string you won't do the insert. (And you don't need any of the empty else blocks that contain nothing but a comment.)
$err = "";
if (empty($_POST["category"])) {
$err .= "<br/>Category is required";
}
if (empty($_POST["rating"])) {
$err .= "<br/>Rating is required";
}
if (empty($_POST["post_name"])) {
$err .= "<br/>Title is required";
}
if (empty($_POST["text"])) {
$err .= "<br/>Text is required";
}
//PDO query begins here...
if($err=='')
{
$sql = "INSERT INTO forum(ID,
category,
rating,
...";
...
}
There are many solutions to your problem. Here are 3 methods of solving your issue.
You could combine all of your if statements like so:
if (empty($_POST['rating']) || empty($_POST'rating']) || ... ) { ... }
and separate them by double pipes.
You could also check the entire array:
if (empty($_POST)) $error = "There was an error!";
You could set a universal error variable and then output it.
A third solution could keep your current syntax but cut down on the amount of lines. You could save lines by doing without brackets. You can create an array and push your errors to the array.
Note: You can use empty() or isset().
// create an array to push errors to
$errors_array = array();
// if a particular field is empty then push the relevant error to the array
if(!isset($_POST['category'])) array_push($errors_array, "Category is required");
if(!isset($_POST['rating'])) array_push($errors_array, "Rating is required");
...
Once you have an array full of errors you can check for them like so:
// if the array is not empty (then there are errors! don't insert!)
if (count($errors_array) > 0) {
// loop through and echo out the errors to the page
for ($i = 0; $i < count($errors_array); $i++) {
echo $errors_array[i];
}
} else {
// success! run your query!
}
You should use javascript to validate the page before it is even processed into a post. This script will run client-side when they hit submit and catch errors before they even leave the page.
Here's a tutorial on how to do something like that: tutorial
Each field can have its own validation parameters and methods, and it will also make the page's code look a lot nicer.
I got it to go with this approach after showdev got me thinking that way. It's not very elegant perhaps, but does the trick, although all the user is taken to a blank page if there are errors and it simple says: Missing category (or whatever). Wondering if I can echo a link or something back to the page with the form from there so the user has an option like "go back and resubmit". Otherwise I will have to handle and display the errors alongside the form which will require a different approach altogether...
if(isset($_POST ['submit'])){
$errors = false;
if(empty($_POST['category'])) {
echo 'Missing category.<br>';
$errors = true;
}
if(empty($_POST['rating'])) {
echo 'Missing rating.<br>';
$errors = true;
}
if(empty($_POST['post_name'])) {
echo 'Missing title.<br>';
$errors = true;
}
if(empty($_POST['text'])) {
echo 'Missing text.<br>';
$errors = true;
}
if($errors) {
exit;
}
// THEN ADD CODE HERE. But how display form again if user makes errors and sees nothing but error message on page if they miss something (which is how it works now)
Generally, if you find yourself repeatedly writing very similar statements, using some sort of loop is probably a better way to go about it. I think what you said about "handling and displaying the errors alongside the form" is really what you need to do if you want the process to be user-friendly. If you put your validation script at the top of the file that has your form in it, then you can just have the form submit to itself (action=""). If the submission is successful, you can redirect the user elsewhere, and if not, they will see the form again, with error messages in useful places.
if (isset($_POST['submit'])) {
// define your required fields and create an array to hold errors
$required = array('category', 'rating', 'post_name', 'text');
$errors = array();
// loop over the required fields array and verify their non-emptiness
foreach ($required as $field) {
// Use empty rather than isset here. isset only checks that the
// variable exists and is not null, so blank entries can pass.
if (empty($_POST[$field])) {
$errors[$field] = "$field is required";
}
}
if (empty($errors)) {
// insert the record; redirect to a success page (or wherever)
}
}
// Display the form, showing errors from the $errors array next to the
// corresponding inputs

Global error message in php

I have a problem with the understanding of variable scopes.
I've got a huge .php file with many $_POST validations (I know that isn't not good practise). Anyways I want a little html-part above all the code which outputs an error message. This message I want to change in every $_POST validation function.
Example:
if($ERR) {
echo '<div class="error-message">'.$ERR.'</div>';
}
Now my functions are following in the same file.
if(isset($_POST['test']) {
$ERR = 'Error!';
}
if(isset($_POST['test2'] {
$ERR = 'Error 2!';
}
But that doesn't work. I think there's a huge missunderstanding and i'm ashamed.
Can you help me?
I didnt catch your question but maybe this is your answer:
<body>
<p id="error_message">
<?php if(isset($ERR)){echo $ERR;} ?>
</p>
</body>
and I suggest you to learn how to work with sessions.
and you should know that $_Post will be empty on each refresh or F5
You can do put the errors in array make them dynamic.
<?php
$error = array();
if (!isset($_POST["test"]) || empty($_POST["test"])) {
$error['test'] = "test Field is required";
} else if (!isset($_POST["test1"]) || empty($_POST["test1"])) {
$error['test1'] = "test Field is required";
}else{
//do something else
}
?>
You can also use switch statement instead of elseif which is neater.

Display a message using msg in PHP

I have to redirect a to a page and say x already exist.
I am doing some think like this:
header('location:newcategory.php'?msg=category exists);
I would prefer to do this from PHP, rather than in JavaScript.
On the page doing the redirecting:
header("Location: newcategory.php?msg=" . urlencode('category exists'));
On the newcategory.php page:
echo $_GET['msg'];
header("Location: :newcategory.php?msg=category exists&var=".$x);
in the newcategory.php add this
if(msg == "category exists")
{
echo $var." already exists";
}
It won't be good if you pass whole message in a GET parameter, as it would be probably vulnerable to some sort of XSS. The best way is to store collection of message and their identifiers and produce message on the fly. For example you could have an array:
$messages = array(
'exists' => 'category %s exists',
'failed' => 'query %s failed'
);
And then pass only message identifier in an URL, optional is parameter defining more clearly what happened:
header("Location: newcategory.php?msg=exists&id=2");
In target page you could write something like that:
$msg = '';
switch($_GET['msg'])
{
case 'exists':
{
$msg = sprintf($messages[$_GET['msg']], intval($_GET['id']));
break;
}
}
echo $msg;
It could be also wrapped in some classes, but I'd shown you the idea, hope it helps.

Should I refactor this code?

The code is for a view debate page. The code is supposed to determine whether or not to show an add reply form to the viewing user.
If the user is logged in, and the user is not the creator of the debate, then check if the user already replied to the debate.
If the user did not already reply to the debate then show the form...
Otherwise, Check If the user wants to edit their already existing reply by looking in the url for the reply id
If any of these tests dont pass, Then I save the reason as an int and pass that to a switch statement in the view.
The logic seems easy enough, but my code seems a little sloppy.
Here's the code.. (using Kohana V2.3.4)
public function view($id = 0)
{
$debate = ORM::factory('debate')->with('user')->with('category')->find($id);
if ($debate->loaded == FALSE)
{
url::redirect();
}
// series of tests to show an add reply form
if ($this->logged_in)
{
// is the viewer the creator?
if ($this->user->id != $debate->user->id)
{
// has the user already replied?
if (ORM::factory('reply')
->where(array('debate_id' => $id, 'user_id' => $this->user->id))
->count_all() == 0)
{
$form = $errors = array
(
'body' => '',
'choice_id' => '',
'add' => ''
);
if ($post = $this->input->post())
{
$reply = ORM::factory('reply');
// validate and insert the reply
if ($reply->add($post, TRUE))
{
url::redirect(url::current());
}
$form = arr::overwrite($form, $post->as_array());
$errors = arr::overwrite($errors, $post->errors('reply_errors'));
}
}
// editing a reply?
else if (($rid = (int) $this->input->get('edit'))
AND ($reply = ORM::factory('reply')
->where(array('debate_id' => $id, 'user_id' => $this->user->id))
->find($rid)))
{
$form = $errors = array
(
'body' => '',
'choice_id' => '',
'add' => ''
);
// autocomplete the form
$form = arr::overwrite($form, $reply->as_array());
if ($post = $this->input->post())
{
// validate and insert the reply
if ($reply->edit($post, TRUE))
{
url::redirect(url::current());
}
$form = arr::overwrite($form, $post->as_array());
$errors = arr::overwrite($errors, $post->errors('reply_errors'));
}
}
else
{
// user already replied
$reason = 3;
}
}
else
{
// user started the debate
$reason = 2;
}
}
else
{
// user is not logged in.
$reason = 1;
}
$limits = Kohana::config('app/debate.limits');
$page = (int) $this->input->get('page', 1);
$offset = ($page > 0) ? ($page - 1) * $limits['replies'] : 0;
$replies = ORM::factory('reply')->with('user')->with('choice')->where('replies.debate_id', $id);
$this->template->title = $debate->topic;
$this->template->debate = $debate;
$this->template->body = View::factory('debate/view')
->set('debate', $debate)
->set('replies', $replies->find_all($limits['replies'], $offset))
->set('pagination', Pagination::factory(array
(
'style' => 'digg',
'items_per_page' => $limits['replies'],
'query_string' => 'page',
'auto_hide' => TRUE,
'total_items' => $total = $replies->count_last_query()
))
)
->set('total', $total);
// are we showing the add reply form?
if (isset($form, $errors))
{
$this->template->body->add_reply_form = View::factory('reply/add_reply_form')
->set('debate', $debate)
->set('form', $form)
->set('errors', $errors);
}
else
{
$this->template->body->reason = $reason;
}
}
Heres the view, theres some logic in here that determines what message to show the user.
<!-- Add Reply Form -->
<?php if (isset($add_reply_form)): ?>
<?php echo $add_reply_form; ?>
<?php else: ?>
<?php
switch ($reason)
{
case 1 :
// not logged in, show a message
$message = 'Add your ' . html::anchor('login?url=' . url::current(TRUE), '<b>vote</b>') . ' to this discussion';
break;
case 2 :
// started the debate. dont show a message for that.
$message = NULL;
break;
case 3:
// already replied, show a message
$message = 'You have already replied to this debate';
break;
default:
// unknown reason. dont show a message
$message = NULL;
break;
}
?>
<?php echo app::show_message($message, 'h2'); ?>
<?php endif; ?>
<!-- End Add Reply Form -->
Should I refactor the add reply logic into another function or something.... It all works, it just seems real sloppy.
Thanks
Edit: I took all answers into consideration. Since I wasn't adding anything new at the moment and had time to kill, I chose to refactor the code. After a little thought, a better solution popped out to me. The whole process took me about 30 minutes, and I would say it was worth it. Thanks to all for your answers
Yes, refactor. Remove the PHP and use a real language. ;)
Seriously though, do refactor - avoid nesting if statements so deeply (doing so obfuscates logic & makes testing harder) and chunk monolithic sections into separate functions/methods.
No. If you've got one more line of code to write elsewhere on this project, spend your time on that instead.
As is often the case, there will be a ton of different ways to solve the same problem your code is solving. But if you've already solved the problem then take note of what you've learnt here and move on. If this code does turn out to be a weak link later on in development, then fine; you've got proof and a concrete validation that it should be re-factored. Until then you're wasting time that could be spent pushing the project forward by re-inventing your re-invention of the wheel.
I'd say Yes. Refactor it, measure the time it takes you, then when all done assess the improvement. How much time did it take? Was it worth it? So refactor it as an experiment. And please let us know your results. Bottom line: was it worth refactoring?
avoid nested if statement :)
Yes, refactor. If you run a cyclomatic complexity analysis against this code, it would probably return a pretty high number (bad). Elaborate case/switch statements, nested if's all contribute to a higher score.
A future developer who may need to work with this codebase would potentially run a cyclomatic complexity analysis before diving in, and probably estimate that there is relatively high risk/complexity in dealing with this codebase.

Categories