How can I reduce lines of code in PHP? [closed] - php

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am a web developer and I write code in PHP/Laravel framework. I've been tying to follow best practice for writing code and I know it's a good practice to write 15-20 lines of code in functions and maximum 200 lines of code in Classes. But every time I end up writing minimum 40-50 lines in a function. for example here the code snippet which I wrote to get details of client and assigned users.
public function preMessageSend($client, $assigned)
{
$ticket_number = $client->ticket_number;
$title = $client->title;
$department = $client->department;
$priority = $client->priority;
if ($client->first_name !== null || $client->first_name !== '') {
$client_name = $client->first_name." ".$client->last_name;
} else {
$client_name = $client->username;
}
if ($client->email !== '' || $client->email !== null) {
$client_email = $client->email;
} else {
$client->email = 'Not available';
}
if($client->mobile !== null || $client->mobile !== '') {
$client_mobile = $client->code."".$client->mobile;
} else {
$client_mobile = 'Not available';
}
if($assigned != null) {
if ($assigned->first_name !== null || $assigned->first_name !== '') {
$assigned_name = $assigned->first_name." ".$assigned->last_name;
} else {
$assigned_name = $assigned->username;
}
if ($assigned->email !== '' || $assigned->email !== null) {
$assigned_email = $assigned->email;
} else {
$assigned->email = 'Not available';
}
if($assigned->mobile !== null || $assigned->mobile !== '') {
$assigned_mobile = $assigned->code."".$assigned->mobile;
} else {
$assigned_mobile = 'Not available';
}
if ($assigned->address !== null || $assigned->address !== '') {
$assigned_address = $assigned->address;
} else {
$assigned_address = 'Not available';
}
$this->sendMessageWithAssigned($ticket_number, $title, $department, $priority, $client_name, $client_email, $client_mobile, $assigned_name, $assigned_email, $assigned_mobile, $assigned_address);
} else {
$this->sendMessageWithoutAssigned($ticket_number, $title, $department, $priority, $client_name, $client_email, $client_mobile);
}
Please tell me how can I reduce the loc in my class and functions and what are the best practices to avoid writing such long functions.
TIA

First of all, null and '' is true for empty() so you could do:
if (!empty($client->first_name)) { // if not empty
$client_name = $client->first_name." ".$client->last_name;
} else {
$client_name = $client->username;
}
Then you could also use the ternary operator:
$client_name = !empty($client->first_name) ? $client->first_name." ".$client->last_name : $client->username;
Then for some statements there is also the or statement available:
$client_email = $client->email or 'Not available';
$client_mobile = $client->code . $client->mobile or 'Not available';
$assigned_address = $assigned->address or 'Not available';
These or statements are only equal to:
if(!empty($assigned->address)){
$assigned_address = $assigned->address;
} else {
$assigned_address = 'Not available';
}
// Or the equivalent ternary
$assigned_address = !empty($assigned->address) ? $assigned->address : 'Not available';
And what I mean for "some" is that:
$client->first_name = null;
$client->last_name = null;
echo empty($client->first_name." ".$client->last_name); // false
echo isset($client->first_name." ".$client->last_name); // true
is not empty even if both variables are null, due to the " " space which would make it isset()
Now be careful with those or statements because !empty() does not always give the opposite results as isset() where isset([]) is true and where empty([]) is also true.

Instead of
if ($client->first_name !== null || $client->first_name !== '') {
$client_name = $client->first_name." ".$client->last_name;
} else {
$client_name = $client->username;
}
You could do:
$client_name = ($client->first_name !== null || $client->first_name !== '') ? $client->first_name." ".$client->last_name : $client->username;

As others already suggested, you can use empty() instead of the != null and != '' checks. Furthermore, you could omit the else part in most statements, e.g.:
$assigned_name = $assigned->username;
if (!empty($assigned->first_name)) {
$assigned_name = $assigned->first_name." ".$assigned->last_name;
}
This sets $assigned_name to your former else value by default and if the condition is met $assigned_name gets overwritten. I don't recommend using ternary operator because it's not that readable IMO.
I wouldn't worry too much about lines of code anyway as long as the code is readable and efficient.

Related

Using empty() to adjust output with multiple variables

I have two primary variables that are composed of strings and other variables. I want the two primary variables only to be echo'ed if all the variables that they are comprised of have data.
The two primary variables are $introduction and colortxt.
$introduction is comprised of $finalvehicle3, $bodystyle, $mileage, and $hi.
$colortxt is comprised of $model, $exterior, and $interiorspec.
If any of the secondary variables are empty, I don't want the primary variable to be displayed.
Below is the code I have created that doesn't seem to be working. I have been using empty().
My PHP:
<?php
$finalvehicle3 = "Toyota Camry";
$bodystyle = "sedan";
$mileage = "30,000";
$hi = null;
$model = "Camry";
$exterior = "red";
$interiorspec = "black cloth";
if (empty([$finalvehicle3, $bodystyle, $mileage, $hi]) == true){
$introduction = "";
}
else {
$introduction = "I am pleased to present this ".$finalvehicle3." ".$bodystyle." with ".$mileage." miles.";
}
if (empty([$model, $exterior, $interiorspec]) == true){
$colortxt = "";
}
else {
$colortxt = "This ".$model." is finished in ".$exterior." with a ".$interiorspec. " interior.";
}
echo "<textarea name='' id='' style='width: 565px;' rows='8' cols='60'>";
echo $introduction." ".$colortxt;
echo "</textarea>";
echo "<br><br>";
?>
In this case $introduction should not be displayed as $hi = null
I can't get empty([$finalvehicle3, $bodystyle, $mileage, $hi]) to work.
I was able to use:
if (empty($hi)
|| empty($finalvehicle3)
|| empty($bodystyle)
|| empty($mileage)){
$introduction = "";
}
else {
$introduction = "I am pleased to present this ".$finalvehicle3." ".$bodystyle."
with ".$mileage." miles.";
}
Will that not work?
Check if both variables are not empty echo them out:
if (!empty($introduction) && !empty($colortxt)) {
echo $introduction." ".$colortxt;
}
As a side, while coding style has personal preference, where you set these variables seems awkward as you set them to empty based on a condition, but logically (my logical at least) is to instead preset them to empty and add data if the data exists.
INSTEAD of your code here:
if (empty([$finalvehicle3, $bodystyle, $mileage, $hi]) == true){
$introduction = "";
}
else {
$introduction = "I am pleased to present this ".$finalvehicle3." ".$bodystyle." with ".$mileage." miles.";
}
if (empty([$model, $exterior, $interiorspec]) == true){
$colortxt = "";
}
else {
$colortxt = "This ".$model." is finished in ".$exterior." with a ".$interiorspec. " interior.";
}
Do this:
$introduction = "";
$colortxt = "";
if (!empty([$finalvehicle3, $bodystyle, $mileage, $hi]) == true) {
$introduction = "I am pleased to present this ".$finalvehicle3." ".$bodystyle." with ".$mileage." miles.";
}
if (!empty([$model, $exterior, $interiorspec]) == true) {
$colortxt = "This ".$model." is finished in ".$exterior." with a ".$interiorspec. " interior.";
}
Just looks cleaner to me :)
I'd also not create a new array to check multiple variables, and would do:
if (
!empty($finalvehicle3)
&& !empty($bodystyle)
&& !empty($mileage
&& !empty($hi)
) {
To clarify (not intended to take away from the other answers); only isset() can accept multiple comma-separated values, and not empty().
The manuals state:
on empty():
bool empty ( mixed $var )
on isset()
bool isset ( mixed $var [, mixed $... ] )
Therefore you need to separate and check if each value is empty.
I.e.:
if(empty($var1)) && empty($var2)){}
Or using the || (OR) logical operator depending on what you want to check for; if any or all are empty.
http://php.net/manual/en/language.operators.logical.php
Note:
What you used here:
if (empty([$finalvehicle3, $bodystyle, $mileage, $hi]) == true)
theoretically would be a "false positive".
If anything, you will need to use the == true in a separate statement.
I.e.:
if(empty($var1)) && empty($var2) && $x_var == true){}
However, the first 2 would need the ! negation operator since you're checking if something is true.
I.e.:
if(!empty($var1)) && !empty($var2) && $x_var == true){}

php i need null to be null, zero to be zero

my table field status is NULL[default], or it is 0, or 1. then i assign to PHP var $status. when value is NULL i want to display no icon, when value is 0, display a gray check image, when value is 1, display a green check image.
trouble is, NULL value shows a gray check image, 0 does not show a check image. somehow NULL and 0 are alike but only in one direction. what i mean is, regardless of how i conditionally test if var is null, not null, null but not zero, they get interpreted wrongly. it is confusing. there must be a simple straight foward way to keep NULL and 0 separate and distinct. i grab the value:
$status = $Card['status']; //from above array.
if ($status == 1) {
$status = '1';
} else if ($status == 0) {
$status = '0';
} else if ($status === NULL) {
$status = 'NULL';
}
then to display the images either gray, green, or none at all i am trying this:
if ($status == '1') {
echo "<img src='../images/status_check_green.png' />";
} else if ($status == '0') {
echo "<img src='../images/porc_check_gray.png' />";
} else if ($status == 'NULL') {
echo "<img src='' />";
}
}
i know i do not need the '' around the values, but i am trying to literalize everything to force valid comparisons. likely no need for someone to try unraveling my code; but to elucidate how to keep NULL and 0 separate. it's like i am missing something fundamental here. btw, when i stuff a js var with the PHP var, it gets the correct value; they just don't follow the comparison like i need them to.
ideas?
HI your issue is procedure order or not type checking the 0 ( depending if you want to catch false )
if ($status == 1) {
$status = '1';
} else if ($status == 0) {
$status = '0'; //<--- this runs on null because (null == 0) is true
} else if ($status === NULL) {
$status = 'NULL'; //<--- this block is un-reachable
}
Because your not type checking with === of 0 null will return true for that condition.
See this sandbox with and example using $status = null;
http://sandbox.onlinephpfunctions.com/code/1f3dd9d83d0026aa0f682b61bed2ba858ae285aa
Outputs:
'0'
If you change it to this
if ($status == 1) {
$status = '1';
} else if ($status === 0) {
$status = '0';
} else if ($status === NULL) {
$status = 'NULL';
}
As you can see here using the same setting for $status
http://sandbox.onlinephpfunctions.com/code/d86b0c60c06338d2d6ee1c1fa9d3fa7e08a22663
Outputs
'NULL'
The other way to fix it would be to switch them so the more specific one is first.
if ($status == 1) {
$status = '1';
} else if ($status === NULL) {
$status = 'NULL';
} else if ($status == 0) { //I would prefer if(!$status){ but I'm lazy
$status = '0';
}
Then 0 would catch false as well as 0 but not null as the block above it will catch it first. You can see this last one here
http://sandbox.onlinephpfunctions.com/code/3028f5826dcede29b14dd8cfc03618ea5830c12c
Which also outputs
'NULL'
Cheers!

PHP ternary operators

I have written a ternary function in PHP and it seems to work, although I am not sure if it is correct, can someone take a look and tell me if it is right?
I have added the ternary and the if of what should be happening.
//Foreach Loop
foreach ($post as $item) {
//If of what should occur
if ($passed == true) {
if (is_numeric($item)) {
if ($item > 0) {
$passed = true;
}
else {
$passed = false;
}
}
else {
if ($item != "") {
$passed = true;
}
else {
$passed = false;
}
}
//Ternary operator.
$passed = (is_numeric($item) ? ($item > 0 ? true : false) : ($item != "" ? true : false));
}
else {
return $passed;
}
}
please have a look on corrected code
$passed = (is_numeric($item))?($item>0?true:false):($item !="" ? true:false);
Honestly I do not really understand why you do not use a
if (!empty($item)) {
$passed = true;
} else {
return false;
}
In any case, ternaries are less readable than if /elseif / else, they are also slower (note that it is not an universal truth but a more general use case thing http://fabien.potencier.org/the-php-ternary-operator-fast-or-not.html).
I would recommend, if you really need all these if and elses to keep them rather than using ternaries (for readability's purpose).

make an ifnot statement and if statement in one line

I'm trying to make an if statement with 2 conditions. One that checks if one variable is NOT present & does NOT matches the word "good2go" and the other that checks to make sure "body" variable is present. I'm trying to trip the error message here. Here is what I have and what I've tried, and none of it seems to work.
if (stripos($_POST['check'], 'good2go') == FALSE && $_POST['body']) {
$error = true; }
if (!$_POST['check'] == 'good2go' && $_POST['body']) {
$error = true; }
if (!stripos($_POST['check'], 'good2go') && $_POST['body']) {
$error = true; }
if ((!stripos($_POST['check'], 'good2go')) && $_POST['body']) {
$error = true; }
How do I get this to work?
here's the entire code of contact_us.php this has the validation code and the email code.
$error = false;
if (isset($_GET['action']) && ($_GET['action'] == 'send')) {
// Winnie the pooh check
//$t = tep_db_prepare_input($_POST['verify']);
if (!isset($_POST['check']) && !$_POST['check']=='good2go' && isset($_POST['body'])) {
$error = true;
} else { // Winnie the pooh Check
$name = tep_db_prepare_input($_POST['name']);
$email_address = tep_db_prepare_input($_POST['email']);
//IP recorder start
$ipaddress = $_SERVER["REMOTE_ADDR"];
$ip = "\n\nIP: " . $ipaddress;
$content = "\n\nName: ".$name."\n\nComments: ".$_POST['enquiry'];
$product = tep_db_prepare_input($_POST['product']);
if ($product) {
$product_text = "\n\nProduct Interest: ".$product; }
$content_ip = $content . $product_text. $ip;
$enquiry = tep_db_prepare_input($content_ip);
//IP recorder end
}
// BOF: Remove blank emails
// if (tep_validate_email($email_address)) {
// tep_mail(STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, EMAIL_SUBJECT, $enquiry, $name, $email_address);
// tep_redirect(tep_href_link(FILENAME_CONTACT_US, 'action=success'));
// } else {
// $error = true;
// $messageStack->add('contact', ENTRY_EMAIL_ADDRESS_CHECK_ERROR);
if (! tep_validate_email($email_address)) {
$error = true;
$messageStack->add('contact', ENTRY_EMAIL_ADDRESS_CHECK_ERROR);
}
if ($enquiry == '') {
$error = true;
$messageStack->add('contact', ENTRY_EMAIL_CONTENT_CHECK_ERROR);
}
if ($error == false) {
tep_mail(STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, EMAIL_SUBJECT, $enquiry, $name, $email_address);
tep_redirect(tep_href_link(FILENAME_CONTACT_US, 'action=success'));
// EOF: Remove blank emails
}
}
Solution to your updated problem:
if (!isset($_POST['check']) || !$_POST['check']=='good2go' || !isset($_POST['body'])) {
$error = true;
}
The reason for the pipes vs ampersands is that you want to throw an error if ANY of the fields has issue. Also, you want to check if body is NOT set vs IS set. Glad this worked out for you!
and the other that checks to make sure "body" variable is not present.
if(stripos($_POST['check'], "good2go") !== false && !isset($_POST['body'])){
//code here
}
According to PHP docs regarding the stripos function:
This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.
So you need to change the first line to:
// Doing stripos checks you MUST use === (not ==)
if (stripos($_POST['check'], 'good2go') !== FALSE && $_POST['body']) {
$error = true; }
And to check if there is no $_POST['body'] you can change the above to:
if (stripos($_POST['check'], 'good2go') !== FALSE && (!isset($_POST['body'])) {
-- Update --
According to your comment, you need $_POST['check'] to equal 'good2go', then you shouldn't be using stripos as it will check for the existence of good2go regardless if it's exactly equal, or part of a string; 'wow this hamburger is good2go'.
So I would change the conditional to:
if (((isset($_POST['body'])) && (strlen($_POST['body']) > 0)) && ((!isset($_POST['check'])) || ($_POST['check'] !== 'good2go'))) {
// Post body has a value and Post check DOES NOT equal good2go, someone is hax0rin!
}
You may want to read up on Cross-site request forgery as it seems right inline with what you are working on.
One that checks if one variable is present & matches the word "good2go"
isset($_POST['check']) AND $_POST['check'] == 'good2go'
and the other that checks to make sure "body" variable is not present.
!isset($_POST['body'])
so, just put them together
if (isset($_POST['check']) AND $_POST['check'] == 'good2go' AND !isset($_POST['body'])) {
$error = true;
}
try this:
if(!empty($_POST['check']) && $_POST['check']=='good2go' && empty($_POST['body'])) { $error=true; }
Consider using empty instead of isset if your $_POST['body'] can be present with an empty value.
No need for all those unneeded functions. What you are trying to achieve is:
if (isset($_POST['check']) && $_POST['check']=='good2go' && !isset($_POST['body']) {
// your code
}
However, As per the title of the question: Use a ternary statement. Syntax is as such
$var = <condition> ? <true> : <false>;

I need a more efficient way of checking if multiple $_POST parameters isset

I have these variables, and I need to check if all of them isset(). I feel there has to be a more efficient way of checking them rather than one at a time.
$jdmMethod = $_POST['jdmMethod'];
$cmdMethod = $_POST['cmdMethod'];
$vbsMethod = $_POST['vbsMethod'];
$blankPage = $_POST['blankPage'];
$facebook = $_POST['facebook'];
$tinychat = $_POST['tinychat'];
$runescape = $_POST['runescape'];
$fileUrl = escapeshellcmd($_POST['fileUrl']);
$redirectUrl = escapeshellcmd($_POST['redirectUrl']);
$fileName = escapeshellcmd($_POST['fileName']);
$appData = $_POST['appData'];
$tempData = $_POST['tempData'];
$userProfile = $_POST['userProfile'];
$userName = $_POST['userName'];
Try this
$allOk = true;
$checkVars = array('param', 'param2', …);
foreach($checkVars as $checkVar) {
if(!isset($_POST[$checkVar]) OR !$_POST[$checkVar]) {
$allOk = false;
// break; // if you wish to break the loop
}
}
if(!$allOk) {
// error handling here
}
I like to use a function like this:
// $k is the key
// $d is a default value if it's not set
// $filter is a call back function name for filtering
function check_post($k, $d = false, $filter = false){
$v = array_key_exists($_POST[$k]) ? $_POST[$k] : $d;
return $filter !== false ? call_user_func($filter,$v) : $v;
}
$keys = array("jdmMethod", array("fileUrl", "escapeshellcmd"));
$values = array();
foreach($keys as $k){
if(is_array($k)){
$values[$k[0]] = check_post($k[0],false,$k[1]);
}else{
$values[$k] = check_post($k[0]);
}
}
You could extend the keys array to contain a different default value for each post-value if you wish.
EDIT:
If you want to make sure all of these have a non-default value you could do something like:
if(sizeof(array_filter($values)) == sizeof($keys)){
// Not all of the values are set
}
Something like this:
$jdmMethod = isset($_POST['jdmMethod']) ? $_POST['jdmMethod'] : NULL;
It's Ternary Operator.
I think this should work (not tested, from memory)
function handleEmpty($a, $b) {
if ($b === null) {
return false;
} else {
return true;
}
array_reduce($_POST, "handleEmpty");
Not really. You could make a list of expected fields:
$expected = array(
'jdmMethod',
'cmdMethod',
'fileName'
); // etc...
... then loop those and make sure all the keys are in place.
$valid = true;
foreach ($expected as $ex) {
if (!array_key_exists($ex, $_POST)) {
$valid = false;
break;
}
$_POST[$ex] = sanitize($_POST[$ex]);
}
if (!$valid) {
// handle the problem
}
If you can develop a generic sanitize function, that will help - you can just sanitize each as you loop.
Another thing I like to use is function that gives a default as it sanitizes.
function checkParam($key = false, $default = null, $type = false) {
if ($key === false)
return $default;
$found_option = null;
if (array_key_exists($key,$_REQUEST))
$found_option = $_REQUEST[$key];
if (is_null($found_option))
$found_option = $default;
if ($type !== false) {
if ($type == 'string' && !is_string($found_option))
return $default;
if ($type == 'numeric' && !is_numeric($found_option))
return $default;
if ($type == 'object' && !is_object($found_option))
return $default;
if ($type == 'array' && !is_array($found_option))
return $default;
}
return sanitize($found_option);
}
When a default is possible, you'd not want to do a loop, but rather check for each independently:
$facebook = checkParam('facebook', 'no-facebook', 'string);
It is not the answer you are looking for, but no.
You can create an array an loop through that array to check for a value, but it doesn't get any better than that.
Example:
$postValues = array("appData","tempData",... etc);
foreach($postedValues as $postedValue){
if(isset($_POST[$postedValue])){
...
}
}

Categories