In short
PHP (PHP: Hypertext Preprocessor) is a server-side scripting language embedded in HTML that generates dynamic pages; MySQL (and its drop-in fork MariaDB) is the relational database that stores the data behind them. Together with Linux and Apache they form the LAMP stack, which still runs a very large share of Indian web hosting, college project work and WordPress sites (WordPress alone powers a big fraction of all websites and is pure PHP+MySQL). BCA syllabi examine it as a full paper — syntax, arrays, strings, forms, sessions, file handling, OOP, database connectivity, CRUD — and lab exams ask for a working registration/login or inventory module. Placement rounds for web-developer and PHP-developer roles at Indian service and product companies ask prepared statements, sessions, joins and password_hash almost every time.
Explained
PHP language core
- Nature: interpreted, server-side, loosely typed, open source (Zend Engine). Files end
.php; code lives in<?php ... ?>. The browser never sees PHP source — only its output. - Request flow: browser → Apache/Nginx → PHP interpreter (mod_php, PHP-FPM) → runs script, queries MySQL → returns HTML. PHP is stateless per request; nothing persists unless stored in a session, cookie, file or database.
- Variables:
$name, case-sensitive, no declaration needed. Loose typing →"10" + 5is15.==compares after type juggling,===compares type and value. - Data types: int, float, string, bool, array, object, NULL, resource.
var_dump()shows type and value;gettype(),settype(),intval(),(int)casting. - Strings: single quotes are literal; double quotes interpolate variables and escapes. Concatenation with
.. Key functions:strlen,strtoupper,ucfirst,trim,substr,strpos,str_replace,explode,implode,sprintf,str_contains(PHP 8+),nl2br,htmlspecialchars. - Arrays: indexed (
[10,20]), associative (['name'=>'Asha']) and multidimensional. Functions:count,array_push/pop/shift/unshift,array_merge,in_array,array_key_exists,array_keys,array_values,sort,rsort,asort,ksort,usort,array_map,array_filter,array_slice,array_search. - Control structures:
if/elseif/else,switch,match(PHP 8),for,while,do...while,foreach ($arr as $k => $v),break,continue. Alternative syntaxif: endif;is used inside templates. - Functions:
function f($a, $b = 5) { return $a + $b; }. Pass by value by default, by reference with&$x. Variadic...$nums. Type declarations and return types (function add(int $a): int), nullable?int, union types (PHP 8). Scope: variables inside a function are local unless declaredglobalor storedstatic. - Superglobals:
$_GET,$_POST,$_REQUEST,$_SESSION,$_COOKIE,$_FILES,$_SERVER,$_ENV,$GLOBALS. - Includes:
include(warning on failure, script continues),require(fatal error, stops),include_once/require_once(prevents double inclusion) — used for header, footer anddb.php. - Errors: notice/warning/fatal;
error_reporting(E_ALL)anddisplay_errorsON in development, OFF in production withlog_errorsto a file. PHP 7+ exceptions:try { } catch (Exception $e) { } finally { },throw new Exception("msg"). - Versions: PHP 7 brought a big speed gain and scalar type hints; PHP 8 added JIT, named arguments,
match, constructor property promotion, nullsafe?->, attributes. Old versions reach end of life quickly — check php.net for the currently supported branch before quoting one.
PHP OOP, sessions and forms
- Classes:
class Student { public $name; private $marks; public function __construct($n){ $this->name = $n; } }; instantiate withnew.$thisrefers to the current object;::(scope resolution) forstaticmembers and constants. - Pillars: encapsulation (
public/private/protected), inheritance (extends, single only), polymorphism (method overriding; PHP has no true overloading but has__call), abstraction (abstract class,interfacewithimplements).traitsupplies horizontal reuse to work round single inheritance.finalblocks overriding. - Magic methods:
__construct,__destruct,__get,__set,__call,__toString,__invoke. - Namespaces and autoloading:
namespace App\Models;,use App\Models\Student;; Composer (composer require,vendor/autoload.php) gives PSR-4 autoloading and the package ecosystem. - Forms:
<form method="post" action="save.php">; read with$_POST['email']. Use POST for data that changes state or is sensitive (not visible in the URL, no length limit) and GET for search/filter links that can be bookmarked. Always check$_SERVER['REQUEST_METHOD'] === 'POST'andisset()/empty()before use. - Validation and sanitising: validate server-side always (client-side JS can be bypassed).
filter_var($e, FILTER_VALIDATE_EMAIL),FILTER_VALIDATE_INT,preg_matchfor a mobile pattern,htmlspecialchars($s, ENT_QUOTES, 'UTF-8')on output to stop XSS. - Sessions:
session_start()at the very top (before any output) creates/resumes a session; data in$_SESSION; the browser holds only thePHPSESSIDcookie while the data stays on the server insession.save_path. Logout =session_unset(); session_destroy();and expire the cookie. Callsession_regenerate_id(true)right after a successful login to stop session fixation. - Cookies:
setcookie('theme','dark', time()+86400, '/', '', true, true)— the last two flags aresecure(HTTPS only) andhttponly(JS cannot read it); available in$_COOKIEfrom the next request. Sessions are server-side and safer; cookies are client-side, size-limited (~4 KB) and user-editable. - File upload:
enctype="multipart/form-data";$_FILES['f']['tmp_name'],['size'],['error']; verify real MIME type withfinfo, generate your own filename, store outside the web root or in a directory with script execution disabled, thenmove_uploaded_file(). Limits come fromupload_max_filesize,post_max_size,max_file_uploads. - Other:
header('Location: list.php'); exit;for redirects (must precede output);date()/DateTimewithdate_default_timezone_set('Asia/Kolkata');json_encode/json_decode;mail()or PHPMailer/SMTP;file_get_contents,fopen/fwrite/fclose.
MySQL: database side
- RDBMS concepts: data in tables (relations) of rows (tuples) and columns (attributes); primary key uniquely identifies a row; foreign key references another table's key and enforces referential integrity; unique, not null, check, default constraints;
AUTO_INCREMENTsurrogate keys. - Data types: INT, BIGINT, TINYINT(1) for flags, DECIMAL(10,2) for money (never FLOAT for rupees), VARCHAR(n), CHAR, TEXT, DATE, DATETIME, TIMESTAMP, ENUM, JSON, BLOB.
- SQL sub-languages: DDL
CREATE/ALTER/DROP/TRUNCATE; DMLINSERT/UPDATE/DELETE; DQLSELECT; DCLGRANT/REVOKE; TCLCOMMIT/ROLLBACK/SAVEPOINT. - SELECT clause order:
SELECT ... FROM ... JOIN ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... LIMIT.WHEREfilters rows before grouping;HAVINGfilters groups after aggregation. - Aggregates:
COUNT,SUM,AVG,MIN,MAX;DISTINCT;COUNT(*)counts rows,COUNT(col)skips NULLs. - Joins:
INNER JOIN(matching rows only),LEFT JOIN(all left + matches, NULLs otherwise),RIGHT JOIN,CROSS JOIN; MySQL has noFULL OUTER JOIN— emulate withLEFT JOIN UNION RIGHT JOIN. Self-join for employee–manager. Subqueries withIN,EXISTS, and derived tables. - Normalisation: 1NF (atomic values, no repeating groups), 2NF (1NF + no partial dependency on part of a composite key), 3NF (2NF + no transitive dependency), BCNF (every determinant is a candidate key). Denormalise deliberately only for read speed.
- Indexes: B-tree index on columns used in
WHERE,JOIN,ORDER BY; primary key is clustered in InnoDB. Indexes speed reads and slow writes and consume space. UseEXPLAIN SELECT ...to see whether an index is used; avoid functions on an indexed column inWHERE(kills the index). - Engines: InnoDB (default) — transactions, row-level locking, foreign keys, crash recovery; MyISAM — no transactions, table-level locking, legacy only. Transactions give ACID (atomicity, consistency, isolation, durability); isolation levels READ UNCOMMITTED → READ COMMITTED → REPEATABLE READ (MySQL default) → SERIALIZABLE.
- Other objects: views, stored procedures and functions, triggers, events.
CHAR SET utf8mb4is required for full Unicode (Indian languages, emoji-safe storage). - Admin:
mysqldump -u root -p db > db.sqlfor backup,mysql -u root -p db < db.sqlto restore; create a least-privilege app user withCREATE USER+GRANT SELECT, INSERT, UPDATE, DELETE— never shiproot. phpMyAdmin is the usual GUI in XAMPP.
Connecting PHP to MySQL — and doing it safely
- Three APIs: deprecated
mysql_*(removed in PHP 7 — never use), MySQLi (procedural and OOP, MySQL only) and PDO (object-oriented, 12+ database drivers, so portable). Both MySQLi and PDO support prepared statements; prefer PDO for new work. - Steps of any CRUD script: connect → prepare statement with placeholders → bind values → execute → fetch results (
fetch,fetchAll,fetch_assoc) → handle errors → close/release. - SQL injection: concatenating user input into SQL lets an attacker change its meaning —
' OR '1'='1' --in a password box bypasses login;; DROP TABLEdestroys data. Fix: prepared statements with bound parameters, so input is always data and never SQL.mysqli_real_escape_string()is a weaker fallback; a whitelist is needed for dynamic table/column names andORDER BYdirection, which cannot be bound. - Passwords: store
password_hash($p, PASSWORD_DEFAULT)(bcrypt/Argon2 with a per-password salt) in aVARCHAR(255)column and check withpassword_verify($p, $hash). Never store plain text; MD5 and SHA-1 are unacceptable for passwords. - Other security basics: CSRF token in every state-changing form (random token in session, compared with
hash_equals); XSS blocked by escaping output; least-privilege DB user; credentials in a file outside the web root or in environment variables, never committed; HTTPS; disabledisplay_errorsin production; validate file uploads; rate-limit login attempts. - Indian legal context: personal data (student, candidate or customer records) is governed by the Digital Personal Data Protection Act, 2023 — collect only what is needed, obtain consent with a notice, secure it with reasonable safeguards and report breaches to the Data Protection Board; its rules were notified in 2025 with phased timelines, so check the current stage before quoting a deadline. The Information Technology Act, 2000 section 43A/72A and section 66 cover compensation for negligent security and penalties for data theft, and CERT-In's 2022 directions require reporting cyber incidents within 6 hours and keeping logs (CERT-In specifies 180 days of ICT logs within India).
- Performance: avoid
SELECT *; fetch only needed columns; paginate withLIMIT ... OFFSET; avoid queries inside loops (the N+1 problem — use a JOIN orWHERE id IN (...)); add indexes guided byEXPLAIN; cache with OPcache (bytecode), Redis/Memcached (data); use transactions for multi-table writes;mysqli_free_result/unset large result sets.
Deployment and the wider ecosystem
- Dev stack: XAMPP/WAMP/Laragon on Windows (Apache + MySQL/MariaDB + PHP + phpMyAdmin), LAMP on Ubuntu; files in
htdocs//var/www/html; reach the site athttp://localhost/project/. Docker is common in jobs. - Server config:
php.ini(memory_limit, max_execution_time, upload limits, timezone, error settings); Apache.htaccessfor pretty URLs (RewriteEngine On),ErrorDocument, denying access to.env/includes/; Nginx + PHP-FPM is the faster modern pairing. - Frameworks: Laravel (dominant in India — Eloquent ORM, Blade templates, Artisan CLI, migrations, middleware), CodeIgniter (light, still common in older Indian projects), Symfony, Yii. CMS: WordPress, Drupal, Joomla, Magento for e-commerce. Frameworks add MVC structure, routing, ORM, CSRF and validation out of the box.
- MVC pattern: Model (data and rules) – View (presentation) – Controller (request handling); separation makes code testable and team-friendly. PHP commonly serves JSON endpoints consumed by a JavaScript or mobile front end.
- Tooling: Composer (dependencies), Git, PHPUnit (unit tests), PSR-12 coding style, Xdebug,
php -S localhost:8000built-in server, cron for scheduled scripts. - Hosting in India: shared cPanel hosting (Hostinger, BigRock, GoDaddy) roughly ₹100–400 per month, VPS ₹400–1,500 per month, and AWS/Azure/GCP for scale — figures move, so treat them as indicative.
.indomains are managed under NIXI's registry.
Key points
- PHP - server-side scripting language; output reaches the browser, source never does.
- LAMP/WAMP - Linux/Windows + Apache + MySQL + PHP, the classic deployment stack.
- Loose typing -
==juggles types,===compares value and type; always prefer===. - include vs require - include warns and continues, require is fatal;
_onceprevents duplicates. - GET vs POST - GET is visible, bookmarkable and length-limited; POST carries form and sensitive data.
- Session - data stored on the server, keyed by the
PHPSESSIDcookie;session_start()before any output. - Cookie - data stored in the browser, ~4 KB, user-editable; set
httponlyandsecure. - Superglobals -
$_GET,$_POST,$_SESSION,$_COOKIE,$_FILES,$_SERVER, available in every scope. - Prepared statement - query sent with placeholders, values bound separately; the one real cure for SQL injection.
- password_hash / password_verify - the only acceptable way to store and check passwords in PHP.
- htmlspecialchars - escape on output to prevent XSS; validation is for input, escaping is for output.
- MySQLi vs PDO - MySQLi is MySQL-only; PDO supports many drivers and named placeholders.
- InnoDB - default engine, gives transactions, foreign keys and row-level locking; MyISAM gives none.
- Joins - INNER keeps matches only; LEFT keeps all left rows with NULLs for missing matches.
- WHERE vs HAVING - WHERE filters rows before grouping, HAVING filters aggregated groups.
- Normalisation - 1NF atomic, 2NF no partial dependency, 3NF no transitive dependency.
- Index - speeds
WHERE/JOINlookups, slows inserts; check usage withEXPLAIN. - DPDP Act, 2023 + IT Act, 2000 - the Indian law frame for storing user data; CERT-In requires 6-hour incident reporting.
Formulas and examples
Pagination:
LIMIT $per_page OFFSET ($page − 1) × $per_page; total pages = ceil(total_rows ÷ per_page)Storage estimate: table size ≈ rows × (sum of column byte widths + row overhead); INT = 4 bytes, BIGINT = 8, DATETIME = 5, DECIMAL(10,2) ≈ 5, VARCHAR(n) = actual bytes + 1 or 2 length bytes (utf8mb4 = up to 4 bytes per character)
Session/upload limits: effective upload size = min(upload_max_filesize, post_max_size, memory_limit)
Example 1 — a safe login with PDO and password hashing
<?php // db.php
$pdo = new PDO('mysql:host=localhost;dbname=campus;charset=utf8mb4',
'app_user', getenv('DB_PASS'),
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false]);
<?php // login.php
session_start();
require 'db.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
$pass = $_POST['password'] ?? '';
$st = $pdo->prepare('SELECT id, name, pass_hash FROM users WHERE email = ?');
$st->execute([$email]);
$u = $st->fetch();
if ($u && password_verify($pass, $u['pass_hash'])) {
session_regenerate_id(true);
$_SESSION['uid'] = $u['id'];
header('Location: dashboard.php'); exit;
}
$err = 'Invalid email or password.'; // never say which one is wrong
}
?>
<p><?= isset($err) ? htmlspecialchars($err, ENT_QUOTES, 'UTF-8') : '' ?></p>
Registration side: $hash = password_hash($pass, PASSWORD_DEFAULT); then INSERT INTO users (name,email,pass_hash) VALUES (?,?,?).
Example 2 — injection, arithmetic of the damage
Unsafe code: $sql = "SELECT * FROM users WHERE email='$e' AND pass='$p'"; With $e = "x' OR '1'='1' -- " the query becomes ... WHERE email='x' OR '1'='1' -- ' AND pass='', whose WHERE is always true, so it returns all rows; a script taking $u = $rows[0] logs the attacker in as the first user (often the admin, id 1). Prepared version sends email = ? and binds the whole string as one value — zero rows match, login fails. Fix cost: 2 lines. Breach cost under the DPDP Act, 2023: penalties for failing to take reasonable security safeguards run to a maximum of ₹250 crore per instance (the Board decides the quantum) once the duty applies from 13 May 2027 - until then compensation under IT Act s.43A - plus CERT-In reporting within 6 hours.
Example 3 — joins and aggregation on a campus placement database
CREATE TABLE students (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(80) NOT NULL,
branch VARCHAR(30), cgpa DECIMAL(3,2)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE offers (id INT AUTO_INCREMENT PRIMARY KEY, student_id INT NOT NULL,
company VARCHAR(80), ctc DECIMAL(10,2),
FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE) ENGINE=InnoDB;
-- students with their offers (only placed students)
SELECT s.name, o.company, o.ctc FROM students s
INNER JOIN offers o ON o.student_id = s.id ORDER BY o.ctc DESC;
-- every student, placed or not: unplaced show NULL
SELECT s.name, o.company FROM students s
LEFT JOIN offers o ON o.student_id = s.id;
-- branches whose average CTC exceeds 6 lakh, among students with CGPA above 7
SELECT s.branch, COUNT(o.id) AS offers, ROUND(AVG(o.ctc),2) AS avg_ctc
FROM students s JOIN offers o ON o.student_id = s.id
WHERE s.cgpa > 7.00
GROUP BY s.branch HAVING AVG(o.ctc) > 600000 ORDER BY avg_ctc DESC;
With rows BCA ₹4,50,000 and ₹5,50,000, and BCom ₹7,00,000 — BCA average = (450000+550000)/2 = ₹5,00,000 (excluded by HAVING), BCom average = ₹7,00,000 (kept). If students has 5 rows and offers has 3 (two students unplaced), the INNER JOIN returns 3 rows and the LEFT JOIN returns 5.
Example 4 — pagination and index arithmetic
A jobs table has 5,00,000 rows; a listing page shows 20 per page.
- Total pages = ceil(500000 ÷ 20) = 25,000. Page 7 →
LIMIT 20 OFFSET 120(because (7−1) × 20 = 120). - Full scan reads 5,00,000 rows. A B-tree index with fan-out 100 needs about log₁₀₀(500000) = ln(500000)/ln(100) = 13.12/4.61 ≈ 2.85 → 3 node reads plus the matching rows — the reason
EXPLAINshowingtype: ALLon a big table is a red flag. - Deep
OFFSET 400000is still slow because MySQL counts and discards those rows; keyset pagination (WHERE id > :last_id ORDER BY id LIMIT 20) stays fast.
Example 5 — row size estimate
users(id INT, name VARCHAR(50), email VARCHAR(100), pass_hash CHAR(60), created DATETIME), data mostly ASCII averaging 20 and 25 characters.
- Bytes ≈ 4 (INT) + (20+1) + (25+1) + 60 + 5 (DATETIME) = 116 bytes of data per row.
- 2,00,000 users ≈ 116 × 200000 = 23.2 MB of data, plus roughly 20–30 bytes per row of InnoDB overhead and index pages — call it 30–35 MB, comfortably inside a ₹200/month shared-hosting plan.
| MySQLi | PDO | |
|---|---|---|
| Databases | MySQL/MariaDB only | 12+ drivers (MySQL, PostgreSQL, SQLite, SQL Server) |
| API style | Procedural and OOP | OOP only |
| Placeholders | ? only | ? and named :email |
| Prepared statements | Yes | Yes |
| Named binding / fetch into object | Limited | Rich (FETCH_CLASS, fetchAll) |
| Best for | Legacy MySQL-only code | New projects, portability |
| Session | Cookie | |
|---|---|---|
| Stored where | Server (file/Redis) | Browser |
| Size | Practically large | About 4 KB |
| Lifetime | Till browser close or timeout | Till expiry date set |
| Tamper-proof | Yes (id only on client) | No — user can edit |
| Typical use | Login state, cart, flash messages | "Remember me", theme, consent |
Where it is used
- IT services and web agencies: PHP/Laravel developers at Indian service firms and the thousands of SME web agencies building CMS, portals and dashboards; typical fresher PHP roles are advertised at roughly ₹2–4.5 lakh per annum, varying widely by city and employer.
- Government and education portals: many state-government, university result, admission and tender portals run PHP+MySQL on NIC/state data-centre infrastructure; college ERP, library and attendance systems too.
- E-commerce and CMS: WordPress + WooCommerce and Magento stores, with Razorpay/PayU/Paytm payment-gateway integration done in PHP (webhooks, signature verification) — the mainstay of small-business online selling in India.
- Job roles: PHP developer, full-stack (PHP + JavaScript) developer, WordPress developer, backend developer, database administrator, DevOps for LAMP hosting, and support roles maintaining legacy CodeIgniter/CakePHP code.
- Freelance and campus projects: BCA/MCA final-year projects — hospital management, hostel allotment, online examination, placement cell — are overwhelmingly PHP+MySQL CRUD applications; the same skill supports freelance work on Indian SME websites.
- SaaS and APIs: PHP backends exposing JSON APIs for Android/React front ends, SMS/WhatsApp integrations, Aadhaar-free KYC form workflows, and reporting systems that export to Excel/PDF.
Interview questions
- Q: What is the difference between
includeandrequire? A: Both insert a file;includeemits a warning and lets the script continue if the file is missing, whilerequireraises a fatal error and halts execution. - Q: How do you prevent SQL injection in PHP? A: Use prepared statements with bound parameters via PDO or MySQLi so user input is treated as data, never as SQL; whitelist anything that cannot be bound, such as table or column names.
- Q: Difference between
==and===? A:==compares values after type juggling, so"5" == 5is true;===also requires the same type, so"5" === 5is false. - Q: How does a PHP session actually work? A:
session_start()issues a session id stored in aPHPSESSIDcookie; the data itself lives on the server and is looked up by that id on each request. - Q: Why must
session_start()come before any output? A: It sends aSet-CookieHTTP header, and headers cannot be sent after the body has begun — otherwise you get "headers already sent". - Q: How should passwords be stored? A: With
password_hash()(bcrypt or Argon2, automatically salted) in a VARCHAR(255) column, verified bypassword_verify(); never plain text, MD5 or SHA-1. - Q: MySQLi or PDO, and why? A: PDO for new code — it supports many databases, named placeholders and richer fetching; MySQLi only when the project is locked to MySQL or is legacy.
- Q: Difference between
WHEREandHAVING? A:WHEREfilters individual rows before grouping;HAVINGfilters the groups after aggregation, so onlyHAVINGcan useAVG(),SUM()and similar. - Q: INNER JOIN versus LEFT JOIN? A: INNER JOIN returns only rows matching in both tables; LEFT JOIN returns every row of the left table, with NULLs where the right table has no match.
- Q: Why is InnoDB preferred over MyISAM? A: InnoDB gives ACID transactions, foreign keys, row-level locking and crash recovery; MyISAM has none of these and locks whole tables.
- Q: What is the N+1 query problem? A: Fetching a list then running one query per row inside a loop; replace it with a single JOIN or
WHERE id IN (...)query. - Q: What is
htmlspecialcharsfor, and is it enough against SQL injection? A: It escapes HTML on output to prevent XSS; it does nothing for SQL injection, which needs prepared statements. - Q: How do you handle file uploads securely? A: Check
$_FILESerror and size, verify the real MIME type withfinfo, rename the file yourself, and store it outside the web root or where scripts cannot execute.
Common mistakes
- Building SQL by concatenating
$_POSTvalues, then addingmysqli_real_escape_stringand calling it secure — only prepared statements are. - Echoing output or leaving a blank line before
session_start()/header(), producing "headers already sent". - Storing passwords in plain text or MD5 in lab projects, and carrying that habit into interviews.
- Writing
$_POST['x']withoutisset()/empty()checks, and trusting client-side JavaScript validation as the only validation. - Using
=instead of==/===in conditions, orSELECT *and queries inside loops in every listing page. - Forgetting that a cookie set with
setcookie()is not readable in$_COOKIEuntil the next request. - Shipping with
display_errorson, the MySQLrootuser indb.php, and credentials committed to Git inside the web root. - Confusing
WHERE/HAVING, or claiming MySQL supportsFULL OUTER JOIN.
Related topics
- Server-side web development · REST APIs · Web fundamentals: HTML, CSS and JavaScript · E-commerce systems · Cloud computing basics · Linux command line essentials