Cho mình hỏi về steps trong Css với !
steps
ở đây là tên một class thôi bạn ạ.
.header .menu-btn:checked ~ .menu-icon:not(.steps) .navicon:before,
Tức là khi button .menu-btn
được check tương ứng với việc mobile menu được mở thì tất cả element có class .navicon
bên trong .menu-icon
kế tiếp ngay sau .menu-btn
mà .menu-icon
này không chứa class steps
thì sẽ có top: 0
. Và top: 0
này chỉ áp dụng cho phần before
.
Cách viết laravel để tiện cho người dùng
Ý em là làm Menu điều hướng ở trên website có thể được thay đổi trong Admin à.
- Thêm/sửa/xóa một menu item.
- Menu item được thêm có thể là Danh Mục của hệ thống hoặc không phải Danh mục tức nhập tay gồm: Tiêu đề, URL, vị trí.
Như vậy, a nghĩ e có thể tham khảo, mình tạo một bảng menu lưu danh sách menu item. Menu item có các thuộc tính:
- label: Tên được hiển thị trên menu
- url: Đường dẫn tới trang đích khi click vào menu item
- category_id: ID của danh mục (nếu menu item liên kết tới một danh mục hệ thống trong trường hợp thêm dựa trên category). Cũng là để phân biệt menu item là danh mục hay là nhập tay.
- parent_item_id: ID của menu item cha chứa nó.
- position: Số thứ tự của item đó trong danh sách menu.
Về giao diện quản trị, nếu để thuận tiện cho người admin thì anh nghĩ cứ show danh sách menu item ra, hiển thị theo nhóm theo parent_item_id. Mỗi menu item có một icon hỗ trợ kéo thả (hoặc không thì nút click up/down) để thay đổi vị trí menu item trong danh sách; Một icon để chỉnh sửa menu item; Một icon để xóa.
Khi thêm mới menu item lúc nhập tên có có thể search theo tên danh mục, hiển thị dạng auto complete. Nếu được chọn, thì lưu thêm category_id để liên kết tới danh mục. Trường hợp không liên kết thì cứ lưu lại label, url position như bình thường.
Về việc hiển thị thì mình query hết menu item ra rồi, nhóm phân cấp theo parent_item_id/ sắp xếp theo position bằng PHP. Hoặc em query lần lượt theo parent_item_id cũng được. Sau khi log ra một danh sách theo thứ tự đúng thì lúc hiển thị có thể làm kiểu đệ quy. Ngoài ra, vì menu thì ít thay đổi nên sau khi có được danh sách đã sắp xếp, em cache forever nó lại. Lần đầu thì query từ db, nhóm sắp xếp. Lần thứ 2 thì lấy trong cache ra. Sau này, mỗi khi admin thêm sửa xóa thì em xóa cache đi là được.
Ngoài ra nữa là, thay vì dùng parent_item_id em có thể nghĩ ra cách nào đó như quản trị theo cách nhóm menu chẳng hạn... Và nếu yêu cầu của hệ thống không cần làm đến mức kéo thả/auto complete như a nói thì đừng làm. Nhất là nếu outsource, thì làm đúng đủ theo yêu cầu khách hàng thôi nhé.
url() và route()
Nếu cái route đấy dùng nhiều thì mình thường sẽ dùng route($name)
thay vì url
. Lý do là khi mình thay đổi url, giữ nguyên route name thì sẽ không phải sửa các chỗ gọi hàm nữa.
Lỗi throttle trong Laravel
cái này 'throttle:60,1'
- TH1: Nếu đã đăng nhập: Là cho phép user được truy cập tối đa 60 request / 1 phút tới các apis tương ứng.
- TH2: Nếu chưa đăng nhập: Là cho phép client có IP
xxx.xxx.xxx.xxx
được truy cập tối đa 60 request / 1 phút tới các apis tương ứng.
Thứ tự check: Check TH1 sau đó mới check TH2.
Nếu bạn test dưới local, chưa đăng nhập thì tất cả các client đều chung IP loopback nên có thể làm bạn nghĩ là cả server die luôn.
cái này 'throttle:60,1'
Chú ý: Nếu được sử dụng ngay trong kernel mặc định thì tức là nó đang áp dụng cho toàn bộ apis.
About session when make app with vuejs and nodejs.
Session lưu ở backend ấy em ơi.
Nhờ giúp đỡ căn nội dung theo chiều cao trong FlexBox
Bạn thêm CSS như sau là được:
.content {
display: flex;
align-items: center;
}
em khởi động php artisan bị lỗi này, bác nào biết fix chỉ em với : bash: winpty: command not found. em cảm ơn ạ
MÌnh ko dùng thằng gitbash này nên mình không rõ lỗi này như nào. Thường trên windows, mình sẽ:
- Sử dụng luôn
Powershell
/cmd
để chạy một dòng lệnh cho tiện. - Ngoài ra, sau này làm việc trên Linux nhiều nên mình cài
Cygwin
để mình có thể thực hiện các câu lệnh Linux ở trong môi trường Windows.
Bạn thử chuyển sang dùng 1 trong hai cách trên của mình xem sao nha.
Nhờ giải thích giá trị biến i trong đoạn Code
Bạn có thể hiểu đơn giản sự khác nhau giữa var
và let
là phạm vi mà biến đó còn có thể lấy ra giá trị hoặc thay đổi giá trị của nó.
var a = 10
: Sau khi khai báo thì biếna
có thể lấy ra giá trị hiện tại là10
, hoặc bị thay đổi ở bất cứ đâu. Dù bạn khai báovar a
bên trong một function nhưng vẫn còn có thể dùnga
ở ngoài function đó. Vì thế nên 5 function sử dụng chung biếna
, một trong 5 function thay đổi giá trị củaa
thì 4 function còn lại cũng sử dụng giá trị đã bị thay đổi.let a = 10
: Sau khi khai báo thì biếna
chỉ có thể sử dụng ngay bên trong function đầu tiên mà chứa lệnh khai báo biếna
. Ngoài function đó, biếna
không còn tồn tại.
Trong ví dụ của bạn:
var i
,i
được khởi tạo ở lần lặp đầu tiên, các lần lặp sau sử dụng lại biếni
lần lặp trước đó. Cả 5 lầnconsole.log(i)
đều hiển thị giá trị của cùng một biếni
và đều có thể thay đổi giá trị của i. Vìconsole.log
đặt bên trongsetTimeout
nên ra khỏi vòng fori
tức khi kết thúc lần lặp thứ 5 vài
đã bị gán thành5
mất rồi thì mới hiển thị giá trị đã bị thay đổii = 5
.let i
,i
sẽ được khởi tạo lại sau mỗi lần lặp. Nên mỗi lần lặp nắm giữ một biếni
khác nhau. Kết thúc vòng lặp for, hiển thị giá trịi
của từng lần lặp là khác nhau.
Lấy thông tin người dùng để show notification
Cách hoạt Notificaion hoạt động
@minhtuancnttk39 Ý bạn là: Người dùng U1 comments bài post của ông U2. Notification báo về cho U2 rằng ông U1 đã comment vào bài viết. Chúng ta sẽ coi U1 là người đóng vai trò gửi notification ở đây.
- Cách 1: Bạn có thể lưu thêm
sender_id
tức id của người dùng U1 - tác nhân dẫn tới gửi notification. Lưu thêm sender_id như vậy thì việc truy vấn sẽ linh hoạt hơn sau này. - Cách 2: Ngoài ra, nếu chỉ để hiển thị thông tin người gửi ra cho U2 thôi thì bạn có thể return thêm thông tin người người qua method:
toDatabase
hoặctoArray
bên trong class Notification.
public function toArray()
{
return [
'sender' => [
'id' => 1,
'name' => 'Nguyen Huu Kim',
'avatar' => 'da1ad1-fdsafa',
'url' => '/u/huukimit',
],
];
}
Implement theo Cách 1
Cách 2 đơn giản hơn, tuy nhiên nó không linh hoạt, giả sử như avatar U1 thay đổi thì dữ liệu notification ko thay đổi, U1 vẫn thấy thông tin cũ. Hay trang /u/huukimit
thay đổi, khi click vào notification cũ sẽ bị lỗi. Bởi vậy nên mình nói là nó ko linh hoạt.
Trước hết, bạn cần hiểu thêm một chút về hoạt động của Notification. Chúng ta có khái niệm Channel, tạm hiểu là một kênh để thực hiện vận chuyển thông tin của notification đi tới đích.
Chẳng hạn:
- Để gửi realtime notification tới người U2, Dữ liệu Notification được gửi qua
BroadcastChannel
. - Để lưu vào database, dữ liệu của notification được gửi qua
Illuminate\Notifications\Channels\DatabaseChannel
. - Sau này để push notification, bạn có thể tạo thêm một Channel riêng như
FirebaseCloudMessageChannel
chẳng hạn.
Thực hiện lưu thêm sender_id
Một Notification có thể gửi qua nhiều Channels. Tất nhiên chúng đều có một method cần implement có tên là send
. Và bạn đã biết DatabaseChannel
là nơi thực hiện lưu dữ liệu vào database.
Để lưu được sender_id, bạn thực hiện các bước sau giúp mình:
- Tạo một migration mới, thực hiện thêm column sender_id vào table notifications.
- Tạo một
DatabaseChannel
mới, thực hiện overwrite lại methodsend
. Ở đây bạn lưu thêm mọi thứ tùy ý bạn, không chỉ có sender_id.
Lấy thông tin sender:
Đến đây mọi thứ đã sáng tỏ và bạn có thể dễ dàng database query, join notification tới table users và lấy được thông tin sender_id. Chúng bạn thành công.
UPDATE LARAVEL 5.6
- Kể từ phiển bản laravel 5.6,
buildPayload
method được thêm mới vàoDatabaseChannel
. Methodsend
sẽ gọi sangbuildPayload
để lấy dữ liệu thay vì tự định nghĩa bên trong nó. Chính vì thế, chúng ta overwritebuildPayload
thay cho overwritesend
để lưu thêm dữ liệusender
. - Ngoài ra, mình bổ sung thêm để câu trả lời được hoàn chỉnh hơn, chúng ta cần thêm method
via
trong class của những Notification cần lưu vào database (Chắc có lẽ là hầu hết). Return một array chứa tên classCustomDatabaseNotification
- làDatabaseChannel
đã tự tạo ở trên. Như vậy channelCustomDatabaseNotification
mới được áp dụng.
Lỗi 502 bad gateway khi cài PHP7.0-FPM cho máy chủ Nginx-1.13.12
Bạn có thể check config syntax trước:
nginx -c /etc/nginx/nginx.conf -t
Rồi tham khảo config này xem sao:
server {
server_name localhost;
listen 80;
root /var/www/html;
index index.php index.html index.htm;
charset utf-8;
access_log /var/log/nginx/access.log;
location / {
try_files $uri /index.php$is_args$args;
index index.php index.html index.htm;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
V/v chặn và pop-up modal upload ảnh khi dùng markdown Simplemde
Bạn đọc lại document về Toolbars
của SimpleMDE nhé, phần toolbars có một action
là image
:
Nguồn: https://github.com/sparksuite/simplemde-markdown-editor
Cụ thể họ có ví dụ rất rõ ràng:
Customize the toolbar using the toolbar option like:
// Customize only the order of existing buttons
var simplemde = new SimpleMDE({
toolbar: ["bold", "italic", "heading", "|", "quote"],
});
// Customize all information and/or add your own icons
var simplemde = new SimpleMDE({
toolbar: [{
name: "bold",
action: SimpleMDE.toggleBold,
className: "fa fa-bold",
title: "Bold",
},
{
name: "custom",
action: function customFunction(editor){
// Add your own code
},
className: "fa fa-star",
title: "Custom Button",
},
"|", // Separator
...
],
});
Không kết nối laravel với Oracle database được
Laravel không support Oracle bạn nhé. Tuy nhiên bạn cài thêm package này để thêm Oracle driver: https://yajrabox.com/docs/laravel-oci8/master
V/v upload ảnh và quản lý ảnh trên website
Mình thấy hướng đi của bạn đúng rồi đấy! Nhưng bạn có thể mở rộng bảng images
thành uploads
, lưu thông tin của tất cả các file được upload lên không chỉ giới hạn là Image mà có thể là Video
, Document
... Sử dụng relation Polymorphic
của Laravel trong trường hợp đấy rất hiệu quả. Còn nếu không cần thiết thì bạn dùng bảng images
như kia cũng được. Có thể lưu thêm các thông tin khác như: file size, file name, file extension, path/to/folder... Có thể nó sẽ cần thiết khi bạn hiển thị danh sách các file được upload.
Đối với việc hiển thị hình ảnh, bạn có thể hiển thị qua một url riêng biệt dựa trên id của model Upload
.
VD với Viblo:
Ảnh avatar: https://images.viblo.asia/avatar/005d826e-8b0c-4421-b95f-a5fd1eb85d54.jpg
Ảnh thumbnail: https://images.viblo.asia/thumbnail/005d826e-8b0c-4421-b95f-a5fd1eb85d54.jpg
Ảnh gốc: https://images.viblo.asia/full/005d826e-8b0c-4421-b95f-a5fd1eb85d54.jpg
URL hiển thị ảnh được tính toán sắp đặt sẵn, nếu có thay đổi cấu trúc thư mục lưu file thì tất cả các đường dẫn hình ảnh kia vẫn sẽ hoạt động bình thường trong bài viết của bạn.
Với ID, thay vì dùng id
- Integer và auto increment, bạn nên sử dụng dạng hash id như: uuid
, hay md5
... Chẳng hạn như ví dụ ở trên, Viblo sử dụng chuỗi hash 005d826e-8b0c-4421-b95f-a5fd1eb85d54
thay cho id nguyên thủy.
Selector in Jquery
Giải pháp làm nhiều form như thế kia có vẻ không ổn vì phải trả lại nhiều html dư thừa. Tuy nhiên nếu đang làm cách trên thì mình nghĩ bạn có thể sử dụng event onsubmit
của form
tag thay vì bắt sự kiện click button.
<form method="POST" class="form-comment" onsubmit="alert(1)">
<textarea></textarea>
<div class="form-group clearfix">
<button type="submit">Post Reply</button>
</div>
</form>
Làm sao để search ra item là object trong 1 listview
Custom lại Adapter
Theo mình vấn đề của bạn đang gặp phải là ở chỗ filter. Bạn có thể viết thêm một public method vào adapter như này chẳng hạn:
# NodeAdapter
public boolean filterByNodeTitle(String newText) {
IList filtered = new List();
foreach(NodeModel note in this.notes) {
if (note.title.toString().Contains(newText)) {
filtered.Add(note);
}
}
this.notes = filtered;
// Thông báo cho ListView thay đổi:
NotifyDataSetChanged();
}
# activity:
public boolean onQueryTextChange(String newText) {
adapter.filterByNoteTitle(newText);
}
Hoặc là bạn có thể custom lại getFilter()
, hàm này return ra một instance Filter
khác, lớp Filter
này có method filter()
chính là method filterByNoteTitle()
ở trên.
Bạn thử xem nhé, chúc bạn thành công. À mà cá nhân mình lại thích dùng RecyclerView hơn là ListView. hihi
Auto create image when register new account without upload avatar. How can we do that?
Phân tích vấn đề
Xin chào bạn, câu hỏi bạn đặt ra mình xin tách làm 2 vấn đề:
- Thứ nhất, vấn đề tạo ra từ viết tắt
- Thứ hai, vấn đề về tạo ảnh
Vấn đề tạo từ viết tắt
Mình nghĩ vấn đề này ko có gì khó đối với bạn, mình nên tạo một quy tắc cho tên viết tắt:
VD: Tên: Nguyễn Hữu Kim
, giả sử quy tắc là từ đầu tiên là First name, viết hoa chữ cái đầu, các ký tự tiếp theo sau là viết tắt của họ đệm - viết in hoa. Sử dụng tiếng Việt không dấu. Khi đó:
Nguyễn Hữu Kim => Tên viết tắt: KimNH
Với quy tắc trên, cách làm là:
- Chuẩn hóa chuỗi họ đệm, tên về dạng không dấu, mỗi từ chỉ cách nhau một dấu cách. Có thể sử dụng các helper:
trim
,str_replace
vàstr_slug
... - Lấy ra các ký tự viết tắt từ họ đệm. Có thể sử dụng helper:
str_explode
theo dấu cách rồi lấy ký tự đầu tiên, hoặc sử dụngregex
. Sau đó nối Tên + Các ký tự viết tắt lại. (tạm thời bỏ qua TH tên có nhiều hơn 1 từ. VD: Lan Anh).
Vấn đề tên viết tắt tạm thời được giải quyết. Mỗi quy tắc bạn sẽ có cách giải quyết tương ứng nên phần này phải dựa vào quy tắc của bạn.
Vấn đề tạo ảnh từ tên viết tắt.
Vấn đề này hết sức đơn giản, bạn sử dụng: https://placeholdit.imgix.net là xong. Place Hold It sẽ tạo ảnh từ một text mà bạn gửi lên. VD: https://placeholdit.imgix.net/~text?txtsize=17&txt=JavaScript&w=100&h=100&txttrack=0
Kết quả:
Bạn có thể thay thế các tham số:
- txt: Tên viết tắt đã tạo
- txtSize: Font size cho từ sẽ tạo ra trong ảnh.
- w: Chiều rộng
- h: Chiều cao
Bạn có thể đọc thêm tại trang document của https://placeholdit.imgix.net.
Hỏi về Fabric js
Mình có xem qua demo của bạn, mình thấy bạn bị lỗi chút style. Bạn nên kiểm tra lại style của canvas thứ 2. Bằng một lý do nào đó, default background của canvas thứ 2 bị mất. Mình có enable lại background cho canvas 2 thì khung iphone sẽ hiển thị lại:
À mà hình như trong hình mình sửa background cho thẻ canvas
chứ ko phải canvas thứ 2.
Học web
Câu hỏi thật khó để em đưa ra lời khuyên vì không nắm được tình hình học tập, công việc hiện tại của anh. Nhưng có một điều em chắc chắn rằng là Nếu anh thực sự yêu thích lập trình thì 25 tuổi chưa phải là muộn.. Em có anh đồng nghiệp cũ, sinh năm 87. Tháng 6 năm 2016 (29 tuổi) anh ý cũng mới bắt đầu học lập trình Android. Hiện tại thì anh ý lại vào FPT làm Lập trình nhúng cho IOT. Tất nhiên là các anh sẽ phải cạnh tranh với những bạn trẻ hơn rồi. Nhưng sẽ chưa bao giờ là quá muộn để theo đuổi đam mê của mình. Tin em đi, 25 tuổi chưa muộn đâu. Chúc anh thành công!
Lỗi search like trong Laravel (search chữ d và đ)
Thực tế thì việc sử dụng like trong MySQL để làm chức năng tìm kiếm cho tiếng Việt không được hiệu quả. Có hai cách đơn giản nhất mình có thể giúp bạn:
- Cách 1: Bạn có thể chuyển từ khóa tìm kiếm về dạng tiếng Việt không dấu rồi truy vấn dựa trên từ khóa đó. Cách này hơi tù. Không nên dùng.
- Cách 2: Bạn có thể tìm hiểu và sử dụng full-text search trong MySQL để tìm kiếm. Việc implement full-text search cũng khá đơn giản. Đặc biệt nó có thể giải quyết được vấn đề search tiếng Việt, tốc độ nhanh. Mình nghĩ bạn nên dùng cách này. Bạn có thể đọc thêm về Full text search trên Viblo tại: https://viblo.asia/tags/fulltext-search.
async/await - foreach & for
Như bạn đã biết, tham số callback
là sự khác biệt cơ bản nhất giữa hai cách sử dụng vòng lặp Array.forEach
và for
. Bởi forEach hoạt động với tư tưởng, lặp qua và phần tử trong mảng và truyền nó vào hàm callback. Như vậy callback thực chất được gọi bên trong forEach. Và bạn thấy, forEach được define mà không có async/await nên Promise wait(1000)
của bạn sẽ không có tác dụng.