跳至内容

PHP 编程/编码规范

来自维基教科书,开放世界中的开放书籍

缩进和行长

[编辑 | 编辑源代码]

使用一个制表符缩进(不要使用空格!好的 IDE 可以将制表符转换为伪空格 - 2、4 等)。如果你使用 Emacs 编辑代码,你应该将 indent-tabs-mode 设置为 nil。建议你在大约 75-85 个字符处换行。关于换行最佳方式没有标准规则;请使用你的判断。这适用于所有文件类型:PHP、HTML、CSS、JavaScript 等。

缩进规则应该应用于将由其他人编辑的源文件。生成 HTML 代码的视觉效果不应该在编写生成 HTML 代码时考虑。

HTML 标准

[编辑 | 编辑源代码]

截至 2006 年 9 月,我们文档上的 DocType 将为 XHTML 1.0 Transitional。因此,应始终使用符合 XHTML 1.0 标准的兼容 HTML。例外情况应仅是例外情况。可以在 DevGuru 上找到 XHTML 元素的良好参考。

此外,为了确保 Internet Explorer 6 正确执行盒子模型,我们必须在所有页面上使用以下 DocType。只应使用此文档类型。在其之前不应放置任何其他信息。

示例 DocType
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


元素用法

[编辑 | 编辑源代码]

尽可能使用标准 HTML 元素。应始终避免使用 "Div Soup"。"Div Soup" 指的是在不需要的情况下使用 div(或 span)的 HTML。例如,如果你需要使一个词加粗,不要使用<span>标签并应用样式。相反,使用<strong>标签。

表格仅应在需要将数据以列形式显示时使用。永远不要使用单格表格。

一个常见的例外是需要使用<div>标签代替<p>标签,当标签的内容将是其他块级元素(如<ul>.

示例 HTML
<div class="article">
    <h4>this is the headline</h4>
    <p>This is the body with an <strong>important word</strong>.</p>
    <small>Posted 2 days ago</small>
</div>


CSS 标准

[编辑 | 编辑源代码]

应避免使用内联样式!

CSS 文件中的样式应尽可能具体。应该始终尝试避免使用裸类名。如果你正在为包含一个容器的对象设置样式,你的样式应该引用容器以及正在设置样式的元素。CSS 中的样式越冗长,你就越不可能意外地搞乱其他页面上的其他元素。

为元素设置样式的最有效方法是为容器内的该类型元素设置样式。如果只有一个元素需要以特殊方式设置样式,则应为其分配一个 ID 并使用该 ID 设置样式,最好是使用一个容器。

以下是我们侧边栏中的一些 HTML 代码

示例文章 HTML
<div id="sidebar">

    <ul class="blue" id="categories">
        <label><a href="/categories/">Categories</a></label>
        <li class="current"><a href="/categories/Computer/39.html">Computer</a></li>
        <li><a href="/categories/Electronics/142.html">Electronics</a></li>
        <li><a href="/categories/Gaming-Toys/186.html">Gaming & Toys</a></li>
        <li><a href="/categories/Office-Supplies/182.html">Office & Supplies</a></li>
        <li><a href="/categories/DVDs-Music-Books/178.html">DVDs, Music, Books</a></li>
        <li><a href="/categories/Clothing-Accessories/202.html">Clothing & Accessories</a></li>
        <li><a href="/categories/Home-Garden/196.html">Home & Garden</a></li>
        <li><a href="/categories/Everything-Else/231.html">Everything Else</a></li>
        <li><a href="/categories/Store-Events/40.html">Store Events</a></li>
        <li><a href="http://dealnews.com/coupons/">Coupons</a></li>
        <li><a href="http://dealnews.com/deals/The-new-dealnews-Gift-Finder-sort-by-price-/101164.html">Gift Ideas</a></li>
    </ul>

    <ul class="gray">
        <label>Stores</label>
        <li><a href="/online-stores/Amazon-com/313/">Amazon.com</a></li>
        <li><a href="/online-stores/Buy-com/233/">Buy.com</a></li>
        <li><a href="/online-stores/Circuit-City-com/296/">CircuitCity.com</a></li>
        <li><a href="/online-stores/Dell-Home/638/">Dell Home</a></li>
        <li><a href="/online-stores/Best-Buy-com/560/">BestBuy.com</a></li>
        <li><a href="/online-stores/Comp-USA-com/595/">CompUSA.com</a></li>
        <li><a href="/online-stores/Dell-Small-Business/604/">Dell Small Business</a></li>
        <li><a href="/online-stores/Newegg-com/504/">Newegg.com</a></li>
        <li><a href="/online-stores/Meritline/303/">Meritline</a></li>
    </ul>

</div>


以下是如何为这些元素设置样式的一小部分。

示例 CSS
#sidebar ul {
    list-style: none;
    margin: 0 0 15px 0;
    padding: 0 0 4px 0;
}

#sidebar ul label {
    color: White;
    display: block;
    font-weight: bold;
    font-size: 100%;
    margin: 0 0 4px 0;
    padding: 6px 8px 4px 10px;
}
    
#sidebar ul label a, #sidebar ul label a:visited {
    color: White;
    text-decoration: none;
    display: block;
}

#sidebar ul li {
    font-size: 95%;
    margin: 0 0 4px 0;
    padding: 2px 8px 2px 12px;
}
    
#sidebar ul li a {
    display: block;
    color: Black;
    text-decoration: none;
}

#sidebar ul.gray {
    background: #DDDDE2 url('http://images.dealnews.com/dealnews/backgrounds/sidebar/footer_light_gray.png') no-repeat 0 100%;
}

#sidebar ul.gray label {
    color: White;
    background: #75758A url('http://images.dealnews.com/dealnews/backgrounds/sidebar/header_dark_gray.png') no-repeat 0 0;
}

#sidebar ul.blue {
    background: #EBEBFA url('http://images.dealnews.com/dealnews/backgrounds/sidebar/footer_light_blue.png') no-repeat 0 100%;
}

#sidebar ul.blue label {
    color: White;
    background: #2E2E6B url('http://images.dealnews.com/dealnews/backgrounds/sidebar/header_dark_blue.png') no-repeat 0 0;
}

#sidebar #categories li.current {
    color: #FF9A00;
    font-weight: bold;
}


这种冗长确保不会意外地为其他元素设置样式。

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
require_once('functions/base_url.php');
if (session_status() == PHP_SESSION_NONE) {
	session_start();
}

//  database connect file check
!file_exists('functions/Connect_db.php') ? header('Location: ' . $base_url . 'functions/databaseSettings.php') : '';
require_once('functions/Connect_db.php');
require_once('functions/SqlQuery.php');
require_once('functions/CheckerFn.php');
require_once('currencyAndIcons.php');
require_once('SendMail.php');

class Action
{
	public $db;
	public $checker;
	public $theDay;
	public function __construct()
	{
		$this->db = new SqlQuery;
		$this->theDay = date('Y-m-d');
		$this->checker = new CheckerFn;
	}


	// company settings manage add, update
	public function manageSettings()
	{
		$logo = '';
		$companyName = $this->checker->c_valid($_POST['companyName']);
		$userCurrency = $this->checker->c_valid($_POST['userCurrency']);
		$smtpHost = $this->checker->c_valid($_POST['smtpHost']);
		$smtpPort = $this->checker->c_valid($_POST['smtpPort']);
		$smtpAuth = $this->checker->c_valid($_POST['smtpAuth']);
		$contactEmail = $this->checker->c_valid($_POST['contactEmail']);
		$emailPassword = $this->checker->c_valid($_POST['emailPassword']);
		$startingDate = $this->checker->c_valid($_POST['startingDate']);
		if (!empty($_FILES['logo']['name'])) {
			$logo_array = $_FILES['logo'];
			$name = explode('.', $logo_array['name']);
			$logo = md5(rand() . time()) . '.' . end($name);
		} else {
			$logo = $this->checker->c_valid($_POST['preLogo']);
		}

		$data = [
			'companyName' => $companyName,
			'companyLogo' => $logo,
			'userCurrency' => $userCurrency,
			'smtpHost' => $smtpHost,
			'smtpPort' => $smtpPort,
			'smtpAuth' => $smtpAuth,
			'contactEmail' => $contactEmail,
			'emailPassword' => $emailPassword,
			'startingDate' => $startingDate
		];

		// check smtp connection
		$smtpCheck = fsockopen($smtpHost, $smtpPort, $errno, $errstr, 6);
		if (is_bool($smtpCheck) && $smtpCheck === false) {
			$_SESSION['smtpInvalid'] = $data;
			return $this->checker->redirect('settings');
		}

		if (isset($_SESSION['atFirstSettings'])) {
			$insertSuccess = $this->db->insertAction('company_settings', $data);
			if (isset($insertSuccess)) {
				unset($_SESSION['atFirstSettings']);
				move_uploaded_file($logo_array['tmp_name'], 'img/' . $logo);
				return $this->checker->redirect('registerPartner');
			}
		} elseif (isset($_POST['settingsEdit'])) {
			$id = $this->checker->c_valid($_POST['settingsEdit']);
			$success = $this->db->updateAction('company_settings', $data, ['id' => $id]);
			if (isset($success)) {
				if ($logo !== $_POST['preLogo']) {
					$_SESSION['logo'] = $logo;
					unlink('img/' . $_POST['preLogo']);
					move_uploaded_file($logo_array['tmp_name'], 'img/' . $logo);
				}
				$_SESSION['settingsUpdated'] = 1;
				$_SESSION['currency'] = currency_symbol($userCurrency);
				return $this->checker->redirect('manageSettings');
			}

		}
	}

	// user account recovery method if user forgot user account informetion
	public function getAccount($getBy)
	{

		// user account information get by email
		$getAccount;
		if ($getBy === '010') {
			$email = $this->checker->c_valid($_POST['email']);
			if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
				$emailExist = $this->db->get_row("fms_admin", ['email' => $email]);
				if (isset($emailExist) && $emailExist) {
					$getAccount = $emailExist;
				} else {
					$_SESSION['doesNotExist_e'] = $email;
					return $this->checker->redirect('forgotPassword');
				}
			} else {
				$_SESSION['invalidEmail'] = $email;
				return $this->checker->redirect('forgotPassword');
			}
		}


		// to get user account information by user full name & birthday
		if ($getBy === '101') {
			$fullName = $this->checker->c_valid($_POST['fn']) . ' ' . $this->checker->c_valid($_POST['ln']);
			$birthday = $this->checker->c_valid($_POST['birthday']);
			$userExist = $this->db->get_row('fms_admin', ['fullName' => $fullName, 'birthday' => $birthday]);
			if (isset($userExist)) {
				$userExist = $getAccount;
			} else {
				$_SESSION['actionfaild'] = 1;
				return $this->checker->redirect('forgotPassword');
			}
		}


		// check user is exists
		if (isset($getAccount)) {
			$email = $getAccount['email'];
			$userName = $getAccount['userName'];
			$fullName = $getAccount['fullName'];
			$sec = json_decode($getAccount['userInfo_sc']); // secure informetion container
			$password = md5(sha1($userName . rand()));
			$sec_one = md5(sha1($password . rand()));
			$sec_two = md5(sha1($sec_one . rand()));
			$setLink = $this->checker->base_url() . 'resetPassword.php?' . $userName . '=' . $password . '&' . $sec_one . '=' . $sec_two;
			$getEmail = $this->db->get_row("company_settings");
			$accountInf = [$sec->userName_sc, $sec->password_sc];


			// this is mail data to send a mail
			$emailData = ['getEmail' => $getEmail, 'toMail' => $email, 'fullName' => $fullName, 'link' => $setLink, 'accountInf' => $accountInf];


			// mail sender class
			$emailClass = new SendMail;
			$sendResult = $emailClass->send_mail($emailData);

			// check, mail send is success
			if (isset($sendResult) && intval($sendResult) === 1) {
				$sec = $this->checker->secureInfoProcess($sec);
				$id = $getAccount['id'];
				array_push($sec, [$sec_one, $sec_two]);
				$upd = ['userInfo_sc' => json_encode($sec)];
				$edit = $this->db->updateAction('fms_admin', $upd, ['id' => $id]);
				if (isset($edit)) {
					$_SESSION['emailSend'] = $email;
					return $this->checker->redirect('login');
				} else {
					$_SESSION['actionfaild'] = 3;
					return $this->checker->redirect('forgotPassword');
				}
			} else {
				$_SESSION['actionfaild'] = 2;
				return $this->checker->redirect('forgotPassword');
			}
		}
	}


	// user account reset
	public function resetPassword($updateUser = null)
	{
		if (isset($_SESSION['userInformetion'])) {
			$info = $_SESSION['userInformetion'];
			$ridirectLink = $_SESSION['ridirect_l'];
			$protocol = isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : 'http';
			$ridirectLink = $protocol . '://' . $_SERVER['HTTP_HOST'] . $ridirectLink;

			if (empty($_POST['passworda']) || empty($_POST['passwordr'])) {
				$_SESSION['emptyField'] = 1;
				return header('Location: ' . $ridirectLink);
			} else {
				if ($_POST['passworda'] === $_POST['passwordr']) {
					$pas = $this->checker->c_valid($_POST['passworda']);
					$secure = json_decode($info['userInfo_sc']);
					$secure_od = $secure;
					$secure = $secure->oldPassword_sc;
					if (empty($secure)) {
						$password = $pas;
					} else {
						if (in_array($pas, $secure) || $pas === $secure_od->password_sc) {
							$_SESSION['old_p'] = 1;
							return header('Location: ' . $ridirectLink);
						} else {
							$password = $pas;
						}
					}
					if (isset($password)) {
						$getEmail = $this->db->get_row("company_settings");
						$email = !isset($updateUser) ? $info['email'] : $this->checker->c_valid($_POST['email']);
						$newPassword = $password;
						$fullName = !isset($updateUser) ? $info['fullName'] : $this->checker->c_valid($_POST['fn']) . ' ' . $this->checker->c_valid($_POST['ln']);
						$userName = !isset($updateUser) ? $secure_od->userName_sc : $updateUser;
						$accountInf = [$userName, $newPassword];
						$emailData = ['getEmail' => $getEmail, 'toMail' => $email, 'fullName' => $fullName, 'accountInf' => $accountInf];

						// mail sender class
						$emailClass = new SendMail;
						$sendResult = $emailClass->send_mail($emailData);

						if (isset($sendResult) && intval($sendResult) === 1) {
							$password = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]);
							$password_sc = $newPassword;
							$oldPassword_sc = $secure_od->oldPassword_sc;
							array_push($oldPassword_sc, $secure_od->password_sc);
							$new_userInfo_sc = ['userName_sc' => $userName, 'password_sc' => $password_sc, 'oldPassword_sc' => $oldPassword_sc];
							$upd = ['password' => $password, 'userInfo_sc' => json_encode($new_userInfo_sc)];

							unset($_SESSION['ridirect_l']);
							unset($_SESSION['userInformetion']);
							if (isset($updateUser)) {
								return $upd;
							} else {
								$passwordUpdate = $this->db->updateAction('fms_admin', $upd, ['id' => $info['id']]);
								if (isset($passwordUpdate)) {
									$_SESSION['resetSuccess'] = $email;
									return $this->checker->redirect('login');
								}
							}
						}
					}
				} else {
					$_SESSION['doesNot_m'] = 1;
					return header('Location: ' . $ridirectLink);
				}
			}
		}
	}

	// create user account
	public function createUserNamePassword($securAction = null)
	{
		if (isset($securAction) && $securAction === 8994723402 && !empty($_POST)) {
			$info = $_SESSION['userinfo'];
			$userName = $this->checker->c_valid($_POST['userName']);
			$password = $this->checker->c_valid($_POST['password']);
			$userInfo_sc = json_encode(array('userName_sc' => $userName, 'password_sc' => $password, 'oldPassword_sc' => []));
			if (ctype_alnum($userName)) {
				$email = $info['email'];
				$fullName = $info['fullName'];
				$accountInf = [$userName, $password];
				$getEmail = $this->db->get_row("company_settings");
				$emailData = ['getEmail' => $getEmail, 'toMail' => $email, 'fullName' => $fullName, 'accountInf' => $accountInf];

				// mail sender class
				$emailClass = new SendMail;
				$sendResult = $emailClass->send_mail($emailData);

				if (isset($sendResult) && intval($sendResult) === 1) {
					$userName = md5(sha1($userName));
					$password = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]);
					$upData = [
						'userName' => $userName,
						'password' => $password,
						'userInfo_sc' => $userInfo_sc
					];
					$success = $this->db->updateAction('fms_admin', $upData, ['id' => $info['id']]);
					if (isset($success)) {
						unset($_SESSION['userinfo']);
						$_SESSION['a_create_success'] = $email;
						return $this->checker->redirect('login');
					} else {
						return $this->checker->redirect('setUserNamePassword');
					}
				}
			}
		}
	}

	// user informetion add or eidt manager
	function manageUsers()
	{
		if (isset($_SESSION['ridirect_l'])) {
			$ridirectLink = $_SESSION['ridirect_l'];
			$protocol = isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : 'http';
			$ridirectLink = $protocol . '://' . $_SERVER['HTTP_HOST'] . $ridirectLink;
		}
		if (isset($_POST['fn']) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
			$fullName = $this->checker->c_valid($_POST['fn']) . ' ' . $this->checker->c_valid($_POST['ln']);
			$currency = isset($_POST['currency']) ? $_POST['currency'] : '';
			$percentage = $this->checker->c_valid($_POST['percentage']);
			$birthday = $this->checker->c_valid($_POST['birthday']);
			$email = $this->checker->c_valid($_POST['email']);
			$gender = $this->checker->c_valid($_POST['gender']);
			$userRoll = $this->checker->c_valid($_POST['userRoll']);

			$file_name = '';
			if (!empty($_FILES['img']['name'])) {
				$photo_array = $_FILES['img'];
				$name = explode('.', $photo_array['name']);
				$file_name = md5(rand() . time()) . '.' . end($name);
			}

			if (isset($_POST['register']) || isset($_POST['atFirstRegisterUser'])) {
				$userName = md5(sha1($email . rand()));
				$password = md5(sha1($email . rand() . $fullName));
				$setLink = $this->checker->base_url() . 'setUserNamePassword.php?' . $userName . '=' . $password;
				$getEmail = $this->db->get_row("company_settings");
				$emailData = ['getEmail' => $getEmail, 'toMail' => $email, 'fullName' => $fullName, 'link' => $setLink];
				$emailClass = new SendMail;
				$sendResult = $emailClass->send_mail($emailData);
				if (isset($sendResult) && intval($sendResult) === 1) {
					$insertD = ['fullName' => $fullName, 'email' => $email, 'userName' => $userName, 'password' => $password, 'userInfo_sc' => '', 'percentage' => $percentage, 'photo' => $file_name, 'birthday' => $birthday, 'gender' => $gender, 'userRoll' => $userRoll, 'a_date' => $this->theDay, 'u_date' => ''];
					$insertSuccess = $this->db->insertAction('fms_admin', $insertD);
					if (isset($insertSuccess)) {
						$_SESSION['install'] = 1;
						$_SESSION['registerSuccess'] = $email;
						move_uploaded_file($photo_array['tmp_name'], 'uploadFiles/userPhoto/' . $file_name);
						$page = isset($_POST['register']) ? 'userRegistration' : 'login';
						return $this->checker->redirect($page);
					} else {
						$_SESSION['sorry'] = 'action failde';
						return $this->checker->redirect('userRegistration');
					}
				} else {
					$exists_p = $this->db->get("fms_admin");
					if (isset($exists_p)) {
						return $this->checker->redirect('userRegistration');
					}
					return $this->checker->redirect('registerPartner');
				}
			}

			if (isset($_POST['editUserInfo'])) {
				$preEdit = $_SESSION['userInformetion'];
				$upFile = empty($_FILES['img']['name']) ? $preEdit['photo'] : $file_name;
				$upd = ['fullName' => $fullName, 'email' => $email, 'percentage' => $percentage, 'photo' => $upFile, 'birthday' => $birthday, 'gender' => $gender, 'userRoll' => $userRoll, 'u_date' => $this->theDay];

				if (isset($_POST['passworda']) && !password_verify($_POST['passworda'], $preEdit['password'])) {
					$userName = $this->checker->c_valid($_POST['userName']);
					$updatePass = $this->resetPassword($userName);
					if (is_array($updatePass) && !empty($updatePass)) {
						$resetSuccess = 1;
						$upd['userName'] = md5(sha1($userName));
						$upd['password'] = $updatePass['password'];
						$upd['userInfo_sc'] = $updatePass['userInfo_sc'];
					} else {
						return header('Location: ' . $ridirectLink);
					}
				} elseif (isset($_POST['userName'])) {
					$userName = $this->checker->c_valid($_POST['userName']);
					$upd['userName'] = md5(sha1($userName));
				}
				$id = $preEdit['id'];
				$edit = $this->db->updateAction('fms_admin', $upd, ['id' => $id]);
				if (isset($edit)) {
					$_SESSION['editSuccess'] = 1;
					isset($resetSuccess) ? $_SESSION['resetSuccess'] = $email : false;
					$user = $this->db->get_row('fms_admin', ['id' => $id]);
					unset($user['password']);
					unset($user['userName']);
					unset($user['userInfo_sc']);
					$_SESSION['userinfo']['id'] === $id ? $_SESSION['userinfo'] = $user : false;
					if ($upFile === $file_name) {
						move_uploaded_file($photo_array['tmp_name'], 'uploadFiles/userPhoto/' . $upFile);
						unlink('uploadFiles/userPhoto/' . $preEdit['photo']);
					}
					return $this->checker->redirect('users');
				} else {
					$_SESSION['editfaild'] = 1;
				}
			}
		} else {
			$_SESSION['invalidEmail'] = $_POST['email'];
			if (isset($_POST['editUserInfo'])) {
				return header('Location: ' . $ridirectLink);
			} else {
				return $this->checker->redirect('userRegistration');
			}
		}
	}

	// add user Earns
	public function cashInsert()
	{
		$source = $this->checker->c_valid($_POST['source']);
		$amount = $this->checker->c_valid($_POST['amount']);
		if (ctype_digit($amount)) {
			$id = $_SESSION['userinfo']['id'];
			$insertData = ['id' => $id, 'earnSource' => $source, 'amount' => $amount, 'currency' => '', 'ba_date' => $this->theDay, 'bu_date' => ''];
			$result = $this->db->insertAction('fms_bank', $insertData);
			if (isset($result)) {
				$_SESSION['success_ms'] = 1;
				return $this->checker->redirect('bankCash');
			}
		} else {
			$_SESSION['invalidAmount'] = $amount;
			return $this->checker->redirect('bankCash');
		}
	}

	// edit user Earns
	public function cashUpdate()
	{
		$source = $this->checker->c_valid($_POST['source']);
		$bankId = $this->checker->c_valid($_POST['updateId']);
		$amount = $this->checker->c_valid($_POST['amount']);
		if (!empty($bankId)) {
			$up_data = ['earnSource' => $source, 'amount' => $amount, 'bu_date' => $this->theDay];
			$result = $this->db->updateAction('fms_bank', $up_data, ['bankId' => $bankId]);
			if (isset($result)) {
				$_SESSION['info_message'] = 1;
				return $this->checker->redirect('cashDetails');
			}
		}
	}

	// Expense maange add or eidt
	public function manageExpense()
	{
		$amount = $this->checker->c_valid($_POST['amount']);

		if (isset($_SESSION['costInsert'])) {
			$memoData = [];
			$memoName = $_FILES['memo']['name'];
			$tmpName = $_FILES['memo']['tmp_name'];
			for ($i = 0; $i < count($memoName); $i++) {
				$memoName[$i];
				$tmpName[$i];
				if (!empty($memoName[$i])) {
					$name = explode('.', $memoName[$i]);
					$fileName = md5(rand() . $name[0] . time()) . '.' . end($name);
					$memoData[] = $fileName;
					move_uploaded_file($tmpName[$i], 'uploadFiles/memo/' . $fileName);
				} else {
					$memoData[] = '';
				}
			}
			$id = $_SESSION['userinfo']['id'];
			$costDetails = json_encode(['c_productName' => $_POST['costCn'], 'c_amount' => $_POST['costCa'], 'c_memo' => $memoData]);
			$insertData = ['id' => $id, 'cst_amount' => $amount, 'cst_currency' => '', 'cost_details' => $costDetails, 'cst_a_date' => $this->theDay, 'cst_u_date' => ''];
			$result = $this->db->insertAction('fms_cost', $insertData);
			if (isset($result)) {
				$_SESSION['info_message'] = 'submited';
				return $this->checker->redirect('costManage');
			}
		}

		if (isset($_SESSION['costEdit'])) {
			$memoData = [];
			$upId = $_SESSION['costEdit'];
			$memoName = $_FILES['memo']['name'];
			$tmpName = $_FILES['memo']['tmp_name'];
			$preEdit = $this->db->get_row('fms_cost', ['cst_id' => $upId]);
			$oldMemo = json_decode($preEdit['cost_details']);
			$upc_memo = isset($oldMemo->c_memo) ? $oldMemo->c_memo : [];
			for ($i = 0; $i < count($memoName); $i++) {
				$memoName[$i];
				$tmpName[$i];
				if (!empty($memoName[$i])) {
					$name = explode('.', $memoName[$i]);
					$fileName = md5(rand() . $name[0] . time()) . '.' . end($name);
					$memoData[] = $fileName;
					isset($upc_memo[$i]) ? unlink('uploadFiles/memo/' . $upc_memo[$i]) : false;
					move_uploaded_file($tmpName[$i], 'uploadFiles/memo/' . $fileName);
				} else {
					$memoData[] = isset($upc_memo[$i]) ? $upc_memo[$i] : '';
				}
			}

			$costDetails = json_encode(['c_productName' => $_POST['costCn'], 'c_amount' => $_POST['costCa'], 'c_memo' => $memoData]);
			$upData = ['id' => $preEdit['id'], 'cst_amount' => $amount, 'cost_details' => $costDetails, 'cst_u_date' => $this->theDay];
			$updateSuccess = $this->db->updateAction('fms_cost', $upData, ['cst_id' => $upId]);
			if (isset($updateSuccess)) {
				unset($_SESSION['costEdit']);
				if ($upFile === $cst_memo) {
					move_uploaded_file($photo_array['tmp_name'], 'uploadFiles/memo/' . $upFile);
					!empty($preEdit['cst_memo']) ? unlink('uploadFiles/memo/' . $preEdit['cst_memo']) : false;
				}
				$_SESSION['info_message'] = ' update ' . $cst_memo_up;
				return $this->checker->redirect('userCostDetails');
			}
		}
	}
}

$action = new Action;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
	if (isset($_SESSION['atFirstSettings'])) {
		return $action->manageSettings(0000010113112);
	} elseif (isset($_SESSION['registerPartner'])) {
		unset($_SESSION['registerPartner']);
		return $action->manageUsers();
	} elseif (isset($_SESSION['userinfo'])) {
		$userInfo = $_SESSION['userinfo'];
		if (isset($_SESSION['createUserNamePassword'])) {
			unset($_SESSION['createUserNamePassword']);
			return $action->createUserNamePassword(0103010113112);
		}
		if (isset($_POST['getBy']) && !empty($_POST['getBy'])) {
			$getBy = $action->checker->c_valid($_POST['getBy']);
			if ($getBy === '101' || $getBy === '010') {
				return $action->getAccount($getBy);
			}
		}
		if (isset($_SESSION['resetAccount404'])) {
			return $action->resetAccount(0103010112);
		}

		if (isset($_SESSION['csrf']) && $_SESSION['csrf'] === $_POST['cc']) {
			unset($_SESSION['csrf']);
			return $action->resetPassword();
		}

		// sec_a = secure action
		if (isset($_SESSION['sec_a'], $_POST['sec_a']) && $_SESSION['sec_a'] === $_POST['sec_a']) {
			if ($_POST['settingsEdit']) {
				return $action->manageSettings(0000010113112);
			}
			if (isset($_POST['updateEmail'])) {
				return $action->updateEmail();
			}
			if (isset($_SESSION['bank'])) {
				unset($_SESSION['bank']);
				if (isset($_SESSION['cashInsert'])) {
					unset($_SESSION['cashInsert']);
					return $action->cashInsert();
				}
				if (isset($_SESSION['cashUpdate'])) {
					unset($_SESSION['cashUpdate']);
					return $action->cashUpdate();
				}
			}
			if (isset($_SESSION['userAction'])) {
				unset($_SESSION['userAction']);
				return $action->manageUsers();
			}
			if (isset($_SESSION['costAction'])) {
				unset($_SESSION['costAction']);
				return $action->manageExpense();
			}
		}
		return $action->checker->redirect('404');
	} else {
		return $action->checker->redirect('login');
	}
} elseif ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_SESSION['userinfo']) && isset($_SESSION['sec_a']) && isset($_GET) && !empty($_GET)) {
	$userInfo = $_SESSION['userinfo'];
	$valueId = array_values($_GET);
	$keysId = array_keys($_GET);

	// to delete Earn row
	if (isset($_SESSION['bank']) && $_SESSION['sec_a'] === $valueId[1]) {
		$id = $action->checker->makeId($valueId[0]);
		$pre_delete = $action->db->get_row('fms_bank', ['bankId' => $id]);
		$delete = $action->db->deleteAction('fms_bank', ['bankId' => $id]);
		if (isset($delete)) {
			$currency = $pre_delete["currency"] === 'bdt' ? 'Tk' : '$';
			$_SESSION['info_message'] = [($pre_delete["bankId"]), ($pre_delete["amount"] . $currency)];
			return $action->checker->redirect('cashDetails');
		}
	}

	//  to delete user
	if (isset($_SESSION['user']) && $_SESSION['sec_a'] === $keysId[0]) {

		$id = $action->checker->makeId($valueId[0]); // make user id
		$user = $action->db->get_row('fms_admin', ['id' => $id]);  // user information
		$deleteSucccess = $action->db->deleteAction('fms_admin', ['id' => $id]);
		if (isset($deleteSucccess)) {
			unlink('uploadFiles/userPhoto/' . $user['photo']);
			if ($userInfo['id'] === $id) {
				return $action->checker->redirect('login');
			} else {
				$_SESSION['deleteSucccess'] = $user['fullName'];
				return $action->checker->redirect('users');
			}
		}
	}

	return $action->checker->redirect('404');
} else {
	return $action->checker->redirect('404');
}

PHP 语法

[编辑 | 编辑源代码]

请求变量

[编辑 | 编辑源代码]

虽然我们的服务器目前启用了 register_globals,但 PHP 6 将删除此选项。因此,在新代码中,你应该始终使用超级全局变量 $_GET、$_POST 和 $_COOKIE。$_REQUEST 仅应在确定变量可以使用多种方法提供时使用。

PHP & HTML

[编辑 | 编辑源代码]

不会使用 Smarty 等 "模板系统"。PHP 本身就是一种模板语言。应尽力将代码排列为将逻辑放在文件顶部,并将输出放在文件底部。有时这需要循环相同的信息两次。但是,这将使代码更易于维护。

示例 PHP/HTML 混合
<?php

$sql = "select * from publications";
$PHEWSDB->query($sql);
while($rec = $PHEWSDB->fetch_array()){
    $publications[] = $rec;
}

?>

<ul>
    <label>Publications</label>
    <?php foreach($publications as $pub) { ?>
        <li><?=$pub["name"]?></li>
    <?php } ?>
</ul>


控制结构

[编辑 | 编辑源代码]

这些包括if, for, while, switch等。

示例if语句
if (condition1 || condition2) {
    action1;
} elseif (condition3 && (condition4 || condition5)) {
    action2;
} else {
    defaultaction;
}


控制语句应该在控制关键字和左括号之间有一个空格,以将它们与函数调用区分开来。

强烈建议你始终使用花括号,即使在它们在技术上可选的情况下也是如此。使用它们可以提高可读性,并减少在添加新行时引入逻辑错误的可能性。

示例switch语句
switch (condition) {
    case 1:
        action1;
        break;
    case 2:
        action2;
        break;
    
    default:
        defaultaction;
        break;
}


函数调用

[编辑 | 编辑源代码]

函数应该在函数名称、左括号和第一个参数之间没有空格;逗号和每个参数之间有空格,最后一个参数、右括号和分号之间没有空格。

示例函数调用
$var = foo($bar, $baz, $quux);


如上所示,在用于将函数的返回值分配给变量的等号两侧应该有一个空格。在相关分配块的情况下,可以插入更多空格以提高可读性。

$short         = foo($bar);
$long_variable = foo($baz);


函数定义

[edit | edit source]

函数声明类似于函数调用,左括号与函数声明位于同一行。

示例functiondefinition
function foo_func($arg1, $arg2 = '') {
    if (condition) {
        statement;
    }
    return $val;
}


带默认值的实参放在实参列表的最后。如果适用,请始终尝试从函数返回有意义的值。

Longerfunctionexample
function connect(&$dsn, $persistent = false) {
    if (is_array($dsn)) {
        $dsninfo = &$dsn;
    } else {
        $dsninfo = DB::parseDSN($dsn);
    }

    if (!$dsninfo || !$dsninfo['phptype']) {
        return $this->raiseError();
    }

    return true;
}


Comments

[edit | edit source]

必须提供完整的内联文档注释块(docblocks)。请阅读示例文件头注释块部分,了解为 PHP 编写 docblocks 的具体方法。更多信息可以在phpDocumentor网站上找到。

强烈建议使用非文档注释。一个经验法则是,如果你查看一段代码并认为“哇,我不想尝试描述它”,那么你需要在忘记它如何工作之前对其进行注释。

C 样式注释(/* */)和标准 C++ 注释(//)都可以。使用 Perl/shell 样式注释(#强烈不鼓励。

Including Code

[edit | edit source]

在任何无条件包含类文件的地方,使用require_once. 在任何有条件包含类文件的地方,使用include_once. 这两种方法都将确保类文件只被包含一次。它们共享相同的文件列表,因此您无需担心混合它们 - 通过require_once包含的文件不会被include_once.

^

PHP Code Tags

[edit | edit source]

始终使用<?php ?>来分隔 PHP 代码,而不是<? ?>简写。这是在不同操作系统和服务器设置上包含 PHP 代码的最便携方式。

Header Comment Blocks

[edit | edit source]

所有源代码文件都应在每个文件的顶部包含一个“页面级”docblock,以及在每个类或函数上方立即包含一个“类级”docblock。

Example docblocks
<?php

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <[email protected]>
 * @author     Another Author <[email protected]>
 * @copyright  1997-2005 The PHP Group
 * @license    https://php.ac.cn/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */

/*
 * Place includes, constant defines and $_GLOBAL settings here.
 * Make sure they have appropriate docblocks to avoid phpDocumentor
 * construing they are documented by the page-level docblock.
 */

/**
 * Short description for class
 *
 * Long description for class (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <[email protected]>
 * @author     Another Author <[email protected]>
 * @copyright  1997-2005 The PHP Group
 * @license    https://php.ac.cn/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class foo
{
}

?>


Required Tags That Have Variable Content

[edit | edit source]
Short Descriptions
[edit | edit source]

所有 docblocks 必须提供简短描述。它们应该是一句话,而不是项目的名称。请阅读编码标准的示例文件,了解如何编写良好的描述。

@author
[edit | edit source]

没有硬性规定来确定何时将新的代码贡献者添加到给定源文件的作者列表中。一般来说,他们的更改应该属于“实质性”类别(意味着大约 10% 到 20% 的代码更改)。可以对重写函数或贡献新逻辑进行例外处理。

简单的代码重组或错误修复不会为作者列表中添加新的人员提供理由。

@since
[edit | edit source]

在包首次发布后添加文件或类时,此标记是必需的。不要在初始发布中使用它。

@deprecated
[edit | edit source]

当文件或类不再使用但出于向后兼容性而保留时,此标记是必需的。

Order and Spacing

[edit | edit source]

为了方便源代码的长期可读性,文本和标记必须符合上述示例中提供的顺序和间距。此标准是从 JavaDoc 标准中采用的。

Example URLs

[edit | edit source]

根据RFC 2606,对于所有示例 URL 和电子邮件地址,使用 example.com、example.org 和 example.net。

Naming Conventions

[edit | edit source]

Classes

[edit | edit source]

类应该被赋予描述性的名称。尽可能避免使用缩写。类名应该始终以大写字母开头,并使用混合大小写来分隔单词

一些好的类名示例是

Log
NetFinger
HTMLUploadError

Functions, Methods and Variable Names

[edit | edit source]

函数、方法和变量名应该使用 Unix C 样式命名。如果适用,函数应该以包或库名称作为前缀,以避免名称冲突。名称应该全部小写,每个新“单词”用下划线(_)分隔。一些例子

connect() 
get_data()
build_some_widget()

$i
$count
$temp_array

私有类成员(指仅在声明它们的同一类中使用的类成员)前面有一个下划线。例如

_sort()
_init_tree()
$this->_status

Constants and Global Variables

[edit | edit source]

常量和全局变量应该始终为全大写,用下划线分隔单词。常量名称以它们所用类的/包的大写名称为前缀。例如,名为DB的包使用的常量以DB_.

开头。注意:true、false 和 null 常量除外,它们始终为小写。

File Formats

[edit | edit source]

所有脚本必须

  • 以 ASCII 文本形式存储
  • 使用 ISO-8859-1 字符编码
  • 以 Unix 格式,这意味着
    1. 行只能以换行符(LF)结尾。换行符表示为序号 10、八进制 012 和十六进制 0A。不要使用像 Macintosh 电脑那样的回车符(CR)或像 Windows 电脑那样的回车符/换行符组合(CRLF)。
    2. 建议文件中的最后一个字符为换行符。这意味着,当光标位于文件的末尾时,它应该位于文本的最后一行下方。某些实用程序,例如 diff,如果文件中的最后一个字符不是换行符,则会抱怨。

Sample File

[编辑 | 编辑源代码]

示例中的每个文档块都包含许多关于编写文档块注释的细节。遵循这些说明很重要,原因有两个。首先,当文档块易于阅读时,用户和开发人员可以快速了解您的代码的功能。

请注意垂直和水平间距。它们是标准的一部分。

<?php

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <[email protected]>
 * @author     Another Author <[email protected]>
 * @copyright  1997-2005 The PHP Group
 * @license    https://php.ac.cn/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id:$
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      File available since Release 1.2.0
 * @deprecated File deprecated in Release 2.0.0
 */

/**
 * This is a "Docblock Comment," also known as a "docblock."  The class'
 * docblock, below, contains a complete description of how to write these.
 */
require_once 'PEAR.php';

/**
 * Methods return this if they succeed
 */
define('NET_SAMPLE_OK', 1);

/**
 * The number of objects created
 * @global int $GLOBALS['NET_SAMPLE_COUNT']
 */
$GLOBALS['NET_SAMPLE_COUNT'] = 0;

/**
 * An example of how to write code to PEAR's standards
 *
 * Docblock comments start with "/**" at the top. Notice how the "/"
 * lines up with the normal indenting and the asterisks on subsequent rows
 * are in line with the first asterisk. The last line of comment text
 * should be immediately followed on the next line by the closing asterisk
 * and slash and then the item you are commenting on should be on the next
 * line below that. Don't add extra lines. Please put a blank line
 * between paragraphs as well as between the end of the description and
 * the start of the @tags. Wrap comments before 80 columns in order to
 * ease readability for a wide variety of users.
 *
 * Docblocks can only be used for programming constructs that allow them
 * (classes, properties, methods, defines, includes, globals). See the
 * phpDocumentor documentation for more information.
 * http://phpdoc.org/docs/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html
 *
 * The Javadoc Style Guide is an excellent resource for figuring out
 * how to say what needs to be said in docblock comments. Much of what is
 * written here is a summary of what is found there, though there are some
 * cases where what's said here overrides what is said there.
 * http://java.sun.com/j2se/javadoc/writingdoccomments/index.html#styleguide
 *
 * The first line of any docblock is the summary. Make them one short
 * sentence, without a period at the end. Summaries for classes, properties
 * and constants should omit the subject and simply state the object,
 * because they are describing things rather than actions or behaviors.
 *
 * Below are the tags commonly used for classes. @category through @access
 * are required. The remainder should only be used when necessary.
 * Please use them in the order they appear here. phpDocumentor has
 * several other tags available, feel free to use them.
 *
 * @category   CategoryName
 * @package    PackageName
 * @author     Original Author <[email protected]>
 * @author     Another Author <[email protected]>
 * @copyright  1997-2005 The PHP Group
 * @license    https://php.ac.cn/license/3_0.txt  PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://pear.php.net/package/PackageName
 * @see        NetOther, Net_Sample::Net_Sample()
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */
class Net_Sample
{
    /**
     * The status of foo's universe
     *
     * Potential values are 'good', 'fair', 'poor' and 'unknown'.
     *
     * @var string
     */
    var $foo = 'unknown';

    /**
     * The status of life
     *
     * Note that names of private properties or methods must be
     * preceeded by an underscore.
     *
     * @var bool
     * @access private
     */
    var $_good = true;

    /**
     * Registers the status of foo's universe
     *
     * Summaries for methods should use 3rd person declarative rather
     * than 2nd person imperative, beginning with a verb phrase.
     *
     * Summaries should add description beyond the method's name. The
     * best method names are "self-documenting", meaning they tell you
     * basically what the method does. If the summary merely repeats
     * the method name in sentence form, it is not providing more
     * information.
     *
     * Summary Examples:
     *   + Sets the label              (preferred)
     *   + Set the label               (avoid)
     *   + This method sets the label  (avoid)
     *
     * Below are the tags commonly used for methods. A @param tag is
     * required for each parameter the method has. The @return and
     * @access tags are mandatory. The @throws tag is required if the
     * method uses exceptions. @static is required if the method can
     * be called statically. The remainder should only be used when
     * necessary. Please use them in the order they appear here.
     * phpDocumentor has several other tags available, feel free to use
     * them.
     *
     * The @param tag contains the data type, then the parameter's
     * name, followed by a description. By convention, the first noun in
     * the description is the data type of the parameter. Articles like
     * "a", "an", and  "the" can precede the noun. The descriptions
     * should start with a phrase. If further description is necessary,
     * follow with sentences. Having two spaces between the name and the
     * description aids readability.
     *
     * When writing a phrase, do not capitalize and do not end with a
     * period:
     *   + the string to be tested
     *
     * When writing a phrase followed by a sentence, do not capitalize the
     * phrase, but end it with a period to distinguish it from the start
     * of the next sentence:
     *   + the string to be tested. Must use UTF-8 encoding.
     *
     * Return tags should contain the data type then a description of
     * the data returned. The data type can be any of PHP's data types
     * (int, float, bool, string, array, object, resource, mixed)
     * and should contain the type primarily returned. For example, if
     * a method returns an object when things work correctly but false
     * when an error happens, say 'object' rather than 'mixed.'  Use
     * 'void' if nothing is returned.
     *
     * Here's an example of how to format examples:
     * <sample>
     * require_once 'Net/Sample.php';
     *
     * $s = new Net_Sample();
     * if (PEAR::isError($s)) {
     *     echo $s->getMessage() . "\n";
     * }
     * </sample>
     *
     * @param string $arg1  the string to quote
     * @param int    $arg2  an integer of how many problems happened.
     *                       Indent to the description's starting point
     *                       for long ones.
     *
     * @return int  the integer of the set mode used. FALSE if foo
     *               foo could not be set.
     * @throws exceptionclass  [description]
     *
     * @access public
     * @static
     * @see Net_Sample::$foo, Net_Other::someMethod()
     * @since Method available since Release 1.2.0
     * @deprecated Method deprecated in Release 2.0.0
     */
    function set_foo($arg1, $arg2 = 0) {
        /*
         * This is a "Block Comment."  The format is the same as
         * Docblock Comments except there is only one asterisk at the
         * top. phpDocumentor doesn't parse these.
         */
        if ($arg1 == 'good' || $arg1 == 'fair') {
            $this->foo = $arg1;
            return 1;
        } else if ($arg1 == 'poor' && $arg2 > 1) {
            $this->foo = 'poor';
            return 2;
        } else {
            return false;
        }
    }

}

?>


华夏公益教科书