Bạn ơi, mình làm phiền bạn thêm chút xíu nữa, trường hợp nếu mình khai báo hàm foo() bên trong hàm barr(), tức là code sẽ như thế này:
function bar() {
var a = 3;
function foo() {
var a = 2; //=> khi bỏ dòng này đi
console.log(a);
}
}
var a = 'Ahihi';
bar();
Tại sao khi bỏ dòng var a= 2 thì nó lại không log ra giá trị nào cả. Mình tưởng hàm foo() nằm trong Scope của hàm bar() nên nó có quyền truy cập vào biến var a = 3 => tức là nó sẽ in ra giá trị 3 chứ nhỉ. Trường hợp này giải thích thế nào hả bạn ?
Tất nhiên, sau khi bạn git add rồi commit ngay thì sẽ không sao. Còn bạn git add, xong sau đó vào chỉnh sửa file trong thư mục source thì git ko băm phần edit mới đó nhé, mà chỉ băm version bạn đã git add thôi.
Để tường minh mình sẽ có một folder test, bên trong có chứa 1 file test_commit.rb, trong file này có đoạn text this is test file. cd đến folder test, chạy git init sẽ có folder .git
Hiện tại bên trong folder objects ở trong .git có thể được coi là trống trơn
Sau đó thực hiện commit
$ git commit -m 'First time init'
Lúc này sẽ thấy thay đổi bên trong folder objects
Bạn chưa add mà, chỗ này nó sẽ không commit được.
$ git log --oneline
# Log commit
c83dd69 First time init
(END)
Nó sẽ ra như này:
LongNX@LPP00039344K MINGW64 ~/OneDrive/OneDrive - FPT Software/App/GoTiengViet (master)
$ git log --oneline
fatal: your current branch 'master' does not have any commits yet
Cám ơn bài viết của bạn.
Mình có thấy vài chỗ nhầm lẫn trong bài nên cho mình list ra nhé
Tính bảo mật
Eloquent ORM có tính bảo mật cao hơn QueryBuilder trong việc phòng chống SQL Injection.
Cái này chắc bạn đang nói đến kiểu viết bên dưới nhỉ
DB:raw('select * from users where id ='.$id);
Chúng ta có thể dùng PDO parameter binding để tránh khả năng SQL bị tấn công, nên mình nghĩ để tránh thì phải quán triệt dùng PDO binding với các bạn developer trong team
Vd:
DB::select('select * from users where id = :id',['id'=>$id]);
Note: Cẩn thận với whereRaw trong DB facade vì query sẽ không được escape
Hình như ví dụ này đã bị out of date so với version 5.6
Với Eloquent thì mình nghĩ sẽ dùng hàm pluck
User::pluck('name');
Còn với Query builder chúng ta dùng select thay vì dùng hàm lists (hàm list đã bị deprecated từ 5.3 thì phải)
DB::table('users')->select('name')->get();
Lưu ý đối tượng trả về là Laravel Collection chứ không phải array thông thường
8.Delete
$user->destroy();
Hàm destroy phải gọi static function chứ không phải instance function, và hàm destroy nhận vào ID của record muốn delete.
User::destroy(1);
Ngoài ra mình đồng tình với việc cú pháp code của Eloquent dễ hiểu hơn (về mặt business).
(Hiệu suất thì mình chưa bandwidth nên cũng chưa khẳng định được )
Nhưng thấy hơi không rõ ràng ở chỗ
Eloquent ORM dễ dàng kết nối với database hơn QueryBuilder.
Theo mình hiểu thì Eloquent, đến cuối cùng khi giao tiếp với tầng Database thì cũng sử dụng Query Builder
Chúng ta có thể tham khảo class Illuminate\Database\Eloquent\Builder để thấy rằng cuối cùng Eloquent cũng sử dụng Query Builder khi tương tác với DB
Có nghĩa là Eloquent là một wrapper về mặt business cho Query Builder, làm cho code dễ đọc hơn, và cũng cung cấp nhiều business methods hơn QueryBuilder như Eloquent Relationships, Soft delete, Eloquent Events...
Nên khi nói đến tính dễ dàng kết nối, mình nghĩ ORM base trên Query Builder nên sẽ không đánh giá.
@huuhau95 Khá hay khi bạn cố gắng tìm hiểu PHP thuần. Bạn cần chú ý trường hợp người dùng không chọn file tải lên.
Cụ thể trong ví vụ của bạn, nếu bạn không chọn file tải lên mà nhấn submit thì
Để giải thích hoàn toàn trả lời của mình, dùng mỗi lexical scope thôi là chưa đủ. Mà bạn còn phải dùng cả kiến thức của global scope - local scope nữa.
Cái đoạn code tương đương mà bạn đưa ra, chính xác hay không, phải phụ thuộc vào scope.
Việc giá trị của a là gì, sẽ được quyết định bởi scope của nó, và các outer scope (parent scope) bao quanh nó.
Giờ ta sẽ bắt đầu với từng dòng code một, theo đúng luồng chạy (execute code) của nó, cho bạn dễ hiểu. (Lưu ý là để cho bạn dễ hiểu thôi, mục đích là để giải thích cho bạn câu này, còn nếu giải thích chi tiết và chính xác nhất, thì mình e là làm bạn loạn mất)
Ta bắt đầu với var a = 'Ahihi'; Ta có một GLOBAL SCOPE, và khai báo một global variable a. Nó mang giá trị là 'Ahihi'
bar(); Ở đây ta bắt đầu gọi hàm bar, 2 hàm bar và foo đều đã được khai báo ở trên.
Ta sẽ bắt đầu chạy hàm bar, bắt đầu với dòng code đầu tiên là var a = 3;. Như mình vừa nói ở comment trên, parent scope của bar là global scope, nó ĐÃ KHAI BÁO MỘT global variable rồi, là a có giá trị 'Ahihi'. Vào trong đây, là một LOCAL SCOPE, và ta KHAI BÁO một giá trị a MỚI, đó là một local variable, trùng tên với a đã khai báo trước đó, nhưng mang giá trị là a = 3. Lưu ý là do khác scope, nên từ dòng code này trở đi, ta dùng giá trị của a, tức là ta sẽ động tới local scope, local variable a có gía trị là 3.
foo(); call hàm foo.
Bắt đầu chạy hàm foo, dòng lệnh đầu tiên là var a = 2; Lại giống như trên, foo tạo ra một LOCAL SCOPE mới, khác với local scope của bar, và parent scope của nó là ... GLOBAL SCOPE, ngoài ra, nó cũng khai báo một local variable MỚI, một biến a mới có giá trị là 2. Kể từ sau dòng lệnh này, BÊN TRONG function foo, bạn dùng giá trị a thì nó sẽ là a mới này (với giá trị là 2)
console.log(a); Nó sẽ in ra 2. Đương nhiên rồi, mình vừa giải thích ở bước chạy trên xong.
Giờ ta bỏ cái var a = 2 đi. Chuyện gì xảy ra? Javascript engine sẽ tìm outer scope, để xem có gía trị a đã khai báo nào không mà ta lại dùng ở đây. Và nó sẽ tìm đến parent scope, chính là GLOBAL SCOPE, và tìm được var a = 'Ahihi'.
Ở trên mình có nói, code tương đương mà bạn đưa ra chính xác hay không, phụ thuộc vào scope. Đấy là bởi, nó sẽ là đoạn code tương đương thật sự, nếu như function foo được khai báo bên trong bar, mục tiêu, là để scope của chúng theo đúng thứ tự phân cấp global scope -> bar scope -> foo scope.
Code tương đương mà bạn đưa ra, chỉ là luồng chạy của code. Còn javascript hiểu, và đọc giá trị như nào, là việc khác, và việc khác này, phụ thuộc vào Scope.
@quynh001 Cảm ơn anh đã phân tích rất hay và chi tiết. Em không coi đây là điểm yếu vì Laravel vẫn quá "pro" và vì em không giám chắc rằng mình viết được concrete nào "hay ho" hơn concrete mặc định của nó.
Giống như anh nói "trade-offs giữa sự đơn giản và tính đầy đủ ấy" và phân tích.
PHP là một duck typed language thay vì strong typed như trong một số ngôn ngữ khác như Java, .NET. Với các ngôn ngữ dạng strong typed, method signature trong interface thường phải định nghĩa cả kiểu cho parameters và kiểu trả về --> đảm bảo type safety. Trong PHP thì không như vậy thường sẽ ko có kiểu xác định. Do đó với PHP, các phương thức của một object sẽ xác định cách object đó có thể sử dụng thay vì phải phụ thuộc vào sự kế thừa từ một class khác hoặc một thể hiện cụ thể của interface. Tất nhiên PHP vẫn có thể là một strong typed nếu muốn
Em chỉ không thích phong cách code như vậy. Với em, khi đã viết interface và type-hint interface, chỉ nên gọi những phương thức đã được định nghĩa trên interface đó.
dạ vâng eloquent xây dựng sẵn sử dụng PDO nên nó theo 1 cấu trúc rồi ạ!, ý em là sử dụng code sql thuần mh có thể check được những cái mà mình nghĩ eloquent chưa đáp ứng được ạ!
mình có thắc mắc là trên trang jwt.io mình dễ dàng decode được chuỗi JWT mà ko cần khóa, nếu có ai đó lấy được chuỗi JWT mà user gửi lên thì hoàn toàn có thể lấy được quyền truy cập. V liêu JWT có an toàn ko nhỉ?
Mình dựa vào bài của bạn để làm đối với model User, sử dụng form request để validate trong controller. Trường hợp mình gửi ảnh đây là để trường name trống thì vẫn hiện thông báo lỗi. Ngay sau khi nhập name và để email trống thì console hiện báo như thế. Mình kiểm tra có báo yêu cầu không để trống email trong trình duyệt. Mong bạn có thể xem hộ mình.
THẢO LUẬN
Bạn ơi, mình làm phiền bạn thêm chút xíu nữa, trường hợp nếu mình khai báo hàm
foo()bên trong hàmbarr(), tức là code sẽ như thế này:Tại sao khi bỏ dòng
var a= 2thì nó lại khônglogra giá trị nào cả. Mình tưởng hàmfoo()nằm trongScopecủa hàmbar()nên nó có quyền truy cập vào biếnvar a = 3=> tức là nó sẽ in ra giá trị3chứ nhỉ. Trường hợp này giải thích thế nào hả bạn ?nice!
Bạn chưa add mà, chỗ này nó sẽ không commit được.
Nó sẽ ra như này:
Cám ơn bài viết của bạn. Mình có thấy vài chỗ nhầm lẫn trong bài nên cho mình list ra nhé
Cái này chắc bạn đang nói đến kiểu viết bên dưới nhỉ
Chúng ta có thể dùng PDO parameter binding để tránh khả năng SQL bị tấn công, nên mình nghĩ để tránh thì phải quán triệt dùng PDO binding với các bạn developer trong team
Vd:
Note: Cẩn thận với
whereRawtrong DB facade vì query sẽ không được escapeHình như ví dụ này đã bị out of date so với version 5.6
Với Eloquent thì mình nghĩ sẽ dùng hàm pluck
Còn với Query builder chúng ta dùng
selectthay vì dùng hàmlists(hàm list đã bị deprecated từ 5.3 thì phải)Hàm destroy phải gọi static function chứ không phải instance function, và hàm destroy nhận vào ID của record muốn delete.
Ngoài ra mình đồng tình với việc cú pháp code của Eloquent dễ hiểu hơn (về mặt business). (Hiệu suất thì mình chưa bandwidth nên cũng chưa khẳng định được
)
Nhưng thấy hơi không rõ ràng ở chỗ
Theo mình hiểu thì Eloquent, đến cuối cùng khi giao tiếp với tầng Database thì cũng sử dụng Query Builder
Chúng ta có thể tham khảo class
Illuminate\Database\Eloquent\Builderđể thấy rằng cuối cùng Eloquent cũng sử dụng Query Builder khi tương tác với DBCó nghĩa là Eloquent là một wrapper về mặt business cho Query Builder, làm cho code dễ đọc hơn, và cũng cung cấp nhiều business methods hơn QueryBuilder như Eloquent Relationships, Soft delete, Eloquent Events...
Nên khi nói đến tính dễ dàng kết nối, mình nghĩ ORM base trên Query Builder nên sẽ không đánh giá.
Cám ơn bạn nhiều nha, bạn giải thích rất chi tiết, đến đây thì mình mới hiểu được cặn kẽ hơn.
@huuhau95 Khá hay khi bạn cố gắng tìm hiểu PHP thuần. Bạn cần chú ý trường hợp người dùng không chọn file tải lên. Cụ thể trong ví vụ của bạn, nếu bạn không chọn file tải lên mà nhấn submit thì
Những giá trị của error phụ thuộc vào các hằng được khai báo ở đây http://php.net/manual/en/features.file-upload.errors.php
Để giải thích hoàn toàn trả lời của mình, dùng mỗi lexical scope thôi là chưa đủ. Mà bạn còn phải dùng cả kiến thức của global scope - local scope nữa. Cái đoạn code tương đương mà bạn đưa ra, chính xác hay không, phải phụ thuộc vào scope. Việc giá trị của
alà gì, sẽ được quyết định bởi scope của nó, và các outer scope (parent scope) bao quanh nó. Giờ ta sẽ bắt đầu với từng dòng code một, theo đúng luồng chạy (execute code) của nó, cho bạn dễ hiểu. (Lưu ý là để cho bạn dễ hiểu thôi, mục đích là để giải thích cho bạn câu này, còn nếu giải thích chi tiết và chính xác nhất, thì mình e là làm bạn loạn mất)var a = 'Ahihi';Ta có một GLOBAL SCOPE, và khai báo một global variablea. Nó mang giá trị là'Ahihi'bar();Ở đây ta bắt đầu gọi hàmbar, 2 hàmbarvàfoođều đã được khai báo ở trên.bar, bắt đầu với dòng code đầu tiên làvar a = 3;. Như mình vừa nói ở comment trên, parent scope củabarlà global scope, nó ĐÃ KHAI BÁO MỘT global variable rồi, làacó giá trị'Ahihi'. Vào trong đây, là một LOCAL SCOPE, và ta KHAI BÁO một giá trịaMỚI, đó là một local variable, trùng tên vớiađã khai báo trước đó, nhưng mang giá trị làa = 3. Lưu ý là do khác scope, nên từ dòng code này trở đi, ta dùng giá trị củaa, tức là ta sẽ động tới local scope, local variableacó gía trị là3.foo();call hàmfoo.foo, dòng lệnh đầu tiên làvar a = 2; Lại giống như trên,footạo ra một LOCAL SCOPE mới, khác với local scope củabar, và parent scope của nó là ... GLOBAL SCOPE, ngoài ra, nó cũng khai báo một local variable MỚI, một biếnamới có giá trị là 2. Kể từ sau dòng lệnh này, BÊN TRONG functionfoo, bạn dùng giá trịathì nó sẽ làamới này (với giá trị là 2)console.log(a);Nó sẽ in ra 2. Đương nhiên rồi, mình vừa giải thích ở bước chạy trên xong.Giờ ta bỏ cái
var a = 2đi. Chuyện gì xảy ra? Javascript engine sẽ tìm outer scope, để xem có gía trịađã khai báo nào không mà ta lại dùng ở đây. Và nó sẽ tìm đến parent scope, chính là GLOBAL SCOPE, và tìm đượcvar a = 'Ahihi'.Ở trên mình có nói, code tương đương mà bạn đưa ra chính xác hay không, phụ thuộc vào scope. Đấy là bởi, nó sẽ là đoạn code tương đương thật sự, nếu như function
foođược khai báo bên trongbar, mục tiêu, là để scope của chúng theo đúng thứ tự phân cấp global scope -> bar scope -> foo scope. Code tương đương mà bạn đưa ra, chỉ là luồng chạy của code. Còn javascript hiểu, và đọc giá trị như nào, là việc khác, và việc khác này, phụ thuộc vào Scope.mình login xong, gọi req.user thì nó không tìm thấy! ko biết lúc login xong user được lưu vào đâu?
@thangtd90 @vinhnguyen Hai anh phân tích đầy đủ và chi tiết quá. Em không thể accept hai câu trả lời được sao?
@quynh001 Cảm ơn anh đã phân tích rất hay và chi tiết. Em không coi đây là điểm yếu vì Laravel vẫn quá "pro" và vì em không giám chắc rằng mình viết được concrete nào "hay ho" hơn concrete mặc định của nó.
Giống như anh nói "trade-offs giữa sự đơn giản và tính đầy đủ ấy" và phân tích.
Em chỉ không thích phong cách code như vậy. Với em, khi đã viết interface và type-hint interface, chỉ nên gọi những phương thức đã được định nghĩa trên interface đó.
rất hay
dạ vâng eloquent xây dựng sẵn sử dụng PDO nên nó theo 1 cấu trúc rồi ạ!, ý em là sử dụng code sql thuần mh có thể check được những cái mà mình nghĩ eloquent chưa đáp ứng được ạ!
Mình nghĩ là bạn nên đưa thêm 1 số thông tin như là bạn sẽ quản lí, lưu trữ những gì, mục đích ra sao thì sẽ dễ hỗ trợ hơn.
Hay
Nếu đã biết có "sơ sót", và "sơ sót" đó là gì, b nên nêu ra trong câu hỏi, để mọi người không mất thời gian để xem tất cả các bảng đó.
good
Đoạn trên em viết ntn cơ mà
mình có thắc mắc là trên trang jwt.io mình dễ dàng decode được chuỗi JWT mà ko cần khóa, nếu có ai đó lấy được chuỗi JWT mà user gửi lên thì hoàn toàn có thể lấy được quyền truy cập. V liêu JWT có an toàn ko nhỉ?
dạ vâng a? em nghĩ dùng db raw thì code bảo mật sẽ chặt chẽ hơn chứ anh?