Mọi người đang thiết kế DB để lưu bài viết và tương tác giữa user với nhau như nào?
Mình nghĩ về cấu trúc DB có thể làm như này:
-
Bảng users để lưu tài khoản người dùng
-
Bảng subscriptions để biết được người dùng đăng ký theo dõi gì. Sử dụng relation
Polymorphic Relations
của laravel, mình dùng relation này thì thêm 2 colums làsubscribable_id
,subscribable_type
. Để phân biệt được các đối tượng được người dùng đăng ký theo dõi, vd:
- subscribable_id: 100
- subscribable_type: Post | User
-
Bảng comments để lưu bình luận của người dùng Nếu người dùng comment được cho nhiều loại đối tượng thì mình lại dùng
Polymorphic Relations
giống subscriptions ở bên trên. -
Phần thông báo thì sử dụng chức năng notification của Laravel nó sẽ tạo table cho mình.
-
Về việc gửi thông báo thì là xử lý trong code của mình thôi.
Người dùng có thể bình luận và nhận được thông báo từ những bình luận khác trong bài viết mà mình đã bình luận
Tức là bạn muốn gửi thông báo tới tất cả những ai cùng comment trong bài đấy. Khi người dùng A tạo comment thì mình lấy tất cả người cùng comment trong bài viết đấy và gửi thông báo tới họ. Chung quy phần này là xử lý logic trong code thôi.
Crawl Website
Lấy source code của website về là điều không thể nếu source code là private. Bạn chỉ có thể lưu lại html, css, image về tham khảo giao diện mà thôi. ha ha ha. 😜😛😝
Xử lý register của viblo
@johndoe Sau khi bạn làm theo flow OAuth2 và bạn lấy được thông tin người dùng từ bên thứ 3. Bạn lưu thông tin người dùng này vào session rồi redirect về trang register. Ở trang register bạn lấy lại thông tin người dùng vừa nãy từ session ra rồi fill vào form để người dùng tiếp tục quá trình đăng ký. Vì thông tin này chỉ dùng một lần nên bạn dùng kiểu flash session là đủ.
vhost trên Ubuntu bị trỏ về domain http://example.com/
Chỉ có domain trỏ về server/host thôi chứ bạn. Bạn check xem domain của bạn trỏ về đúng host chưa hay đang cài đặt redirect sang example.com.
Javascript: Hỗ trợ bài tập
Lỗi báo ra là gì vậy cậu? Có lẽ là cậu chưa lấy được data từ file nên khi dùng indexOf với undefine
sẽ bị lỗi. Câu thử kiểm tra coi đã lấy được input và target từ file json ra chưa. Cách lấy thì đơn giản lắm:
// ES5:
const data = require('./input.json')
// ES6:
import data from './input.json'
console.log(data)
Tư vấn cách làm trang news feed
@TuanAnh9996 Nếu cậu dùng SQL thì có thể dùng UNION ALL
để nối nhiều câu truy vấn lấy dữ liệu làm một câu truy vấn duy nhất. Kết quả sẽ là tổng hợp kết quả của các câu truy vấn được nối. Điểm lưu ý là mệnh đề select trong các câu truy vấn phải lấy ra field name như nhau. Trong case của cậu là lấy dữ liệu từ bảng Câu hỏi
và bảng Tin tuyển dụng
.
Cú pháp mẫu dạng như này:
SELECT *
FROM (
query_1
UNION ALL
query_2
UNION_ALL
query_3
...
) as results
....
Example:
SELECT *
FROM (
SELECT title, created_at FROM questions
UNION ALL
SELECT name as title, created_at FROM jobs
) as new_feeds
ORDER BY new_feeds.created_at DESC
document.execCommand("copy") not working !!!!
Mình nghĩ vấn đề nằm ở cái async/await
bạn gọi. Bạn thử console.log(result)
xem có data trả về không? Mình đoán nó return undefined
nên không copy được gì vào clipboard cho bạn. Chứ cái đoạn xử lý copy vào clipboard ở bên dưới là đúng rồi đấy bạn.
Thêm ma trận
Bạn có thể nói cụ thể hơn được ko? Chứ nếu chỉ là array bình thường có cấu trúc như kia thì khai báo như này là xong mà:
>>> a = [1, 2, 3, 4]
>>> a
[1, 2, 3, 4]
>>> b = [a, a, a, a]
>>> b
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
Nhưng mình nghĩ chắc là ko phải như mình nghĩ bên trên.
Call to undefined function trong lavarel
Bạn chạy lại lệnh dưới đây xem có được không:
composer dump-autoload
Vì sau mỗi lần add file vào autoload mình cần generate lại file autoload.php
để nó nạp file mới vào code.
Cách tạo 1 web xem phim
Nếu chỉ là share video lập trình thì mình nghĩ bạn upload video lên youtube. Nơi có thể share video và mọi người cũng rất dễ tìm kiếm. Thêm vào việc bạn tạo trang web thì chỉ cần nhúng video youtube vào là xong. Việc nhúng video youtube thì dễ như ăn bánh rồi. Còn nếu bạn muốn tạo web xem phim để kinh doanh kiếm lời thì trước tiên mình nghĩ bạn nên cân nhắc vấn đề bản quyền. Cá nhân mình thì không ủng hộ các website xem phim lậu tại Việt Nam. Ngược lại còn muốn tẩy chay chúng.
Lưu và thay đổi dữ liệu trong quan hệ nhiều nhiều.
C1: Dùng hai api thêm và xóa riêng
Nếu bạn dùng hai api thêm và xóa role của user riêng.
- Khi gọi api xóa thì post một mảng danh sách role_id lên rồi tìm và xóa nếu có:
DELETE FROM UserRole WHERE user_id = ? and role_id in (?, ?, ?)
- Khi gọi api insert role thì insert các records vào nếu chưa có:
VD: Mẫu query thêm role 10, 20, 30 cho user 1 vào bảng UserRole, nếu các role này chưa có trong DB. Role nào có thì không thêm mới nữa.
INSERT INTO UserRole (user_id, role_id)
SELECT *
FROM
(
SELECT 1 as user_id, 10 as role_id FROM UserRole
UNION ALL
SELECT 1 as user_id, 20 as role_id FROM UserRole
UNION ALL
SELECT 1 as user_id, 30 as role_id FROM UserRole
) AS TEMP
WHERE NOT EXISTS (SELECT * FROM UserRole WHERE role_in IN (10, 20, 30) AND user_id = 1)
C2: Không dùng hai API
Tức dùng chung 1 api, api này nhận dữ liệu vào là mảng các role_id cần giữ cuả User (bao gồm cả role mới và cũ). Và hệ thống tự sync (xóa những role ko có, thêm những role mới).
VD: Xóa role 10, 20, thêm mới role 40, 50. Khi đó mảng roles_id đẩy lên gồm: [30, 40, 50] Lúc này bạn chạy 2 cây truy vấn, làm như sau:
- Chạy câu truy vấn xóa toàn bộ những role không có trong params đẩy lên, tức những role đã bị xóa. => role_id not in (30, 40, 50) bị xóa <=> role 10, 20
- Chạy câu truy vấn insert toàn bộ role trong params đẩy lên vào db (gồm cả role đã lưu và role mới). Thực hiện giống y hệt mục 2 ở trên. => Insert 30, 40, 50 nếu chưa có.
Kết luận
Trên đây là một cách triển khai chỉ mất 2 câu truy vấn, bạn cũng ko cần phải quan tâm role cũ hay mới, tồn tại hay không, không phải xử lý tách role cũ, mới rồi mới thực hiện truy vấn.
Search giống like trong elastichSearch
Mình chưa dùng thư viện này bao giờ và thực sự cũng chưa biết bạn đang dùng thư viện nào :v, nhưng câu truy vấn Elastic search cơ bản để search một field như ý bạn như sau:
{
"body": {
"query": {
"match": {
"<field_name>": "There are keywords"
}
}
}
}
Còn nếu bạn muốn search theo nhiều fields thì câu truy vấn cơ bản như sau:
{
"body": {
"query": {
"multi_match": {
"query": "There are keywords",
"fields": [
"first_field",
"second_field"
]
}
}
}
}
Bạn tham khảo documentation: tại đây
thay đổi thư mục test mặc định trong Laravel để test Browser
- Move toàn bộ test cũ sang thư mục mới. VD: Move từ
tests
sang thànhnew-directory/tests
. - Update
namespace
cho test qua autoload trong filecomposer.json
. - Build lại composer autoload, chạy lệnh:
composer dump-autoload
- Sửa lại phần require tới
boostrap/app.php
trongTestCase.php
hoặc trong các class test case của bạn cho đúng với đường dẫn thư mục mới. - Update lại file
phpunit.xml
ở root directory theo mẫu dưới (gồm attribute bootstrap ở phpunit (nếu có hoặc để mặc địnhvendor/autoload.php
), sửa đường dẫn mới ở thẻ directory):
<phpunit bootstrap="new-directory/tests/bootstrap.php">
<testsuites>
<testsuite name="My Project Test">
<directory suffix="Test.php">./new-directory/tests</directory>
</testsuite>
....
</testsuites>
</phpunit>
MỘT VÀI CÂU HỎI VỀ THƯ VIỆN SIMPLE MDE SỬ DỤNG TRONG VIBLO
Bạn trình bày câu hỏi hại não quá!
SimpleMDE là Markdown editor, nó base trên CodeMirror và bộ markdown parse có tên là marked.
Hai vấn đề bạn đang gặp phải là:
- Click toolbar icon => Thay đổi nội dung hiển thị ra từ markdown. (Thay đổi thẻ anchor)
- Hiển thị html trong tài liệu markdown mà người dùng nhập. (Code html không nằm trong ``` theo cú pháp markdown)
Tất cả vấn đề này chung quy chỉ là render markdown thành html. Giải pháp, custom bộ render preview mặc định của SimpleMDE thay vì cách như bạn đang nghĩ.
Bạn có thể sử dụng bộ render markdown của Viblo trong Viblo SDK (javascript) tại: https://github.com/viblo-asia/sdk-js ; Hoặc tự custom theo document của SimpleMDE, sử dụng vẫn sử dụng marked hoặc markdown-it. Btw, bạn cũng có thể tham khảo các OpenSource khác của Viblo tại: https://viblo.asia/tools.
Updated: Sr mn, mình có chút nhớ nhầm. Bộ parse mặc định là marked chứ ko phải markdown-it
Sleep in Laravel
sleep
là một hàm của PHP, chương trình sẽ chạy nghỉ ở lời gọi hàm sleep với số giây tương ứng. Rồi mới chạy tiếp.
echo time() . ': Tam dung 10s';
sleep(10);
echo time() . ': Het 10s';
Hỏi về cách truyền 1 mảng trên route
dạ cái này em làm gửi gmail để xác nhận ạ, khi người ta click vào link xác nhận mình sẽ lưu thông tin vào csdl, nên phải truyền qua route ạ.
Câu hỏi của bạn đặt chưa rõ ràng, vấn đề của bạn đang gặp chả liên quan gì tới câu hỏi bạn đặt cả. Mình nói thật đấy!
Mình nhắc lại flow gửi mail xác nhận một chút, giả sử trong tính năng đăng ký tài khoản nhé:
- Người dùng đăng ký tài khoản công
- Tạo một activation token, là một chuỗi ngẫu nhiên, dài loằng ngoằng và unique.
- Lưu nó vào bảng activation_tokens (user_id, token)
- Hệ thống gửi email xác nhận
- Trong email xác nhận có một cái link, cái link này chứa token ở trên để xác thực rằng người đăng ký tài khoản cũng là chủ nhân email.
- Người dùng click vào link xác nhận trong email, chuyển sang trang web của mình. (tạm gọi là route confirm nhé)
- Hệ thống lấy token từ url, sau đó cầm nó tìm trong database xem là của tài khoản nào.
- Nếu ko matched được thông tin user, thì báo lỗi và không làm gì cả.
- Nếu matched thì thực hiện active tài khoản đấy, hoặc cập nhật gì đó lại vào database rồi xóa bỏ activation token.
Như bạn thấy, trong tính năng gửi email xác nhận ở trên chúng ta chỉ cần dựa vào activation token mà thôi. Và cái route confirm đấy nó có một params chính là chuỗi activation token.
Custom Upload ảnh trong simplemde-markdown-editor
Bạn có thể đặt một thẻ <input type="file" style="display:none"/>
vào trong form. Sau đó, ở trong callback action:
const inputFile = document.querySelector('#hidden-input-file');
...
{
name: "image",
action: () => inputFile.click()
}
Tại sao lại là Vuejs
Trước hết bạn nên phân biệt jQuery chỉ là một bộ thư viện javascript hỗ trợ trong quá trình code trong khi Vue.js thì là một framework (bao gồm rất nhiều thành phần con như: router, view), tuy nhiên, mặc định Vue chỉ đóng vai trò render View để hiển thị, các thành phần con này được tách biết hoàn toàn, nếu bạn cần dùng thì bạn cài thêm vào. Các view được phân tách thành các Component của bạn, tạo giao diện nhanh chóng, đơn giản, dễ đọc hiểu hơn là jQuery.
- Nói về jQuery, nó là một bộ thư viện javascript có cái thời mà các chuẩn ES5, ES6 đang phổ dụng ở hiện tại còn chưa ra đời. Khi mà jQuery chưa ra đời, để viết một hiệu ứng khi cuộn trang, cuộn về đầu trang hay gì đó ta phải viết cả nghìn dòng code. jQuery tập hợp rất nhiều các function hữu ích, giúp code gọn gàng hơn, giúp mọi người viết ít code hơn mà vẫn làm được các chức năng. Ngay cơ bản là select một element trong DOM dùng Javascript thuần, nó đã dài gấp đôi so với dùng jQuery, chưa nói đến các function làm chức năng khác phức tạp hơn.
// Javascript:
var element = document.getElementById('kim')
// jQuery:
var element = $('#kim')
jQuery như là một con đường tắt vào bấy giờ, bởi thế nên thời đấy (cũng phải 10 năm về trước) jQuery rất thông dụng. Và có rất nhiều các plugin được viết để tích hợp với jQuery, nhất là cách thư viện làm hiệu ứng cho website.
- Tới thời điểm hiện tại, jQuery vẫn được dùng rất rộng rãi , tuy nhiên, từ khi Node.js ra đời, mọi thứ đang dần thay đổi, khi mà các thư viện javascipt nhỏ gọn thực hiện cho các mục đích cụ thể xuất hiện rất nhiều và quản lý đơn giản qua NPM. Giúp bạn chỉ dùng những thứ bạn cần, thay vì một bộ javascript đồ sộ từ jQuery. VD như Vue.js, nó là framework giúp bạn làm ra các ứng dụng web. Mã nguồn khi viết dễ đọc hiểu, Vue quản lý các view trên virtual DOM được phân tách thành các component giúp bạn dễ dàng quản lý, thao tác, tái sử dụng. Nhưng thứ nhỏ lẻ khác bạn cần, có thể tìm các library nhỏ bé khác để dùng thay vì cài jQuery, rồi lại cài thêm một thự viện khác viết cho jQuery. Mọi thứ lúc đấy bạn sẽ thấy bị phụ thuộc quá nhiều với jQuery.
CSS trong Reactjs
Tận dụng các mức mức ưu tiên của CSS để custom style. Mình khuyên bạn là viết các class input khác của riêng bạn để ghi đè lại css cho bất cứ thư viện nào thay vì viết cho class cùng tên của thư viện. Như thế sẽ làm thay đổi tất cả những chỗ khác. Trừ khi bạn chấp nhận thế.
Nếu thư viện bạn dùng có hỗ trợ SASS, LESS, STYLUS, thì việc custom lại một số thứ như màu theme, font, border.. có thể đơn giản hơn vì thường nó sẽ gán vào các biến chung. Nhưng một số khác cũng nên sử dụng class mình khai báo để ghi đè.
V/v lấy dữ liệu và trộn lại trong MySql
Anh nghĩ em tạo một bảng lưu nhật ký hoạt động riêng, mỗi row tương ướng với một hành động mà người dùng đã thực hiện. Có user_id làm foreign key để tham chiếu với bảng users.
Khi lấy dữ liệu từ nhiều bảng thì em dùng các mệnh đề join của mysql hoặc có thể liệt kê các bảng trong mệnh đề from.
Thường các bảng có quan hệ với nhau chúng ta dùng mệnh đề join. Và trong một các bảng đấy nếu có cột trùng tên thì trong mệnh đề where, order... e phải chỉ rõ tên bảng chứa cột đấy.
VD:
Select title, name, department_name
From employees, departments
Order by employees.created_at Desc