Hướng dẫn dùng php nyc trong PHP
Đôi lúc các bạn xem các hướng dẫn về hàm lấy thời gian :date(format,timestamp). Show
Nếu chưa biết hàm date(format,timestamp) bạn có thể xem ở link:http://congnghe5s.com/bai-viet/xu-ly-ngay-gio-trong-php.html. Bạn thực hiện test lệnh trên máy và kết quả không khớp với time hiện tại. Đó là vì lí do thời gian hay timezone trên server bạn đã cài đặt khác vì thế để trả về đúng time bạn muốn bạn có thể dùng hàm: Cú pháp:date_default_timezone_set ( string $timezone_identifier ). tham số : $timezone_identifier bạn lấy ở đây:http://php.net/manual/en/timezones.asia.php phù hợp khu vực bạn muốn ví dụ mình muốn set lấy giờ việt nam mình làm như sau: date_default_timezone_set('Asia/Ho_Chi_Minh'). Sau đó các bạn dùng hàm : echo date('d/m/Y - H:i:s'); ra đúng kết quả time ở Việt Nam. Ví dụ: date_default_timezone_set('Asia/Ho_Chi_Minh'); if (date_default_timezone_get()) { echo 'date_default_timezone_set: ' . date_default_timezone_get() . ' '; } echo date('d/m/Y H:i:s');Ví dụ trên có 1 hàm cũng khá quan trọng : date_default_timezone_get() trả về timezone mặc định của server bạn đang chạy hoặc là đã được thiết lập thông qua date_default_timezone_set(). Qua bài viết hy vọng các bạn có thêm kiến thức khi xử lý ngày tháng trong PHP. Giới thiệuĐây là những nguyên lý kỹ thuật phần mềm, được trích từ cuốn sách Clean Code của tác giả Robert C. Martin (thường gọi là Uncle Bob) rất thích hợp cho ngôn ngữ PHP. Tài liệu này không phải là sách hướng dẫn về phong cách viết code, mà là hướng dẫn cách làm thế nào để viết phần mềm dễ đọc, dễ sử dụng lại, và dễ cải tiến trong PHP. Bạn không cần phải tuân theo tất cả các nguyên tắc trong tài liệu này. Đây chỉ đơn giản là những hướng dẫn, nhưng dù sao nó cũng là đúc kết từ nhiều năm kinh nghiệm của tác giả. Repository này lấy cảm hứng từ clean-code-javascript Lưu ý: Dù nhiều lập trình viên còn sử dụng PHP 5, nhưng nhiều ví dụ trong đây chỉ chạy được trên PHP 7.1+. Tuyển dụng php cần gấp làm việc online BiếnSử dụng tên biến có ý nghĩa và dễ hiểuChưa tốt: $ymdstr = $moment->format('y-m-d'); Tốt: $currentDate = $moment->format('y-m-d'); Sử dụng cùng từ vựng cho cùng ột loại biến Chưa tốt: getUserInfo(); getUserData(); getUserRecord(); getUserProfile(); Tốt: getUser(); Đặt tên sao cho dễ tìm kiếm (phần 1)Thường thì chúng ta sẽ đọc code nhiều hơn viết code. Nên điều quan trọng là code chúng ta viết ra phải dễ đọc và dễ tìm kiếm. Nếu không đặt tên biến có ý nghĩa và làm chương trình dễ hiểu, chúng ta sẽ gây khó cho những lập trình viên khác. Do đó mỗi khi đặt tên biến, hàm thì hãy đặt có ý nghĩa. Chưa tốt: // Oh man, 448 là cái giề vậy? $result = $serializer->serialize($data, 448); Tốt: $json = $serializer->serialize($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); Đặt tên sao cho dễ tìm kiếm (phần 2)Chưa tốt: // Lại nữa, 4 nghĩa là cái giề đây? if ($user->access & 4) { // ... } Tốt: class User { const ACCESS_READ = 1; const ACCESS_CREATE = 2; const ACCESS_UPDATE = 4; const ACCESS_DELETE = 8; } if ($user->access & User::ACCESS_UPDATE) { // do edit ... } Đặt tên biến dễ hiểuTức là đặt tên biến sao cho đọc vô là hiểu nó là gì và nó dùng để làm gì. Không cần phải suy nghĩ, suy diễn. Chưa tốt: $address = 'One Infinite Loop, Cupertino 95014'; $cityZipCodeRegex = '/^[^,]+,\s*(.+?)\s*(\d{5})$/'; preg_match($cityZipCodeRegex, $address, $matches); saveCityZipCode($matches[1], $matches[2]); Không tệ lắm: Tốt hơn một chút, nhưng vẫn còn phụ thuộc nhiều vào regex. $address = 'One Infinite Loop, Cupertino 95014'; $cityZipCodeRegex = '/^[^,]+,\s*(.+?)\s*(\d{5})$/'; preg_match($cityZipCodeRegex, $address, $matches); [, $city, $zipCode] = $matches; saveCityZipCode($city, $zipCode); Tốt: Đã giảm phụ thuộc vào regex bằng “naming subpatterns”. $address = 'One Infinite Loop, Cupertino 95014'; $cityZipCodeRegex = '/^[^,]+,\s*(? Tránh lồng (nesting) quá nhiều và nên return sớm (phần 1)Quá nhiều if else lồng nhau sẽ khiến code tăng độ phức tạp, khó debug. Giảm sự phức tạp bằng cách giảm số if else lồng nhau xuống ít nhất có thể. Return sớm chính là một cách giảm số lần lồng nhau. Chưa tốt: function isShopOpen($day): bool { if ($day) { if (is_string($day)) { $day = strtolower($day); if ($day === 'friday') { return true; } elseif ($day === 'saturday') { return true; } elseif ($day === 'sunday') { return true; } else { return false; } } else { return false; } } else { return false; } } Tốt: function isShopOpen(string $day): bool { if (empty($day)) { return false; } $openingDays = [ 'friday', 'saturday', 'sunday' ]; return in_array(strtolower($day), $openingDays, true); } Tránh lồng (nesting) quá nhiều và nên return sớm (phần 2)Chưa tốt: function fibonacci(int $n) { if ($n < 50) { if ($n !== 0) { if ($n !== 1) { return fibonacci($n - 1) + fibonacci($n - 2); } else { return 1; } } else { return 0; } } else { return 'Not supported'; } } Tốt: function fibonacci(int $n): int { if ($n === 0 || $n === 1) { return $n; } if ($n > 50) { throw new \Exception('Not supported'); } return fibonacci($n - 1) + fibonacci($n - 2); } Tránh hack não người đọcĐừng khiến người đọc code phải khó khăn để hiểu ý nghĩa của biến. Tên biến càng rõ ràng càng tốt. Chưa tốt: $l = ['Austin', 'New York', 'San Francisco']; for ($i = 0; $i < count($l); $i++) { $li = $l[$i]; doStuff(); doSomeOtherStuff(); // ... // ... // ... // Đợi đã, `$li` là cái gì? dispatch($li); } Tốt: $locations = ['Austin', 'New York', 'San Francisco']; foreach ($locations as $location) { doStuff(); doSomeOtherStuff(); // ... // ... // ... dispatch($location); } Đừng thêm những nội dung không cần thiếtNếu tên của class/object đã rõ ràng, không nên lặp lại chúng trong tên biến. Chưa tốt: class Car { public $carMake; public $carModel; public $carColor; //... } Tốt: class Car { public $make; public $model; public $color; //... } Sử dụng đối số mặc định thay vì phải kiểm tra bằng biểu thức điều kiệnChưa tốt: Chưa tốt vì function createMicrobrewery($breweryName = 'Hipster Brew Co.'): void { // ... } Không tệ lắm: Cái này tốt hơn cái trước, nhưng nó nên quản lý được giá trị của biến thì tốt hơn. function createMicrobrewery($name = null): void { $breweryName = $name ?: 'Hipster Brew Co.'; // ... } Tốt: Bạn có thể sử dụng type hinting và chắc chắn function createMicrobrewery(string $breweryName = 'Hipster Brew Co.'): void { // ... } So sánhSử dụng identical comparisonChưa tốt: Sử dụng simple comparison (so sánh đơn giản) $a = '42'; $b = 42; Sử dụng simple comparison thì nó sẽ tự chuyển kiểu string qua kiểu int if ($a != $b) { //Biểu thức này sẽ trả về `false` } Phép so sánh $a != $b trả về Tốt: Sử dụng identical comparison (so sánh giống hệt nhau) để so sánh cả kiểu dữ liệu và giá trị if ($a !== $b) { //Biểu thức này trả về `true` } HàmĐối số của hàm (ít hơn hoặc bằng 2 là lý tưởng)Giới hạn số lượng đối số (parameters) của hàm vô cùng quan trọng bởi vì nó giúp dễ test hơn. Có nhiều hơn 3 đối số dẫn đến một tổ hợp rất nhiều trường hợp khác nhau cần phải test. Lý tưởng nhất là khi hàm không có đối số nào. Một hoặc hai đối số là ok, còn ba thì nên hạn chế. Bất cứ khi nào hàm có nhiều hơn 3 đối số thì cần phải xem xét tìm cách giảm bớt lại. Bởi vì nếu hàm có nhiều hơn hai đối số thì nó phải xử lý rất nhiều. Chưa tốt: function createMenu(string $title, string $body, string $buttonText, bool $cancellable): void { // ... } Tốt: class MenuConfig { public $title; public $body; public $buttonText; public $cancellable = false; } $config = new MenuConfig(); $config->title = 'Foo'; $config->body = 'Bar'; $config->buttonText = 'Baz'; $config->cancellable = true; function createMenu(MenuConfig $config): void { // ... } Hàm chỉ thực hiện một chức năngĐây là nguyên tắc quan trọng nhất trong phát triển phần mềm. Khi hàm thực hiện nhiều hơn một chức năng, chúng khó biên dịch, kiểm tra và biết được nguyên nhân lỗi. Khi bạn tạo hàm chỉ với một chức năng, sẽ dễ dàng refactor hơn và code sẽ dễ đọc hơn. Nếu làm được điều này thì bạn sẽ tốt hơn nhiều lập trình viên khác. Chưa tốt: function emailClients(array $clients): void { foreach ($clients as $client) { $clientRecord = $db->find($client); if ($clientRecord->isActive()) { email($client); } } } Tốt: function emailClients(array $clients): void { $activeClients = activeClients($clients); array_walk($activeClients, 'email'); } function activeClients(array $clients): array { return array_filter($clients, 'isClientActive'); } function isClientActive(int $client): bool { $clientRecord = $db->find($client); return $clientRecord->isActive(); } Tên hàm nên thể hiện chức năng của hàmChưa tốt: class Email { //... public function handle(): void { mail($this->to, $this->subject, $this->body); } } $message = new Email(...); // Hàm này dùng làm gì? Có phải nó xử lý mail? Nó có đang ghi gì vào file không? $message->handle(); Tốt: class Email { //... public function send(): void { mail($this->to, $this->subject, $this->body); } } $message = new Email(...); // Rõ ràng và minh bạch, hàm này gửi mail $message->send(); Hàm chỉ nên có độ trừu tượng một cấpKhi bạn có độ trừu tượng nhiều hơn một cấp thì hàm thường phải làm quá nhiều việc. Hãy chia tách hàm ra thành nhiều phần để dễ sử dụng lại và dễ test. Chưa tốt: function parseBetterJSAlternative(string $code): void { $regexes = [ // ... ]; $statements = explode(' ', $code); $tokens = []; foreach ($regexes as $regex) { foreach ($statements as $statement) { // ... } } $ast = []; foreach ($tokens as $token) { // lex... } foreach ($ast as $node) { // parse... } } Cũng chưa tốt: Chúng ta đã thực hiện tách ra vài hàm, nhưng hàm function tokenize(string $code): array { $regexes = [ // ... ]; $statements = explode(' ', $code); $tokens = []; foreach ($regexes as $regex) { foreach ($statements as $statement) { $tokens[] = /* ... */; } } return $tokens; } function lexer(array $tokens): array { $ast = []; foreach ($tokens as $token) { $ast[] = /* ... */; } return $ast; } function parseBetterJSAlternative(string $code): void { $tokens = tokenize($code); $ast = lexer($tokens); foreach ($ast as $node) { // parse... } } Tốt: Giải pháp tốt nhất là chuyển các phần thành các
dependencies của hàm class Tokenizer { public function tokenize(string $code): array { $regexes = [ // ... ]; $statements = explode(' ', $code); $tokens = []; foreach ($regexes as $regex) { foreach ($statements as $statement) { $tokens[] = /* ... */; } } return $tokens; } } class Lexer { public function lexify(array $tokens): array { $ast = []; foreach ($tokens as $token) { $ast[] = /* ... */; } return $ast; } } class BetterJSAlternative { private $tokenizer; private $lexer; public function __construct(Tokenizer $tokenizer, Lexer $lexer) { $this->tokenizer = $tokenizer; $this->lexer = $lexer; } public function parse(string $code): void { $tokens = $this->tokenizer->tokenize($code); $ast = $this->lexer->lexify($tokens); foreach ($ast as $node) { // parse... } } } Đừng sử dụng cờ như là một đối số của hàmCờ dùng để nói rằng hàm này thực hiện nhiều hơn một công việc. Nhưng hàm thì chỉ nên xử lý một công việc mà thôi. Do đó hãy chia tách hàm của bạn nếu như chúng có nhiều luồng code phân biệt bằng boolean(true/false). Chưa tốt: function createFile(string $name, bool $temp = false): void { if ($temp) { touch('./temp/'.$name); } else { touch($name); } } Tốt: function createFile(string $name): void { touch($name); } function createTempFile(string $name): void { touch('./temp/'.$name); } Tránh tác dụng phụMột hàm sinh ra tác dụng phụ nếu nó thực hiện thêm việc khác ngoài việc lấy giá trị vào và trả về một hoặc nhiều giá trị khác. Tác dụng phụ có thể là viết vào một file nào đó, sửa đổi biến global, hoặc vô tình chuyển hết tiền của bạn cho người lạ nào đó. Vậy nếu bây giờ bạn cần hàm thực hiện các tác dụng phụ đó thì sao. Giống như ví dụ trước, bạn cần ghi vào file. Điều bạn cần làm là tập trung những việc này lại một chỗ. Đừng viết vài hàm và vài lớp chỉ để ghi vào vài file cụ thể. Hãy viết một service để làm điều đó. Một và chỉ một service. Hãy tránh những sai lầm phổ biến như: chia sẻ trạng thái giữa các object mà không tuân theo cấu trúc nào, sử dụng kiểu dữ liệu có thể thay đổi/bị thay đổi dễ dàng, không tổng hợp các tác dụng phụ có thể xảy ra khi viết hàm. Chưa tốt: // Biến glabal được tham chiếu bởi hàm bên dưới. // Nếu ta tạo một function khác sử dụng chính biến name, ví dụ bên dưới cho thấy nó biến thành array và đã bị phá vỡ. $name = 'Ryan McDermott'; function splitIntoFirstAndLastName(): void { global $name; $name = explode(' ', $name); } splitIntoFirstAndLastName(); var_dump($name); // ['Ryan', 'McDermott']; Tốt: function splitIntoFirstAndLastName(string $name): array { return explode(' ', $name); } $name = 'Ryan McDermott'; $newName = splitIntoFirstAndLastName($name); var_dump($name); // 'Ryan McDermott'; var_dump($newName); // ['Ryan', 'McDermott']; Đừng viết hàm globalDùng nhiều hàm global là bad practice với nhiều ngôn ngữ bởi vì có thể gây xung đột với thư viện khác và người sử dụng API của bạn không hề hay biết gì cho đến khi nhận được thông báo lỗi. Hãy xem xét ví dụ sau: bạn sẽ làm gì nếu muốn trả về một mảng. Bạn có thể viết hàm global như Chưa tốt: function config(): array { return [ 'foo' => 'bar', ] } Tốt: class Configuration { private $configuration = []; public function __construct(array $configuration) { $this->configuration = $configuration; } public function get(string $key): ?string { return isset($this->configuration[$key]) ? $this->configuration[$key] : null; } } Tạo instance của lớp $configuration = new Configuration([ 'foo' => 'bar', ]); Và bây giờ sử dụng instance Đừng sử dụng Singleton patternSingleton là một anti-pattern. Trích đoạn từ Brian Button:
Đây là một ý kiến khác của Misko Hevery về gốc rễ của vấn đề. Chưa tốt: class DBConnection { private static $instance; private function __construct(string $dsn) { // ... } public static function getInstance(): DBConnection { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } // ... } $singleton = DBConnection::getInstance(); Tốt: class DBConnection { public function __construct(string $dsn) { // ... } // ... } Tạo instance của lớp $connection = new DBConnection($dsn); Và bây giờ sử dụng instance Đóng gói điều kiệnChưa tốt: if ($article->state === 'published') { // ... } Tốt: if ($article->isPublished()) { // ... } Tránh điều kiện phủ địnhChưa tốt: function isDOMNodeNotPresent(\DOMNode $node): bool { // ... } if (!isDOMNodeNotPresent($node)) { // ... } Tốt: function isDOMNodePresent(\DOMNode $node): bool { // ... } if (isDOMNodePresent($node)) { // ... } Tránh dùng điều kiệnĐiều này có vẻ không khả quan. Hầu hết mọi người sẽ thắc mắc, “làm sao có thể làm gì đó mà không có Chưa tốt: class Airplane { // ... public function getCruisingAltitude(): int { switch ($this->type) { case '777': return $this->getMaxAltitude() - $this->getPassengerCount(); case 'Air Force One': return $this->getMaxAltitude(); case 'Cessna': return $this->getMaxAltitude() - $this->getFuelExpenditure(); } } } Tốt: interface Airplane { // ... public function getCruisingAltitude(): int; } class Boeing777 implements Airplane { // ... public function getCruisingAltitude(): int { return $this->getMaxAltitude() - $this->getPassengerCount(); } } class AirForceOne implements Airplane { // ... public function getCruisingAltitude(): int { return $this->getMaxAltitude(); } } class Cessna implements Airplane { // ... public function getCruisingAltitude(): int { return $this->getMaxAltitude() - $this->getFuelExpenditure(); } } Còn tiếp…. TopDev via Chungnguyen Xem thêm tuyển dụng php nhiều ngành nghề tại đây |