0% found this document useful (0 votes)
5 views8 pages

Solved Assignment Social Network

The document provides a complete solution for a Social Network assignment, including a database schema, PHP backend code, AJAX endpoints, and frontend HTML/CSS/JavaScript. It details the file structure, class implementations for user and post management, and examples of AJAX functionality for adding, deleting posts, and updating user profiles. Additionally, it includes frontend forms for user signup and login with client-side validation and server-side handling.

Uploaded by

Alankrit Shukla
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views8 pages

Solved Assignment Social Network

The document provides a complete solution for a Social Network assignment, including a database schema, PHP backend code, AJAX endpoints, and frontend HTML/CSS/JavaScript. It details the file structure, class implementations for user and post management, and examples of AJAX functionality for adding, deleting posts, and updating user profiles. Additionally, it includes frontend forms for user signup and login with client-side validation and server-side handling.

Uploaded by

Alankrit Shukla
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Solved Assignment: Social Network (PHP, jQuery,

MySQL)
This document contains a complete solution for the Social Network assignment. It includes database
schema, PHP (OOP) backend code, AJAX endpoints, frontend HTML/CSS/JavaScript (jQuery), and
instructions to set up and run the project. Passwords are hashed using bcrypt (password_hash). File
uploads are validated and sanitized.

1. Database Schema
Use the following SQL to create required tables. Execute in MySQL / MariaDB:
-- Database: social_network
CREATE DATABASE IF NOT EXISTS social_network;
USE social_network;

-- users table
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
full_name VARCHAR(150) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
age INT,
profile_pic VARCHAR(255) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- posts table
CREATE TABLE posts (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
image VARCHAR(255),
description TEXT,
likes INT DEFAULT 0,
dislikes INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. File structure
Place files in a project folder accessible by your web server (e.g., /var/www/html/social_network).
Recommended structure:
/social_network
/uploads/profile_pics/ -- profile pictures (writeable)
/uploads/post_images/ -- post images (writeable)
/classes/
[Link]
[Link]
[Link]
/ajax/
add_post.php
delete_post.php
[Link]
[Link]
update_profile.php
css/
[Link]
js/
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]

3. Backend: PHP (OOP) code


Below are the main PHP class implementations. Adjust DB credentials in [Link].
<?php
// classes/[Link]
class DB {
private static $instance = null;
private $pdo;

private function __construct() {


$host = '[Link]';
$db = 'social_network';
$user = 'root';
$pass = ''; // set your password
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
$this->pdo = new PDO($dsn, $user, $pass, $opt);
}

public static function get() {


if (self::$instance === null) {
self::$instance = new DB();
}
return self::$instance->pdo;
}
}
?>

<?php
// classes/[Link]
require_once __DIR__ . '/[Link]';

class User {
private $pdo;

public function __construct(){


$this->pdo = DB::get();
if(session_status() === PHP_SESSION_NONE) session_start();
}

public function create($data, $file){


// server-side validation (simplified)
if(empty($data['full_name']) || empty($data['email']) || empty($data['password'])) {
throw new Exception('Required fields missing');
}

// check unique email


$stmt = $this->pdo->prepare('SELECT id FROM users WHERE email = ?');
$stmt->execute([$data['email']]);
if($stmt->fetch()) throw new Exception('Email already taken');

// handle profile pic upload


$profile_path = null;
if($file && $file['error'] === UPLOAD_ERR_OK){
$allowed = ['image/jpeg','image/png','image/gif'];
if(!in_array($file['type'], $allowed)) throw new Exception('Invalid file type');
if($file['size'] > 2*1024*1024) throw new Exception('File too large');

$ext = pathinfo($file['name'], PATHINFO_EXTENSION);


$safe = bin2hex(random_bytes(8)) . '.' . $ext;
$dest = __DIR__ . '/../uploads/profile_pics/' . $safe;
move_uploaded_file($file['tmp_name'], $dest);
$profile_path = 'uploads/profile_pics/' . $safe;
}

$hash = password_hash($data['password'], PASSWORD_BCRYPT);


$stmt = $this->pdo->prepare('INSERT INTO users (full_name, email, password, age, profile_pic) VALUES (?
$stmt->execute([$data['full_name'], $data['email'], $hash, $data['age'] ?: null, $profile_path]);
return $this->pdo->lastInsertId();
}

public function login($email, $password){


$stmt = $this->pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
$user = $stmt->fetch();
if(!$user) return false;
if(password_verify($password, $user['password'])){
$_SESSION['user_id'] = $user['id'];
return true;
}
return false;
}

public function find($id){


$stmt = $this->pdo->prepare('SELECT id, full_name, email, age, profile_pic, created_at FROM users WHERE
$stmt->execute([$id]);
return $stmt->fetch();
}

public function update($id, $data, $file = null){


$fields = [];
$params = [];

if(isset($data['full_name'])) { $fields[] = 'full_name = ?'; $params[] = $data['full_name']; }


if(isset($data['age'])) { $fields[] = 'age = ?'; $params[] = $data['age']; }

// handle profile pic


if($file && $file['error'] === UPLOAD_ERR_OK){
$allowed = ['image/jpeg','image/png','image/gif'];
if(!in_array($file['type'], $allowed)) throw new Exception('Invalid file type');
if($file['size'] > 2*1024*1024) throw new Exception('File too large');

$ext = pathinfo($file['name'], PATHINFO_EXTENSION);


$safe = bin2hex(random_bytes(8)) . '.' . $ext;
$dest = __DIR__ . '/../uploads/profile_pics/' . $safe;
move_uploaded_file($file['tmp_name'], $dest);
$fields[] = 'profile_pic = ?';
$params[] = 'uploads/profile_pics/' . $safe;
}

if(empty($fields)) return false;


$params[] = $id;
$sql = 'UPDATE users SET ' . implode(', ', $fields) . ' WHERE id = ?';
$stmt = $this->pdo->prepare($sql);
return $stmt->execute($params);
}
}
?>

<?php
// classes/[Link]
require_once __DIR__ . '/[Link]';

class Post {
private $pdo;
public function __construct(){
$this->pdo = DB::get();
if(session_status() === PHP_SESSION_NONE) session_start();
}

public function add($user_id, $description, $file){


$image_path = null;
if($file && $file['error'] === UPLOAD_ERR_OK){
$allowed = ['image/jpeg','image/png','image/gif'];
if(!in_array($file['type'], $allowed)) throw new Exception('Invalid file type');
if($file['size'] > 4*1024*1024) throw new Exception('File too large');

$ext = pathinfo($file['name'], PATHINFO_EXTENSION);


$safe = bin2hex(random_bytes(8)) . '.' . $ext;
$dest = __DIR__ . '/../uploads/post_images/' . $safe;
move_uploaded_file($file['tmp_name'], $dest);
$image_path = 'uploads/post_images/' . $safe;
}

$stmt = $this->pdo->prepare('INSERT INTO posts (user_id, image, description) VALUES (?, ?, ?)');
$stmt->execute([$user_id, $image_path, $description]);
return $this->pdo->lastInsertId();
}

public function getByUser($user_id){


$stmt = $this->pdo->prepare('SELECT * FROM posts WHERE user_id = ? ORDER BY created_at DESC');
$stmt->execute([$user_id]);
return $stmt->fetchAll();
}

public function delete($post_id, $user_id){


$stmt = $this->pdo->prepare('DELETE FROM posts WHERE id = ? AND user_id = ?');
return $stmt->execute([$post_id, $user_id]);
}

public function changeReaction($post_id, $field, $delta = 1){


if(!in_array($field, ['likes','dislikes'])) throw new Exception('Invalid field');
$sql = "UPDATE posts SET $field = GREATEST(0, $field + ?) WHERE id = ?";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([$delta, $post_id]);
}
}
?>

4. AJAX endpoints (examples)


ajax/add_post.php - add a post via AJAX (multipart/form-data). Returns JSON.
<?php
// ajax/add_post.php
require_once __DIR__ . '/../classes/[Link]';
$post = new Post();
session_start();
if(empty($_SESSION['user_id'])) {
echo json_encode(['success'=>false,'error'=>'Not authenticated']); exit;
}
try {
$id = $post->add($_SESSION['user_id'], $_POST['description'] ?? '', $_FILES['image'] ?? null);
echo json_encode(['success'=>true,'id'=>$id]);
} catch(Exception $e) {
echo json_encode(['success'=>false,'error'=>$e->getMessage()]);
}
?>

ajax/delete_post.php - delete post


<?php
// ajax/delete_post.php
require_once __DIR__ . '/../classes/[Link]';
$post = new Post();
session_start();
if(empty($_SESSION['user_id'])) { echo json_encode(['success'=>false]); exit; }
$id = intval($_POST['post_id'] ?? 0);
$res = $post->delete($id, $_SESSION['user_id']);
echo json_encode(['success'=> (bool)$res]);
?>

ajax/[Link] and ajax/[Link] - toggle reactions


<?php
// ajax/[Link]
require_once __DIR__ . '/../classes/[Link]';
$post = new Post();
session_start();
if(empty($_SESSION['user_id'])) { echo json_encode(['success'=>false]); exit; }
$id = intval($_POST['post_id'] ?? 0);
$res = $post->changeReaction($id, 'likes', 1);
echo json_encode(['success'=> (bool)$res]);
?>

<?php
// ajax/[Link]
require_once __DIR__ . '/../classes/[Link]';
$post = new Post();
session_start();
if(empty($_SESSION['user_id'])) { echo json_encode(['success'=>false]); exit; }
$id = intval($_POST['post_id'] ?? 0);
$res = $post->changeReaction($id, 'dislikes', 1);
echo json_encode(['success'=> (bool)$res]);
?>

ajax/update_profile.php - update user profile (name, age, profile pic)


<?php
// ajax/update_profile.php
require_once __DIR__ . '/../classes/[Link]';
$user = new User();
session_start();
if(empty($_SESSION['user_id'])) { echo json_encode(['success'=>false]); exit; }
try {
$res = $user->update($_SESSION['user_id'], $_POST, $_FILES['profile_pic'] ?? null);
echo json_encode(['success'=> (bool)$res]);
} catch(Exception $e){
echo json_encode(['success'=>false,'error'=>$e->getMessage()]);
}
?>

5. Frontend examples (signup, login, profile)


[Link] - basic form with client-side validation (jQuery). Server-side handled by User->create()
<!-- [Link] -->
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Signup</title>
<link rel="stylesheet" href="css/[Link]">
<script src="[Link]
</head>
<body>
<form id="signupForm" method="post" enctype="multipart/form-data" action="signup_handler.php">
<label>Full Name: <input type="text" name="full_name" required></label><br>
<label>Email: <input type="email" name="email" required></label><br>
<label>Password: <input type="password" name="password" required minlength="6"></label><br>
<label>Age: <input type="number" name="age" min="1"></label><br>
<label>Profile Picture: <input type="file" name="profile_pic" accept="image/*"></label><br>
<button type="submit">Sign Up</button>
</form>
<script>
$('#signupForm').on('submit', function(e){
// simple client-side validation
var pw = $(this).find('input[name=password]').val();
if([Link] < 6){ alert('Password must be >=6'); [Link](); }
});
</script>
</body>
</html>

signup_handler.php - calls User->create and redirects


<?php
// signup_handler.php
require_once 'classes/[Link]';
$user = new User();
try {
$id = $user->create($_POST, $_FILES['profile_pic'] ?? null);
header('Location: [Link]?created=1');
} catch(Exception $e) {
echo 'Error: ' . htmlspecialchars($e->getMessage());
}
?>

[Link] and handler


<!-- [Link] -->
<form method="post" action="login_handler.php">
<input name="email" type="email" required>
<input name="password" type="password" required>
<button type="submit">Login</button>
</form>

<?php
// login_handler.php
require_once 'classes/[Link]';
$user = new User();
if($user->login($_POST['email'], $_POST['password'])){
header('Location: [Link]');
} else {
echo 'Invalid credentials';
}
?>

[Link] - displays user info and posts; uses AJAX to add/delete posts and update likes without reload.
<?php
// [Link]
require_once 'classes/[Link]';
require_once 'classes/[Link]';
$userObj = new User();
$postObj = new Post();
session_start();
if(empty($_SESSION['user_id'])) { header('Location: [Link]'); exit; }
$user = $userObj->find($_SESSION['user_id']);
$posts = $postObj->getByUser($_SESSION['user_id']);
?>
<!doctype html>
<html>
<head>
<title>Profile</title>
<link rel="stylesheet" href="css/[Link]">
<script src="[Link]
</head>
<body>
<div id="profile">
<img src="<?php echo htmlspecialchars($user['profile_pic']?:'[Link]'); ?>" width="120">
<h2 id="name"><?php echo htmlspecialchars($user['full_name']); ?></h2>
<p id="email"><?php echo htmlspecialchars($user['email']); ?></p>
<p id="age"><?php echo htmlspecialchars($user['age']); ?></p>

<form id="profileUpdate" enctype="multipart/form-data">


<input name="full_name" value="<?php echo htmlspecialchars($user['full_name']); ?>">
<input name="age" value="<?php echo htmlspecialchars($user['age']); ?>">
<input type="file" name="profile_pic" accept="image/*">
<button type="submit">Update</button>
</form>

<h3>Create Post</h3>
<form id="postForm" enctype="multipart/form-data">
<input type="file" name="image" accept="image/*">
<textarea name="description"></textarea>
<button type="submit">Post</button>
</form>
<div id="posts">
<?php foreach($posts as $p): ?>
<div class="post" data-id="<?php echo $p['id']; ?>">
<?php if($p['image']): ?>
<img src="<?php echo htmlspecialchars($p['image']); ?>" width="200">
<?php endif; ?>
<p><?php echo htmlspecialchars($p['description']); ?></p>
<div>
<button class="likeBtn">Like (<?php echo $p['likes']; ?>)</button>
<button class="dislikeBtn">Dislike (<?php echo $p['dislikes']; ?>)</button>
<button class="delBtn">Delete</button>
</div>
</div>
<?php endforeach; ?>
</div>
</div>

<script>
$(function(){
$('#postForm').on('submit', function(e){
[Link]();
var fd = new FormData(this);
$.ajax({
url: 'ajax/add_post.php', type:'POST', data:fd, contentType:false, processData:false, dataType:'json',
success: function(res){
if([Link]){ [Link](); } else alert([Link] || 'Error');
}
});
});

$('.delBtn').on('click', function(){
var id = $(this).closest('.post').data('id');
$.post('ajax/delete_post.php',{post_id:id}, function(res){ if([Link]) [Link](); else alert('F
});

$('.likeBtn').on('click', function(){
var id = $(this).closest('.post').data('id');
$.post('ajax/[Link]',{post_id:id}, function(res){ if([Link]) [Link](); else alert('Failed')
});

$('.dislikeBtn').on('click', function(){
var id = $(this).closest('.post').data('id');
$.post('ajax/[Link]',{post_id:id}, function(res){ if([Link]) [Link](); else alert('Faile
});

$('#profileUpdate').on('submit', function(e){
[Link]();
var fd = new FormData(this);
$.ajax({
url:'ajax/update_profile.php', type:'POST', data:fd, contentType:false, processData:false, dataType:'json
success:function(res){ if([Link]) [Link](); else alert([Link]||'Error'); }
});
});
});
</script>
</body>
</html>

6. CSS (css/[Link])
body{font-family: Arial, sans-serif; margin:20px;}
#profile img{border-radius:50%;}
.post{border:1px solid #ddd; padding:10px; margin-bottom:10px;}

7. JS (optional js/[Link])
// Simple delegated handlers if posts are dynamic
$(document).on('click', '.delBtn', function(){ /* as in [Link] */ });
8. Notes, validation & security
Important security and validation practices implemented or recommended:
- Passwords hashed with password_hash (bcrypt).
- Server-side validation of inputs to prevent missing/invalid data.
- File upload restrictions by MIME type and size; filenames randomized to avoid collisions.
- Use prepared statements (PDO) to avoid SQL injection.
- Ensure upload directories are not executable and have correct permissions.
- In production, use HTTPS, CSRF protection tokens, and stricter validation on file contents.

9. Setup instructions
1. Create database using the provided SQL. 2. Configure DB credentials in classes/[Link]. 3. Ensure
uploads directories exist and are writable (chmod 755 or 775). 4. Place files on a PHP-enabled web server
(PHP 7.4+ recommended). 5. Access [Link] to register, then [Link] to enter profile.
This completes the solved assignment. The code included is a complete reference implementation. Adapt
styles and UI behaviour as preferred.
Generated automatically. End of document.

You might also like