Hỏi về Form trong bootstrap 4
Ý họ nói là nếu trong trường hợp bạn dùng input[type="checkbox|ratio"]
mà không có thẻ label
đi kèm thì cần reset cái thuộc tính position
về giá trị mặc định là static
. Bằng cách thêm cái .position-static
cho cái checkbox. Bởi vì cái .form-check-input
nó đang có position: absolute
. Nếu không reset về static thì sẽ bị lỗi giao diện giống @dao.thai.son nói ở dưới.
Hỏi về CSS hover
Để làm hiệu ứng này thì bạn cần sử dụng javascript để xử lý nhé. Mình sẽ bắt sự kiện mousemove
, fire khi con chuột di chuyển. Con chuột di chuyển một khoảng bao nhiêu thì mình sẽ cuộn cái menu một khoảng bấy nhiêu. Lười viết code nên mời bạn tham khảo code mẫu mình kiếm được ở trên mạng nhé:
Deploy dự án Laravel lên hosting, ko chỉnh sửa cấu trúc thư mục
Bạn dùng thử cách này xem:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteRule !^public/ /public%{REQUEST_URI} [L,NC]
Với lại bạn có chắc là đã enable mod Rewrite lên chưa bằng cách vào trang dashbash của CPanel xem info của php. Nếu chưa thì bạn tích chọn để enable mod rewrite cho hosting lên nhé.
Phỏng vấn php
Cái này cũng hơi khó, không biết bạn đang phỏng vấn ứng tuyển vào vị trí nào. Bởi mỗi vị trí bạn ứng tuyến thì nhà tuyển dụng sẽ hỏi những câu hỏi khác nhau tới bạn. Việc phỏng vấn một bạn vào thực tập sẽ khác phỏng vấn một bạn junior hay senior nữa. Nhưng dựa vào cách đặt câu hỏi thì mình đoán bạn là fresher. Do là newbie phỏng vấn về kỹ thuật thì bạn nên nắm chắc:
- Các kiến thức nền của web như HTTP, Restful API, Session/Cookie.
- Các kiến thức nền của PHP như các khái niệm cơ bản về biến, hằng số, namespace.., về lập trình hướng đối tượng - OOP, design partern, và nắm cơ bản một framework nào đó mà công ty đó đang dùng.
- Các kiến thức cơ bản về frontend như CSS, CSS3, HTML5, Ajax, Javascript/ES6, nếu biết dùng cơ bản về một thư viện nào đó như Vue.js, React.js mà công ty đó đang sử dụng.
- Mốt số kiến thức về security cơ bản như XSS, SQL injection...
Nếu là fresher thì mình nghĩ vậy là khá ổn để bạn tự tin hơn rồi.
Khó khăn v/v lần đầu chạy project trên MacOS (Moojave)
Bạn có thể show nội dung file config/database.php
của bạn được không? Mình nghĩ bạn có thể đang cấu hình sai, có thể đang chạy mysql với socket
chứ không phải tcp
ở port 3306 nên không connect được tới mysql. Hoặc bạn thử đổi database host về 127.0.0.1
xem sao?
Hàm khởi tạo PHP Laravel
Hàm khởi tạo trong các ngôn ngữ lập trình hỗ trợ lập trình hướng đối tượng (OOP) nói chung và PHP nói riêng là một hàm được tự động thực thi khi tạo mới một đối tượng qua từ khóa new
. Hàm khởi tạo được sử dụng mục đích khởi tạo các giá trị ban đầu cho đối tượng sau khi tạo mới. Trong PHP, khởi tạo có tên là __construct
và là một trong các magic method của PHP mặc dù nó cũng ko có tí nào là magic cả. Lưu ý là trong __construct
thì không có dùng return
nhé bạn!
class Student
{
protected $name;
// Đây là hàm khởi tạo, được tự động thực thi khi khởi tạo instance của một class
public function __construct($name)
{
$this->name = $name;
}
}
$student = new Student('Nguyen Huu Kim');
Thiết kế database cho web tuyển dụng
Cá nhân mình nghĩ, mục đích trước mắt của bạn là để học tập. Do đó, nếu DBMS nào bạn chưa sử dụng thì bạn có thể áp dụng vào trong lần này để trải nghiệm và khám phá. Cũng bởi lẻ, cả Postgres hay MySQL thì đều ổn cả với hệ thống bạn đang hướng tới. Do đó không phải lăn tăn thêm, chắc bạn đã tìm được lời đáp cho mình rồi nhỉ
Cách lưu database song song trong php
Nếu hosting provider có cung cấp dịch vụ auto backup database thì bạn dùng luôn để tự backup theo ngày là được rồi bạn.
Nếu bạn không dùng dịch vụ backup của hosting provider thì bạn có thể chạy command line để backup database với mysqldump
.
mysqldump -uusername -ppassword database_name > $(date "+%Y-%m-%d-%H-%M").sql
VD: lệnh trên sẽ export dastabase của bạn ra một file .sql
có tên file là ngày tháng năm luôn, bạn có thể dùng để import lại database khi gặp sự cố.
Bạn set command trên vào cronjob để cho nó tự động backup database vào một thời điểm nào đó ít người sử dụng như 1h, 2h hay 3h sáng chẳng hạn. Hoặc bạn cho nó backup cứ cách 4 tiếng chẳng hạn...
Bạn có thể xem xét giải pháp này thay vì hướng giải quyết hiện tại của bạn nhé.
Tìm file đã được backup mới nhất trong thư mục backup sử dụng php như thế nào?
Vấn đề bạn gặp có vẻ giống câu hỏi này?!! Bạn thử tham khảo giải pháp trong câu hỏi kia xem nhé! https://viblo.asia/q/lay-thong-tin-thoi-gian-cua-file-trong-thu-muc-su-dung-laravel-o754DoPW5M6
Sweet alert 2 không hoạt động
Make sure với nhau chút nhé:
- Cái request tới backend đang bị lỗi với status code 422, có thể là bạn đang dùng Laravel và request chưa qua được Request Validation. Do request lỗi nên code sẽ chạy vào trong
.catch
. Cái catch ko làm gì cả nên bị exception bị "ngậm" luôn đi chứ không phải không có lỗi báo ra như bạn đề cập. - Mình đọc comment của @ruacondepzaj bên trên, thấy ảnh báo lỗi do cái Toast chưa tồn tại. Bởi vì bạn đang setup
window.toast
chứ không phảiwindow.Toast
. Khi dùng bạn thử đổi lại thành:
.catch(() => {
toast.fire({
type: 'error',
message: 'Got an error',
})
})
So sánh diff giữa 2 version file
Mình không hiểu câu hỏi của bạn cho lắm. Theo như mình hiểu thì mục đích bạn muốn biết một file nào đó trong hệ thống có thay đổi hay không. Nếu có thì báo cho người dùng biết là có bản cập nhật để cập nhật mỗi file thay đổi thay vì phải tải toàn bộ data về.
Bạn đầu mình nghĩ là bạn có thể dùng hàm băm rồi checksum của file để biết file có thay đổi hay chưa. Nhưng nghĩ lại, nếu là bạn viết phần mềm gồm một gói cài đặt thì trong phần mềm bạn thiết lập thêm một đoạn code gọi API lên server check version của phần mềm. Nếu thấy có version mới thì mình sẽ hiện thông báo ra cho người dùng tải bản cập nhật về để giải nén ghi đè lên các file hiện tại.
Trên đây là ý kiến của mình hy vọng giúp ích được cho bạn.
Return exception vs throw exception in php ?
Về sự khác nhau giữa return và throw trong php
return
được sử dụng để kết thúc việc hoàn tất thực thi thành công một chương trình con (ở đây làmethod
chẳng hạn) và gửi trả lại một giá trị về cho chương trình chính. Giá trị bạn trả lại cho chương trình chính có thể ở bất cứ kiểu dữ liệu nào: Object, Array, Boolean .etc.
VD:
function sum(int $a, int $b)
{
return $a + $b;
}
// Main:
$firstNumber = 5;
$secondNumber = 10;
$result = sum($a, $b);
echo "\$a + \$b = {$result}";
throw
cũng được dùng để kết thúc một việc hoàn tất thực thi một chương trình con (nhưng ở đây là kết thúc với một exit code lỗi).throw
luôn bắn lại về chương trình chính mộtException
(đại diện cho một lỗi từ một trường hợp ngoại lệ nào đó mà logic trong chương trình con không xử lý được).
function divide($a, $b)
{
if ($b === 0) {
throw new \LogicException('Can not divide by zero');
}
return $a / $b;
}
// Main
try {
$firstNumber = 10;
$secondNumber = 0;
echo divide($firstNumber, $secondNumber);
} catch(\LogicException $exception) {
// handle error
}
Quay lại giải pháp bạn đang dùng
- Web app có lỗi -> notice về chatapp trong queue
- Job notice chatapp trong queue có lỗi -> dẫn tới bị quay lại bước trên -> một kiểu như hell callback
- Cách 1: Sử dụng một Custom Exception. Với cách này, khối try cần catch chính xác một exception được định danh cụ thể, như ví dụ trên là
\LogicException
. Hoặc bạn có thể catch toàn bộ exception với class\Exception
. Sau đó trong catch bạn throw Custom Exception để ErrorHandler nhận biết được và không report. Cách này không được ổn lắm. - Cách 2: Theo mình hiểu, bạn đổi cái
throw
trong cái catch ở Cách 1 thành return. Việc này không khác gì dấu bug cả. Và càng không hay ho hơn so với cách 1. - Cách 3: Bạn nên tìm hiểu nguyên nhân bị lỗi là do đâu và sửa nó. Nếu nguyên nhân throw ra exception như do đường truyền mạng ConnectException, NetworkException trong quá trình notice thì với những những cái này bạn có ignore nó. Có thể là log lại exception ra file logs và kết thúc job notice này tại đây thay vì lại report và một job notice khác sẽ chạy tiếp. Vì có cố thì cũng ko thể gửi được bởi mất kết nối mà. Tóm lại bạn phải tìm nguyên nhân gây lỗi và fix cái lỗi đấy chứ không nên quan tâm quá vào việc ignore error để dấu bug.
Cách config base link trong dự án vuejs, nuxtjs
Bạn sử dụng environment variable ý, kết hợp dotenv
để có thể khai báo qua file .env
như Laravel. Tất cả các environment variables sẽ được chứa trong biến global process.env
. Khi solve một environemnt sẽ như sau:
process.env.BASE_URI
.
Lúc này bạn có thể viết thêm một function javascript để render url cho tiện.
const url = (path = '') => `${BASE_URI}/${path}`
Ngoài ra:
- Với Vue.js thuần thì bạn cần cài thêm
EnvironmentPlugin
cho webpack. https://webpack.js.org/plugins/environment-plugin/ - Còn trong Nuxt.js thì nó đã config sẵn rồi, bạn chỉ cần thêm environment vào cho Nuxt.js app qua
nuxt.config.js
như sau thôi:
module.exports = {
env: {
BASE_URI: 'https://viblo.asia'
}
}
Hỏi về cách làm hệ thống comment như viblo
Không biết bạn đang dùng DBMS nào nhỉ? Như bạn nói, mấu chốt của bạn là gặp vấn đề khi query comments ra bị chậm. Bạn có thể thử như sau:
- Mỗi comment mình sẽ lưu id của bài viết được comment (mình gọi là
commentable_id
nha). Khi try vấn chỉ cần thêm ràng buộcwhere('commentable_id', postID)
là lấy được tất cả các comments của một bài viết. - Nếu làm kiểu comment đa cấp, bạn có thể lưu thêm
parent_id
, sau khi truy vấn xong ở bước 1 lấy được tất cả comments, mình xử lý gộp chúng bằng code Python cũng được. Làm kiểu này nếu hệ thống có ít comment. Còn như facebook thì họ chỉ làm 2 cấp. Ở cấp thứ 2 họ chỉ select ra mấy cái mới nhất mà thôi. - Nếu bạn muốn tiện truy vấn trong khi làm comment đa cấp, có thể thêm một trường
path
, có format:child_path
=parent_path
+child_id
VD: Comment 0003 reply cho comment 0002, comment 0002 thì lại reply cho comment 0001 tạo thành 3 cấp độ. Cáipath
tương ứng của các comment là:- 0001 => 0001
- 0002 => 0001.0002
- 0003 => 0001.0002.0003
Lúc này mình có thể query theo regex: comments.path ^= 0001
thì sẽ lấy được tất cả comments của 0001
.
Làm nested comment như trang xem bài viết của Viblo cũng được nhưng chắc bạn nên cải tiến việc hiển thị comments theo một cách khác. Hiển thị như Viblo không phải là một cách hay, khi mà có quá nhiều cấp độ dẫn tới việc hiển thị theo dạng cây rất tệ về UI/UX. Giống như Callback Hell
trong javascript vậy.
Chuyển đồi thời gian sang giây
Nếu không muốn dùng moment bạn có thể dùng cách đơn giản sau để tính toán.
Với điều kiện là time
phải có đúng định dạng ở trên h:m:i
:
const timeString = '00:02:15';
const timeRange = timeString.split(':');
let seconds = 0;
timeRange.forEach((value, weight) => seconds += parseInt(value) * Math.pow(60, 2 - weight));
console.log(seconds)
Update thêm: Lỗi hiển thị kết quả trong code demo của chủ thớt.
Cái time trong code của chủ thớt cần chia 1000 để chuyển về second. comment #bq5QOwJGJZD
Sau đó, là lỗi hiển thị. Chủ thớt cần khởi tạo ở
00:00:00
trước rồi set giây sau cho nó nếu không nó sẽ tính ngày, giờ, phút hiện tại. Sửa lại sẽ theo comment #aGK7gXzQMKj như này:
moment("00:00:00", "HH:mm:ss")
.set("second", trimTime)
.format("HH:mm:ss")
Kiểm tra tất cả giá trị trong arr1 có tồn tại trong arr2 hay không
Mình thấy có nhiều cách lắm. Chắc là bạn chỉ cần duyệt một mảng và tìm kiếm đối chiếu ở mảng còn lại. VD một cách đơn giản như này:
const results = arr1.filter(item => arr2.includes(item.id))
if (results.length) {
// Found them
} else {
// Not found
}
Hỏi về custome login trong laravel, không kiểm tra được Auth::check()
Bạn thử kiểm tra xem default value cái guard
của bạn đang dùng là gì. Code login đã attempt vào đúng guard default đó hay chưa? Hoặc có thể thử Auth::attempt($credentials, $remember = true)
xem sao?
API
@MAINT Mình sẽ ví Zalo như là cái "ngân hàng" chứa thông tin cá nhân của tất cả người dùng trên Zalo. Bên ngoài ngân hàng có "một ông bảo vệ" gác cổng. Muốn vào ngân hàng lấy thông tin của một người dùng thì bạn phải xuất trình một tấm vé cho ông bảo vệ kiểm tra. Tấm vé này gọi là Access Token. Khi xuất trình một Access Token hợp lệ thì bạn có thể gọi API của Zalo để lấy thông tin của người dùng (được cho phép bởi người dùng) về hệ thống của mình và sử dụng.
Sau khi đăng ký một cái app zalo, để lấy Access Token hệ thống của bạn sẽ cần làm 2 bước. Trong đó, bước bạn thắc mắc là bước đầu tiên.
Các tham số:
app_id
: Là ID của cái app mà bạn vừa đăng ký ở trên. Có thể xem trong trang Quản lý ứng dụng.redirect_uri
: Là một cái đường link tới hệ thống của bạn, sẽ được zalo gọi ngược về hệ thống của bạn sau khi kết thúc bước 1 này, nó gọi là Callback URL. Cái Callback URL này phải giống như cái link mà bạn cài đặt trong trang Quản lý ứng dụng của mình nhé.state
: Là một chuỗi bất kỳ bạn chèn vào từ ứng dụng của bạn chèn, zalo ko dùng cái này, nó sẽ gửi trả lại vào trong cái trang redirect_uri kia cho bạn thôi.
Sau khi request cái API ở bước 1, hệ thống zalo sẽ yêu cầu người dùng đăng nhập vào zalo rồi xác nhận rằng họ đồng ý cấp quyền cho ứng dụng của bạn truy cập vào zalo để lấy thông tin cá nhân của người dùng đó. Nếu người dùng đồng ý, thì zalo sẽ sinh ra một cái mã gọi là oauth_code
, và gửi nó tới cái trang redirect_uri mà bạn vừa gửi cho zalo ở trên. Bạn sẽ sử dụng cái oauth_code vừa nhận được để thực hiện tiếp bước 2 và nhận Access Token.
Cách bảo mật API của project
Câu trả lời là không có cách nào để người ngoài không gọi được API của mình đâu nhé. Người ta chắc chắn sẽ gọi đến được dù bạn làm cách nào.
- Authentication chỉ là việc định danh người dùng. Sau khi login người ta vẫn có thể dùng được. Thậm chí là còn dùng tool để cho nó chạy tự động.
- Thông thường thì sẽ theo dõi IP qua access log, khi có bất thường thì cho vào blacklist và ban nó, thêm rate limit để giới hạn số requests có thể gọi.
- CORS cũng không phải là rào cản người ta dùng proxy là ko bị CORS nữa mà .
Gitlab bị permission denied mỗi khi mở terminal mới hoặc reboot máy
Có thể bạn sử dụng nhiều SSH Key không config nên mỗi lần reboot thì lại không ssh được. Bạn thử thêm config cho ssh vào file ~/.ssh/config
để mỗi lần sau khi khởi động lại thì nó đọc lại cấu hình từ file đó ra. Ví dụ:
# SSH config template:
Host <server-alias>
Hostname <domain | Static IP Address>
Port 22
User <username>
IdentityFile <path-to-you-SSH-private-key>
# SSH config example:
Host my-server
Hostname 192.168.2.23
Port 22
User TuanAnh9996
IdentityFile ~/.ssh/id_rsa
Câu lệnh để SSH vào server sau khi thêm config cho my-server
sẽ trở lên ngắn gọn như sau:
ssh my-server