This interview guide is for educational and informational purposes only. It is designed to help readers prepare, but it does not guarantee any interview result, hiring decision, offer, or outcome. Interview questions, hiring criteria, and preferred answers can vary by employer, interviewer, industry, location, and time. The examples and explanations reflect the authors' research and judgment, are provided without warranties of any kind, and should not be treated as the only correct approach. Diagrams are simplified illustrations intended to highlight the main components and their interactions; actual systems and implementations may be more complex. Alternative approaches may be equally valid or better suited to a particular question, context, or interviewer. To the fullest extent permitted by applicable law, the author, contributors, and publisher are not liable for decisions made, actions taken, or losses incurred based on this guide.
Identity, Image, and Privacy Notice
To respect individual privacy, some names, profile photographs, avatars, biographical details, and other identifying information displayed in this guide may be replaced with pseudonyms, licensed stock images, illustrative avatars, composite images, or representative descriptions. Unless a person is expressly identified as an actual contributor, a displayed name, image, or profile should not be understood as depicting or identifying a specific candidate, interviewer, employee, or other real individual. These representations are provided for editorial and illustrative purposes only and do not imply endorsement, employment, participation, or affiliation with this guide or any company mentioned in it. Any resemblance to an actual person is coincidental.
Company Notice
This guide is an independent educational resource and is not affiliated with, endorsed by, sponsored by, or approved by the company named in this guide. Company names are used only to identify interview experiences commonly reported by candidates. Interview practices can change without notice, and inclusion of company-specific content does not mean these questions are official, complete, or guaranteed to be asked. To the fullest extent permitted by law, the author, contributors, and publisher are not responsible for outcomes related to use of this material.
Content Accuracy and Verification
To the fullest extent permitted by applicable law, we do not represent or warrant that interview guides, questions, answers, examples, or diagrams are accurate, complete, current, error-free, or suitable for any particular purpose. You are responsible for independently reviewing and verifying the information before relying on it.
Questions or comments?
Contact us for general questions, or share feedback, technical corrections, and comments with the community.
11. What is the purpose of the $this variable in PHP?Language SpecificEasy
i Question Details
Explain instance context, accessing properties and methods, when $this is unavailable, and how it differs from self and static.
Short Interview Answer (30-60 seconds)
$this refers to the current object whose instance method is running. I use it to access that object’s properties and methods, such as $this->name or $this->save(). It is available only when PHP has an object context, so it is unavailable inside a static method. self resolves to the class where the code was declared, while static uses late static binding and can resolve to the class used for the current call.
$this means the object that is currently doing the work. It lets code inside an object read or change information that belongs to that same object. It also lets one action inside the object call another action on the same object. This matters because several objects can be created from one class, and each object can hold different information. PHP uses $this to know exactly which object should receive the read, change, or action during that method call. It does not create another object or copy the object’s information.
Useful Questions to Ask the Interviewer
Should I also compare $this with self and static?
Should I explain how $this behaves inside closures?
Would you like a small inheritance example?
How to Explain It in an Interview
In PHP, $this is a special variable that refers to the current object. PHP makes it available when a method runs in an object context. For example, when $user->rename() runs, $this inside rename() refers to that exact $user object.
Use $this->property to read or update an instance property. Use $this->method() to call another instance method on the same object. The object operator is required because the property or method belongs to an object instance.
$this is unavailable inside a method declared static. A static method can be called without creating an object, so PHP has no current object to assign to $this. Trying to use $this without an object context throws an Error. In PHP 8 and later, calling a non static method statically also throws an Error.
$this is different from self and static. $this refers to an object instance. self resolves using the class where the code was declared. static uses late static binding, so inherited class behavior can resolve using the class selected by the current call.
A normal closure created in an object context is automatically bound to the current object, so it can use $this. A closure declared static is not bound to an object and cannot use $this. A bound closure can also keep its object alive while the closure remains reachable, which may matter in long running workers.
Accessing $this does not copy the object or allocate a new object. It uses the existing object context. Access itself has constant time behavior and normally adds no meaningful memory cost. The work performed by the accessed property or method may have its own cost. Production code should use $this only for data or behavior that belongs to the current object.
Example
The example creates two User objects that hold separate names. Calling rename on the first object makes $this refer only to that object, so the second object remains unchanged. The describe method reads the current object’s name through $this. The className method uses self::class, which resolves to User because that is where the method was declared. The calledClassName method uses static::class, so a call through AdminUser resolves to AdminUser through late static binding. No static method uses $this because a static call has no required object context.
Code
<?phpdeclare(strict_types=1);
classUser{
publicfunction__construct(privatestring$name)
{
}
publicfunctionrename(string$name): void{
// $this is the exact object that received this method call.$this->name = $name;
}
publicfunctiondescribe(): string{
// Read an instance property from the current object.return"User name: {$this->name}";
}
publicstaticfunctionclassName(): string{
// self resolves to the class where this method was declared.returnself::class;
}
publicstaticfunctioncalledClassName(): string{
// static follows late static binding.returnstatic::class;
}
}
classAdminUserextendsUser{
}
$firstUser = newUser('Amina');
$secondUser = newUser('David');
$firstUser->rename('Sara');
echo$firstUser->describe() . PHP_EOL;
echo$secondUser->describe() . PHP_EOL;
echoAdminUser::className() . PHP_EOL;
echoAdminUser::calledClassName() . PHP_EOL;
Where it is used
$this is used throughout object oriented PHP applications. A service object may use it to access dependencies stored in constructor promoted properties. An entity may use it to update its own state. A controller may use it to call another instance method. A repository may use it to access a database connection stored on the object. It is also common in command handlers, event listeners, middleware objects, queue workers, and test classes whenever behavior must operate on the current instance. In long running processes, developers should consider whether stored bound closures keep an object reachable longer than intended.
Why Interviewers Ask This
Interviewers ask this question to check whether the candidate understands how PHP identifies the current object while an instance method is running. It also tests whether the candidate can distinguish object access through $this from class scope access through self and late static binding through static. A strong answer shows correct judgment about instance properties, instance methods, static methods, inheritance, closures, runtime errors, object identity, and object lifetime.
Common interview mistakes
A common mistake is saying that $this refers to the class. It refers to the current object. Another mistake is using $this inside a static method, where no current object exists. Developers may also confuse $this->method() with self::method() or static::method(). The first calls through the current object. self resolves from the class where the code was declared. static uses late static binding. Another mistake is assuming that every closure has $this. A static closure has no object binding. Developers should also avoid storing a bound closure longer than needed when retaining the related object could increase memory use in a long running process.
Interview tip
Start by saying that $this refers to the current object instance. Give one property example and one method example. Then state that it is unavailable in static methods. Finish by separating $this from self and static. Mention closure binding only if the interviewer asks for an edge case.
Interviewer may ask next
Is $this available inside every closure created in an instance method?
No. A normal closure created in an object context is automatically bound to the current object and can use $this. A closure declared static has no object binding, so $this is unavailable and using it throws an Error. This matters because a normal bound closure can retain the object while the closure remains reachable. A static closure is useful when the callback does not need object state and should not keep the object alive.
When should you use $this, self, or static in PHP?
Use $this when code must access the current object’s instance properties or instance methods. Use self when class scope resolution should stay tied to the class where the code was declared. Use static when inherited class behavior should follow the class selected by the current call through late static binding. The main tradeoff is fixed resolution versus inheritance flexibility. $this is separate from both because it requires an actual object context and does not represent a class name.
12. What is object-oriented programming in PHP?Language SpecificEasy
i Question Details
Define object-oriented programming in PHP using classes and objects. Explain properties, methods, constructors, visibility, encapsulation, inheritance, interfaces, abstract classes, traits, composition, and polymorphism with one small domain example. Explain when a simple function or value object is clearer than creating a large class hierarchy.
Short Interview Answer (30-60 seconds)
Object oriented programming in PHP means organizing related data and behavior inside classes and creating objects from those classes. Properties store state, methods perform actions, and constructors prepare new objects. Visibility supports encapsulation by controlling access to members. Interfaces, inheritance, abstract classes, traits, composition, and polymorphism can help reuse or replace behavior when there is a real need. I prefer a simple function or small value object when a larger class design would only add complexity.
Object oriented programming is a way to keep related information and actions together. For example, an order can store its number and total amount, and it can also know how to describe itself. This can make a larger program easier to organize because each part has a clear job. It also gives developers several ways to reuse behavior or replace one implementation with another. The important point is not to create many layers just because PHP supports them. A simple function or small object is often clearer when the problem itself is simple.
Useful Questions to Ask the Interviewer
Would you like a small PHP example that shows the main object oriented features together?
Should I also explain when composition is better than inheritance?
How to Explain It in an Interview
In PHP, a class defines properties and methods. An object is an instance created from that class. Properties hold state, and methods define behavior. A constructor named __construct runs when an object is created and can receive the values or dependencies that the object needs.
Visibility controls access to class members. A public member can be accessed from outside the class. A protected member can be accessed inside the declaring class and its child classes. A private member can be accessed only from the class that declares it. This supports encapsulation because a class can protect its internal state and expose only the operations callers should use.
Inheritance lets one class extend another class. It is most useful when the child really represents a specialized form of the parent. An abstract class cannot be instantiated directly. It can provide shared implementation and can declare abstract methods that concrete child classes must implement. An interface defines a contract that implementing classes must satisfy. Different classes that implement the same interface can be accepted through that interface type. Using different concrete objects through the same type is polymorphism.
A trait lets classes reuse properties or methods without creating a parent and child relationship. Composition means one object contains or receives another object and delegates work to it. Composition often keeps classes less tightly connected and makes dependencies easier to replace.
In the order example, Order receives a PriceFormatter interface. Different formatter objects can provide different formatting behavior without changing Order. If a problem only needs one calculation, a function may be clearer. If it represents a small group of values with rules, a value object may be enough. Large inheritance trees can increase object count, dependencies, and maintenance cost without improving the design.
Example
This example uses one small order domain. Order stores its own state and receives a PriceFormatter through an interface. DollarPriceFormatter and PlainPriceFormatter provide different implementations of the same format method, so Order can work with either implementation through polymorphism. BaseEntity is an abstract class that gives Order a shared identifier. HasLabel is a trait that reuses a small label method. The Order constructor receives the initial total and formatter dependency. Private properties protect internal state, while public methods expose supported behavior. The formatter is included through composition instead of inheritance. This keeps the example small while demonstrating the main PHP object oriented features.
Code
<?phpdeclare(strict_types=1);
// An interface defines behavior that different classes can provide.interfacePriceFormatter{
publicfunctionformat(float$amount): string;
}
// One concrete implementation of the interface.finalclassDollarPriceFormatterimplementsPriceFormatter{
publicfunctionformat(float$amount): string{
return'$' . number_format($amount, 2);
}
}
// Another implementation shows polymorphism.finalclassPlainPriceFormatterimplementsPriceFormatter{
publicfunctionformat(float$amount): string{
returnnumber_format($amount, 2);
}
}
// An abstract class can provide shared state or behavior.abstractclassBaseEntity{
publicfunction__construct(protectedreadonlyint$id) {
}
publicfunctionid(): int{
return$this->id;
}
}
// A trait reuses a method without creating an inheritance relationship.traitHasLabel{
publicfunctionlabel(): string{
return'Order #' . $this->id();
}
}
finalclassOrderextendsBaseEntity{
useHasLabel;
publicfunction__construct(int$id,
privatefloat$total,
private PriceFormatter $formatter) {
parent::__construct($id);
}
publicfunctiontotal(): float{
return$this->total;
}
publicfunctionformattedTotal(): string{
// Composition delegates formatting to the formatter object.return$this->formatter->format($this->total);
}
}
$order = newOrder(101, 49.95, newDollarPriceFormatter());
echo$order->label() . PHP_EOL;
echo$order->formattedTotal() . PHP_EOL;
Where it is used
PHP applications use object oriented programming for domain models, application services, controllers, repositories, adapters, formatters, and other components that combine related state and behavior. Interfaces are useful when production code needs interchangeable implementations, such as different payment or storage implementations. Composition is useful when one object should use another service without becoming its child class. Small value objects are useful for concepts such as money, identifiers, or date ranges when those values need validation and clear meaning. For a single stateless calculation, a function can be simpler and use fewer objects.
Why Interviewers Ask This
Interviewers ask this to check whether I understand how PHP classes and objects organize state and behavior. They also want to see whether I understand constructors, visibility, encapsulation, inheritance, interfaces, abstract classes, traits, composition, and polymorphism. The question also tests whether I can choose a simple design instead of creating unnecessary class hierarchies.
Common interview mistakes
A common mistake is treating object oriented programming as a reason to turn every function into a class. Another mistake is using inheritance only to reuse code even when the classes do not have a real parent and child relationship. Developers may also expose every property as public, which weakens encapsulation. Another mistake is thinking an interface provides shared implementation. An interface defines required behavior, while a trait can provide reusable implementation. Developers may also think a private parent property is directly accessible from a child class. It is not. Deep inheritance trees can make behavior harder to follow and change. Composition is often simpler when one object only needs another object's service.
Interview tip
Start by saying that classes group related state and behavior and objects are instances of those classes. Then explain constructors, visibility, and encapsulation. After that, compare interfaces, inheritance, abstract classes, traits, composition, and polymorphism with one small example. Finish by saying that good object oriented design does not mean using classes everywhere. A simple function or small value object is often the better choice for a simple problem.
Interviewer may ask next
Can a child class access a private property declared in its parent class?
No. A private property is accessible only from the class that declares it. A child class cannot directly access that private member. If child classes need controlled access, the parent can provide a protected or public method, or it can declare a member as protected when that wider access is part of the design. This matters because private visibility gives the declaring class stronger control over its internal state. Protected access gives subclasses more freedom, but it also couples them more closely to the parent.
When would you choose composition instead of inheritance in PHP?
I choose composition when one object needs another object's behavior but is not really a specialized version of that object. In this example, Order uses a PriceFormatter, so it stores a formatter dependency instead of extending a formatter class. The formatter implementation can then be replaced without changing the Order inheritance tree. This matters in production because dependencies are easier to replace and test. The tradeoff is that composition can require creating and passing more objects, but it usually keeps responsibilities and relationships clearer.
13. What are traits in PHP, and how are method conflicts resolved?Language SpecificMedium
i Question Details
Explain horizontal code reuse, multiple traits, insteadof, aliases, visibility changes, limitations, and when composition is clearer.
Short Interview Answer (30-60 seconds)
Traits let PHP classes reuse methods and other members without inheriting from a common parent. A class can use multiple traits. If two imported traits contain a method with the same name, PHP produces a fatal error unless the conflict is resolved. I use insteadof to choose which implementation keeps the original name. I use as to add an alias or change visibility. Traits suit small shared behavior, while composition is clearer for behavior with dependencies, important state, or a separate responsibility.
Traits let several PHP classes share the same behavior even when those classes do not have the same parent. A trait can provide reusable methods and other class members. A class includes them with a use statement. When two included traits provide a method with the same name, PHP requires the developer to choose which one should be used. The other method can still receive another name. This keeps the choice clear and prevents PHP from silently selecting unexpected behavior.
Useful Questions to Ask the Interviewer
Should I demonstrate both insteadof and as?
Should I include a visibility change in the example?
Should I compare traits with object composition?
How to Explain It in an Interview
Traits provide horizontal code reuse. This means a class can include reusable behavior without extending another class. PHP supports only one parent class, but one class can use several traits.
A trait is declared with the trait keyword and imported into a class with use. Its methods behave as methods of the using class. A method declared directly in the class takes priority over a trait method. A trait method takes priority over a method inherited from a parent class.
If two imported traits define the same method name, PHP produces a fatal error unless the collision is explicitly resolved. The order of traits in the use statement does not choose a winner. The insteadof operator selects which trait implementation keeps the original method name. It excludes the competing implementation from that name within the using class.
The as operator adds another name for a trait method or changes its visibility. It does not rename or remove the original method. An alias can also have a different visibility. For example, a public trait method can receive a private alias while the original method remains public. Visibility can also be changed without creating a new name.
Traits can contain abstract methods, properties, static members, and constants. A trait cannot be instantiated and does not create a separate object. It also does not define a type contract. An interface should be used when callers need a guaranteed public API.
Method conflict operators resolve method collisions only. Trait properties and constants have separate compatibility rules. Conflicting declarations can cause a fatal error when their type, visibility, value, readonly status, or final status is incompatible.
Traits work best for small and closely related behavior. Composition is clearer when behavior has constructor dependencies, important mutable state, external communication, or several replaceable implementations. A separate object makes the dependency visible and easier to test.
Imported trait methods have normal class method behavior. Traits do not allocate a separate helper object for each instance. However, instance properties declared by a trait become properties of each using object and therefore use memory like other instance properties.
Example
The example uses FileWriter and ScreenWriter, which both define write. ReportWriter selects FileWriter::write with insteadof, so calling write uses the file implementation. It then creates a private alias named writeToScreen for ScreenWriter::write. The alias does not remove or rename the original ScreenWriter method inside the trait. The public writeBoth method can call the private alias because it is inside ReportWriter. Running the code first prints one file message. It then prints a second file message followed by a screen message.
Traits are useful when several unrelated PHP classes need a small shared implementation. Examples include formatting values, creating audit messages, normalizing input, exposing framework integration methods, or sharing a small group of utility methods that naturally belong to each class. Composition is usually better when the behavior needs services such as a logger, database connection, HTTP client, or configuration object. It is also better when the behavior owns important state, must be replaced during testing, or represents a separate business responsibility.
Why Interviewers Ask This
Interviewers ask this question to check whether a candidate understands code reuse in a language that supports only one parent class. They also test whether the candidate knows PHP method precedence, can resolve trait method collisions with insteadof and as, understands aliases and visibility changes, recognizes trait limitations, and can choose composition when shared behavior has its own state or dependencies.
Common interview mistakes
A common mistake is expecting PHP to select the first trait listed when two traits define the same method. PHP instead reports a fatal error until the collision is resolved. Another mistake is using as to choose the winning implementation. The winner is selected with insteadof, while as adds an alias or changes visibility. Developers may also believe that an alias removes the original method, but it creates an additional name. Other mistakes include treating a trait as an interface, calling a trait a second parent class, hiding service dependencies inside a trait, or placing too much state and unrelated behavior in one trait. Property and constant conflicts must also satisfy their own compatibility rules and cannot be resolved with insteadof.
Interview tip
Begin by saying that traits provide horizontal code reuse because PHP allows only one parent class. Then explain that unresolved duplicate trait methods cause a fatal error, insteadof chooses the implementation, and as adds an alias or changes visibility. Mention class, trait, and parent method precedence. Finish by explaining that traits suit small shared behavior, while composition is clearer for stateful behavior with dependencies.
Interviewer may ask next
What happens if two used traits define the same method and the class does not use insteadof?
PHP produces a fatal error because the method collision remains unresolved. PHP does not use the order in the use statement to choose an implementation. The class must explicitly select one method with insteadof or change the design so the conflicting methods are not imported together. This matters because an automatic choice could silently change behavior when a trait is added or modified.
When should composition be preferred over a trait?
Composition should be preferred when the behavior has its own responsibility, constructor dependencies, important mutable state, external communication, or interchangeable implementations. The class receives a separate object and calls it explicitly. This makes dependencies visible and makes replacement during testing easier. The tradeoff is an additional object and explicit delegation calls, but the design usually has clearer boundaries and is safer to maintain than a large stateful trait.
14. What is the difference between self, parent, and static in PHP?Language SpecificMedium
i Question Details
Explain compile-time class resolution, inheritance, late static binding, factory methods, and cases where self prevents polymorphic behavior.
Short Interview Answer (30-60 seconds)
The practical difference is how PHP chooses the class. self refers to the class where the current method is declared. parent refers to the immediate parent of the class where the current code is written. static uses late static binding and refers to the class that was called at runtime. I use self when behavior must stay fixed, parent when I need the parent implementation, and static when inherited code must respect the child class.
These three words tell PHP which class to use when one class extends another. The choice affects whether a child class can change inherited behavior. self keeps the operation tied to the class that contains the method. parent moves the operation to that class's immediate parent. static follows the class used in the original call. This difference matters most in shared factory methods and reusable base classes. Choosing the wrong word can create the wrong object, call the wrong method, or ignore a value supplied by a child class.
Useful Questions to Ask the Interviewer
Should an inherited method follow the child class?
Is the method expected to create an object?
Must the parent implementation also run?
How to Explain It in an Interview
self is resolved using the class where the current method was declared. For example, if Document declares a factory containing new self(), that factory creates a Document even when it is called as Report::createFixed(). This fixed resolution can prevent polymorphic behavior.
parent is resolved using the immediate parent of the class where the parent expression is written. It is commonly used inside an overridden method to call the implementation that the child replaced. A parent:: call is also a forwarding call. This means it preserves the class from the original runtime call if the parent method later uses static::.
static uses late static binding. PHP remembers the called class from the most recent non forwarding call. A direct call such as Report::createFlexible() sets Report as the called class. Therefore, new static() inside the inherited method creates a Report. Calls made with self::, parent::, or static:: normally forward that called class instead of replacing it.
Use self when the implementation must remain tied to the declaring class. Use parent when an override must reuse its immediate parent implementation. Use static for extensible factories, overridable class constants, shared configuration, and other inherited behavior that should follow the called class.
The keywords themselves do not copy objects or create extra objects. In the example, each new expression allocates one object. The meaningful difference is its class. The lookup cost is normally insignificant compared with application work, so production decisions should focus on correct inheritance behavior. Visibility and final declarations still apply. For example, late binding cannot legally call an inaccessible private method in a child class, and a final method cannot be overridden.
Example
The example uses Document as the base class and Report as the child class. createFixed uses new self(), so PHP creates Document because that method is declared in Document. createFlexible uses new static(), so PHP creates Report when the method is called through Report. declaredClass uses self::class and returns Document. calledClass uses static::class and returns Report. Report::description() uses parent::description() to run the immediate parent implementation before adding its own text.
Code
<?phpdeclare(strict_types=1);
classDocument{
publicstaticfunctioncreateFixed(): self{
// self is resolved to Document because this method is declared here.returnnewself();
}
publicstaticfunctioncreateFlexible(): static{
// static follows the class used for the runtime call.returnnewstatic();
}
publicstaticfunctiondeclaredClass(): string{
returnself::class;
}
publicstaticfunctioncalledClass(): string{
returnstatic::class;
}
publicfunctiondescription(): string{
return'Base document';
}
}
classReportextendsDocument{
publicfunctiondescription(): string{
// parent calls the immediate parent implementation.returnparent::description() . ' with report details';
}
}
$fixed = Report::createFixed();
$flexible = Report::createFlexible();
echoget_class($fixed) . PHP_EOL;
echoget_class($flexible) . PHP_EOL;
echoReport::declaredClass() . PHP_EOL;
echoReport::calledClass() . PHP_EOL;
echo$flexible->description() . PHP_EOL;
Where it is used
These keywords are used in inherited factory methods, base entity classes, reusable service classes, shared configuration methods, and overridden methods. A base factory can use new static() so each child creates its own object type. An overridden method can use parent::method() to keep shared parent work. A helper can use self when its behavior must remain tied to the class that declares it.
Why Interviewers Ask This
Interviewers ask this question to test whether a candidate understands inheritance, class scope resolution, method overriding, and late static binding in PHP. They also want to know whether the candidate can design an inherited factory or shared base class without accidentally fixing behavior to the wrong class.
Common interview mistakes
A common mistake is treating self and static as interchangeable. self remains tied to the declaring class, while static follows the called class. Another mistake is using new self() in a base factory that must return child objects. Developers may also think parent can select any ancestor, but it refers to the immediate parent of the class containing that expression. Another mistake is assuming parent:: discards late binding. It is a forwarding call, so a parent method that uses static:: can still see the original called class. Developers must also remember that visibility, final methods, constructor requirements, and return types still apply.
Interview tip
State the three resolution rules first. Then show one inherited factory where new self() creates the base class and new static() creates the called child class. Mention that parent:: calls the immediate parent and preserves the called class for later static:: resolution.
Interviewer may ask next
What called class is used when a child method invokes parent::factory() and the parent factory contains new static()?
The original runtime called class is used. parent::factory() is a forwarding call, so it does not replace the called class with the parent. If Report makes the original call, new static() in the parent factory creates a Report. This matters because parent logic can remain reusable while still preserving child specific behavior. Visibility and constructor compatibility must still allow the object to be created.
When should a production design use new self() instead of new static() in a factory method?
It should use new self() when the factory must always create the declaring class and child classes must not change that result. This gives fixed and predictable behavior. The tradeoff is that the factory is not polymorphic, so it is unsuitable when subclasses are expected to create their own types. The keyword does not provide a meaningful performance or memory advantage over new static(); the design choice should be based on required inheritance behavior.
15. How do closures capture variables in PHP?Language SpecificMedium
i Question Details
Explain the use clause, capture by value versus by reference, arrow-function implicit capture, object context, and common loop or mutation surprises.
Short Interview Answer (30-60 seconds)
PHP closures capture outside local variables through the use clause. use ($value) saves the variable value when the closure is created, while use (&$value) shares the same variable, so later changes are visible in both places. Arrow functions capture used outside variables automatically by value. Capturing an object by value still gives access to the same object instance, so its properties can be changed.
A small saved function may need information from the place where it was created. PHP lets the programmer decide whether that information should stay as it was at creation time or follow later changes. This matters when the function runs later, such as during sorting, filtering, event handling, or deferred work. Choosing the wrong behavior can make a saved function return an old value, unexpectedly change outside state, or make every function created in a loop use the same final value.
Useful Questions to Ask the Interviewer
Should changes made after creation be visible inside the closure?
Does the closure only read the outside value, or must it change it?
Is the captured value a scalar, an array, or an object?
How to Explain It in an Interview
A normal PHP anonymous function does not automatically receive ordinary local variables from the surrounding scope. The variables must be listed in a use clause.
With use ($count), PHP captures the value held by $count when the closure is created. If the outer variable is later assigned a different value, the closure still sees its captured value. This is normally the safer choice because the closure has stable and predictable input.
With use (&$count), PHP captures the variable by reference. The closure and the surrounding code access the same variable container. A change made in either place is visible in the other place. This is useful for counters or result collection, but shared mutation can make code harder to understand and test.
Arrow functions use the fn syntax. They automatically capture every outside variable used in their expression by value. They do not have a use clause, and assigning to a captured scalar does not update the outer scalar.
Objects require an important distinction. Capturing an object variable by value does not clone the object. The captured value still identifies the same object instance, so the closure can change its properties. If the outer variable is later assigned a different object, the closure continues to use the object captured earlier.
A non static closure created inside an object method can use $this automatically. A static closure has no $this context.
Loop behavior is a common surprise. use ($item) saves the value from each iteration. use (&$item) shares the reused loop variable, so closures executed later can all see its final value.
Captured values remain reachable while the closure remains reachable. Large objects can therefore stay in memory. Arrays captured by value use PHP value semantics and normally benefit from copy on write behavior, so a separate array allocation is generally needed only when one side mutates it.
Example
The example creates two groups of closures inside one loop. Each value capture closure remembers the current number when it is created, so the first group returns 1, 2, and 3. Each reference capture closure shares the same loop variable, so the second group returns the final value 3 three times. The arrow function captures the multiplier value 4 when it is created, so changing the outer multiplier to 10 does not change its result. The object example shows that value capture does not clone an object, so the closure changes the same object instance.
Code
<?phpdeclare(strict_types=1);
$valueClosures = [];
$referenceClosures = [];
foreach ([1, 2, 3] as$number) {
// Save the current number in this closure.$valueClosures[] = function () use ($number): int{
return$number;
};
// Share the reused loop variable with this closure.$referenceClosures[] = function () use (&$number): int{
return$number;
};
}
echo"Value capture: ";
foreach ($valueClosuresas$closure) {
echo$closure() . ' ';
}
echo PHP_EOL;
echo"Reference capture: ";
foreach ($referenceClosuresas$closure) {
echo$closure() . ' ';
}
echo PHP_EOL;
$multiplier = 4;
// Arrow functions capture used outside variables by value.$multiply = fn (int$input): int =>$input * $multiplier;
$multiplier = 10;
echo"Arrow function result: " . $multiply(3) . PHP_EOL;
$state = newstdClass();
$state->count = 0;
$increment = function () use ($state): void{
// Value capture does not clone the object.$state->count++;
};
$increment();
$increment();
echo"Object count: " . $state->count . PHP_EOL;
Where it is used
Closures are used in array callbacks, custom sorting, route handlers, middleware, event listeners, deferred jobs, dependency configuration, and callback based APIs. Value capture is useful when a callback must keep a stable setting or the current value from a loop iteration. Reference capture is useful when a callback must update a shared counter or collect results, but the mutation should be small and obvious. Arrow functions are useful for short mapping and filtering expressions. In long running workers and callback registries, developers should avoid capturing large service objects unless they are required because the closure can keep those objects and their related data in memory.
Why Interviewers Ask This
Interviewers ask this question to check whether a candidate understands when a closure receives an outside variable, whether later changes are visible, and how value capture differs from reference capture. It also tests knowledge of arrow functions, object behavior, loop surprises, memory retention, and safe production choices.
Common interview mistakes
A common mistake is assuming that a normal anonymous function automatically receives every outside local variable. Another mistake is expecting use ($value) to see a later assignment made to the outer variable. Developers may use use (&$value) inside a loop and then discover that every stored closure sees the final loop value. It is also incorrect to think that capturing an object by value creates a cloned object. The closure still accesses the same object instance. Other mistakes include expecting an arrow function to update an outer scalar, expecting $this inside a static closure, and capturing large objects in long lived callbacks without considering memory retention.
Interview tip
Start with the direct comparison between use ($value) and use (&$value). Then explain automatic value capture in arrow functions. Finish with the two main surprises: an object is not cloned by value capture, and reference capture inside a loop can make every stored closure see the final loop value.
Interviewer may ask next
What happens when several closures capture the same loop variable by reference?
They all share the same variable container. When the closures run after the loop, they normally read the loop variable's final value instead of the value from the iteration in which each closure was created. This matters because callbacks that look independent can return the same result. Capturing with use ($item) gives each closure the value from its own iteration.
What are the production tradeoffs of capturing arrays or objects in long lived closures?
The captured values remain reachable for as long as the closure remains reachable. A captured object can therefore keep the same object instance and its related object graph in memory. An array captured by value normally uses copy on write behavior, but mutation can require a separate array allocation. Capturing complete objects or large arrays is convenient, while capturing only the required small values can reduce memory retention and make dependencies clearer.
16. What is a PHP namespace?Language SpecificEasy
i Question Details
Define a PHP namespace as a way to organize code and prevent name collisions. Explain fully qualified names, namespace declarations, use imports and aliases, resolution of class and function names, and how namespaces work with file organization and autoloading without claiming that a namespace loads files by itself.
Short Interview Answer (30-60 seconds)
A PHP namespace groups related names and helps prevent name collisions. I declare one with the namespace statement. I can then refer to a class by its fully qualified name or import it with use. An alias can give an imported name a different local name. Namespaces organize names, but they do not load files by themselves. File loading is normally handled by an autoloader such as Composer.
Detailed Explanation
A namespace gives a group of PHP classes and functions its own naming area. This lets two parts of an application use the same short name without confusing PHP about which one is meant. You give the group a name near the start of the PHP file. Other code can then refer to an item by its complete name or bring that name into the current file with a shorter local name. A namespace only changes how names are identified. It does not find or open PHP files. File loading is a separate job.
Useful Questions to Ask the Interviewer
Would you like a simple class example showing namespace and use?
Should I also explain how namespaces work with Composer autoloading?
How to Explain It in an Interview
A PHP namespace is a way to organize named code and avoid name collisions. For example, two libraries might both define a class called Logger. They can exist together if their complete names are different, such as App\Logging\Logger and Vendor\Tools\Logger.
A file can declare a namespace with a statement such as namespace App\Logging;. A class or function declared after that statement belongs to that namespace unless another namespace declaration changes the current namespace.
A fully qualified name starts with a backslash and identifies a name from the global namespace, such as \App\Logging\Logger. An unqualified class name such as Logger normally refers to the current namespace unless a use import provides another meaning. PHP does not fall back to a global class when that namespaced class is missing.
The use statement imports a name for easier reference in the current file. For example, use App\Logging\Logger; lets the code write Logger. PHP also supports aliases, such as use App\Logging\Logger as AppLogger;. The alias changes only the local name used by that file.
Function resolution has an important difference. An unqualified function call inside a namespace first refers to that namespace. If the namespaced function does not exist, PHP can fall back to a global function with that name. Using a fully qualified function name makes the target explicit.
Namespaces are often designed to match project folders, but PHP itself does not require that relationship. Composer projects commonly use PSR 4 rules to map namespace prefixes to directories. Composer can then register an autoloader that loads matching class files when needed.
The key limitation is that a namespace never loads a file by itself. It controls names. Autoloading is a separate mechanism. Namespace use normally has no meaningful application level memory or performance cost compared with the work done by the application itself.
Where it is used
Namespaces are used in most modern PHP applications and libraries. They separate application classes from package, framework, and vendor classes that may use the same short names. They are also commonly combined with Composer and PSR 4 autoloading so a project can keep classes in predictable directories while avoiding manual require statements throughout the application.
Why Interviewers Ask This
Interviewers ask this to check whether the candidate understands how PHP organizes named code such as classes and functions, how PHP resolves names, and how namespaces prevent naming conflicts. They also want to see whether the candidate understands the important difference between naming code and loading the file that contains that code.
Common interview mistakes
A common mistake is saying that a namespace loads a PHP file. It does not. Another mistake is assuming that a namespace must exactly match the directory structure. PHP itself does not require that mapping. Developers may also confuse use with file inclusion. The use statement imports a name into the current naming context. It does not work like require. Another mistake is expecting an unqualified class name to fall back to a global class when a namespaced class is missing. That fallback applies to unqualified functions and constants, not classes. An alias also changes only the local name used in that file. It does not rename the original class.
Interview tip
Start by saying that namespaces organize names and prevent collisions. Then explain a fully qualified name, a use import, and an alias. Mention that class resolution and function resolution have an important difference. Finish by making the key distinction that namespaces identify code, while an autoloader is responsible for loading files.
Interviewer may ask next
How does PHP resolve an unqualified function name inside a namespace?
PHP first tries the function name in the current namespace. If that namespaced function does not exist, PHP can fall back to a global function with the same name. This matters because adding a function with that name to the namespace can change which function is called. Using a fully qualified function name makes the intended target explicit.
Does using a namespace mean PHP automatically knows which file contains a class?
No. A namespace only defines the class name and its naming context. It does not load the class file. In production projects, Composer commonly registers an autoloader and uses PSR 4 mappings to connect namespace prefixes with directories. The tradeoff is that the project must keep its autoload configuration, namespace names, and file organization consistent for automatic loading to work correctly.
17. How do PHP namespaces and Composer PSR-4 autoloading work together?Language SpecificMedium
i Question Details
Explain namespace declarations, use imports and aliases, namespace-to-directory mappings, generated autoloaders, case sensitivity, and common deployment mistakes.
Short Interview Answer (30-60 seconds)
PHP namespaces give classes unique fully qualified names, while Composer PSR 4 rules map namespace prefixes to base directories. When PHP first needs an undefined class, the Composer autoloader uses that mapping to locate and include the matching file. The namespace, subdirectories, class name, and file name must use matching letter case. A use statement only creates a local name or alias. It does not include the class file by itself.
Detailed Explanation
Namespaces give PHP classes clear and unique names. Composer connects the beginning of each class name to a folder. When the program needs a class that has not been opened yet, Composer finds and opens the matching file. This avoids writing many manual file includes. The important rule is that the declared class name, folder structure, and file name must agree. A spelling or letter case difference may remain hidden on one computer but fail after deployment on a system that treats upper and lower case letters differently.
Useful Questions to Ask the Interviewer
What namespace prefix and source directory does the project use?
Should production autoload optimization be included in the discussion?
Does the deployment environment use a case sensitive file system?
How to Explain It in an Interview
A namespace declaration becomes part of a class fully qualified name. For example, a class declared inside namespace App\Service with the name Mailer has the fully qualified name App\Service\Mailer.
A use declaration imports that name into the current file. For example, use App\Service\Mailer allows the file to write Mailer instead of the full name. An alias such as use App\Service\Mailer as EmailMailer provides another local name. Imports are resolved when PHP compiles the file. They do not load files, and each file has its own imports. ([php.net](https://www.php.net/manual/en/language.namespaces.importing.php))
Composer PSR 4 configuration maps a namespace prefix to one or more base directories. A composer.json mapping of App\\ to src means that App\Service\Mailer maps to src/Service/Mailer.php. Composer removes the mapped prefix, converts the remaining namespace separators into directory separators, and adds the PHP file extension. Subdirectory names and the final file name must match the referenced class name letter case. ([php-fig.org](https://www.php-fig.org/psr/psr-4/))
Composer generates vendor/autoload.php and supporting files under vendor/composer. The application normally requires vendor/autoload.php once. Composer then registers an autoload function with PHP. When PHP encounters an undefined class like App\Service\Mailer, PHP calls registered autoload functions before reporting that the class cannot be found. ([php.net](https://www.php.net/manual/en/language.oop5.autoload.php))
Namespaces and autoloading therefore solve different problems. Namespaces identify classes. Composer locates their files. PHP does not require one class per file, but PSR 4 works best when each autoloaded class has a predictable matching file.
In production, run Composer install from the locked dependency file and regenerate autoload data after changing mappings. Optimized autoloading builds a class map for known classes. This uses additional generated metadata and some memory, but reduces repeated file system checks. Authoritative class maps require more care because classes generated after deployment cannot be discovered unless they are present in the generated map.
Where it is used
This approach is used in modern PHP applications, reusable Composer packages, command line programs, web applications, background workers, and test suites. A project may map App to src for production classes and Tests to tests for development classes. Third party packages provide their own mappings, and Composer combines them into one generated autoloader. Long running workers should deploy updated code and autoload metadata together, then restart workers so existing processes do not continue using already loaded class definitions.
Why Interviewers Ask This
Interviewers ask this question to check whether a candidate understands the difference between naming a PHP class and locating its source file. It also tests whether the candidate can configure Composer correctly, follow PSR 4 path rules, explain PHP autoload behavior, and diagnose production failures caused by incorrect prefixes, directory paths, file names, letter case, or stale generated autoload data.
Common interview mistakes
Common mistakes include believing that a use declaration includes a file, placing a class in a directory that does not match the configured prefix, declaring the wrong namespace inside the file, and using file or directory letter case that differs from the class name. Other mistakes include forgetting to require vendor/autoload.php, changing composer.json without regenerating autoload data, deploying source files without matching Composer files, running Composer update instead of Composer install during a normal locked deployment, and enabling an authoritative class map when the application creates classes dynamically at runtime.
Interview tip
Explain the two responsibilities separately. First say that namespaces identify classes. Then say that Composer maps those names to files. Use one example from App\Service\Mailer to src/Service/Mailer.php. Finish by mentioning that use only imports a name, letter case must match, and production deployment must regenerate the autoloader when mappings change.
Interviewer may ask next
What happens when the namespace or file path uses different letter case?
The class may fail to autoload because PSR 4 requires class references, subdirectory names, and the final file name to use matching letter case. PHP class names are generally resolved without letter case differences after a class is loaded, but PSR 4 file lookup still requires case correct references and paths. This matters because a mismatch may appear to work on a case insensitive development file system and then produce a class not found error on a case sensitive production file system. The fix is to correct the declaration, reference, directory names, and file name rather than relying on the operating system.
What are the tradeoffs of optimized and authoritative Composer autoloading?
Optimized autoloading builds a class map for known classes, which reduces file system checks and usually improves production class lookup. The generated map adds metadata and consumes some memory, but that cost is normally small compared with the benefit in a large application. An authoritative class map goes further by treating classes missing from the map as nonexistent. This makes failed lookups faster, but runtime generated classes cannot be discovered unless they were included when the map was built. Production deployment must rebuild the map whenever classes or autoload mappings change. ([getcomposer.org](https://getcomposer.org/doc/articles/autoloader-optimization.md))
18. What is Composer?Language SpecificEasy
i Question Details
Define Composer as the standard dependency manager for PHP projects. Explain composer.json, composer.lock, package version constraints, repositories such as Packagist, the vendor directory, install versus update, scripts, and the generated autoloader. Distinguish Composer from PHP itself, a system package manager, and a web framework.
Short Interview Answer (30-60 seconds)
Composer is the standard dependency manager for PHP projects. I declare the packages my project needs in composer.json, and Composer resolves compatible versions and normally installs them in the vendor directory. composer.lock records the exact resolved versions so the same dependency set can be installed again. I normally use composer install with an existing lock file and composer update when I intentionally want Composer to resolve newer allowed versions. Composer also generates an autoloader that applications can use to load installed classes.
Detailed Explanation
Composer helps a PHP project use reusable software from other developers in a controlled way. Instead of finding files by hand, copying them into a project, and remembering which copies were used, you describe what the project needs. Composer finds suitable versions, downloads them, and records the choices. This makes it easier for developers, test systems, and production systems to use the same software. It also puts downloaded packages in one normal location and prepares loading information so the application can use their classes without manually including every file.
Useful Questions to Ask the Interviewer
Would you like me to explain the difference between composer install and composer update?
Should I also explain composer.json, composer.lock, Packagist, and the generated autoloader?
How to Explain It in an Interview
Composer is the standard dependency manager for PHP projects. It is a separate command line tool. It is not PHP itself, an operating system package manager, or a web framework.
composer.json describes the packages a project requires. It can also contain version constraints that tell Composer which package versions are acceptable. Composer resolves a set of versions that satisfies those constraints and the requirements of the packages involved.
Packagist is the default public package repository used by Composer. A project can also configure other repositories when needed.
Composer normally installs downloaded packages in the vendor directory. It also generates vendor/autoload.php. An application can require that file so classes from installed packages can be loaded automatically. Packages often provide loading rules such as PSR 4 mappings, and Composer uses those rules when generating its autoloader.
composer.lock records the exact versions Composer resolved. When a lock file exists, composer install installs those locked versions. If there is no lock file, composer install resolves dependencies from composer.json and creates a lock file. This distinction is important because a committed lock file helps development, testing, and production use the same dependency versions.
composer update resolves versions again within the constraints in composer.json and updates composer.lock. It can update all dependencies or selected packages. Updates should therefore be intentional and tested.
Composer can also run scripts attached to supported Composer events. Because such scripts can execute commands or PHP callbacks, projects should use trusted packages and review dependency changes carefully.
Where it is used
Composer is used in modern PHP applications that depend on reusable libraries, development tools, or frameworks. Teams commonly use it during local development, automated testing, build processes, and production deployment. A project may use Composer to install an HTTP client, a logging library, a testing tool, or framework packages. Applications normally commit composer.lock so tested dependency versions can be installed consistently in other environments. The generated autoloader also gives the application one standard entry point for loading classes provided by installed packages.
Why Interviewers Ask This
Interviewers ask this to check whether the candidate understands how PHP projects manage external packages in real applications. They want to see whether the candidate knows the purpose of composer.json, composer.lock, version constraints, repositories, the vendor directory, scripts, and automatic class loading. They also want to confirm that the candidate understands the important difference between installing locked dependencies and intentionally resolving newer allowed versions.
Common interview mistakes
A common mistake is saying Composer is part of PHP. Composer is a separate dependency management tool. Another mistake is calling Composer a web framework or treating it as the same kind of tool as an operating system package manager. Developers also sometimes treat composer install and composer update as identical. With an existing lock file, install uses the versions recorded there. update resolves package versions again within the constraints in composer.json and changes the lock file. Another mistake is assuming install always requires a lock file. If no lock file exists, install resolves dependencies and creates one. Developers should also avoid editing files inside vendor because Composer can replace those files during later installs or updates.
Interview tip
Start by saying that Composer is the standard dependency manager for PHP projects. Then explain composer.json, composer.lock, Packagist, vendor, install, update, and the generated autoloader. Clearly state that install normally reproduces locked versions while update intentionally performs dependency resolution again. Finish by saying that Composer is separate from PHP itself and is not a web framework.
Interviewer may ask next
What happens when you run composer install if composer.lock does not exist?
Composer resolves dependency versions from the constraints in composer.json, installs the resolved packages, and creates composer.lock. This is different from running composer install when a lock file already exists, because an existing lock file tells Composer which exact resolved versions to install. The distinction matters because the first resolution can select any versions allowed by the current constraints, while later locked installs can reproduce that selected dependency set.
Why should a production deployment normally use composer install instead of composer update?
A production deployment should normally use composer install with the committed composer.lock file because it installs the dependency versions that were already resolved and tested. composer update performs dependency resolution again and can select newer versions that still satisfy composer.json. That may introduce changes that were not tested with the application. The tradeoff is that dependency updates must be performed separately and intentionally, but this gives the deployment process much better repeatability and control.
19. What is PSR-4 autoloading?Language SpecificEasy
i Question Details
Define PSR-4 as a PHP-FIG specification that maps namespace prefixes to base directories so class names can be resolved to PHP files. Explain the namespace-to-directory and class-to-file mapping, case sensitivity, Composer autoload configuration, vendor/autoload.php, dump-autoload, and the difference between namespaces and autoloading.
Short Interview Answer (30-60 seconds)
PSR 4 is a PHP FIG specification for mapping namespace prefixes to base directories so an autoloader can find PHP class files. For example, if App\ maps to src/, then App\Service\PaymentService maps to src/Service/PaymentService.php. Composer commonly generates this autoloader, and the application usually includes vendor/autoload.php once during startup.
Detailed Explanation
PSR 4 gives a PHP project a predictable rule for finding the file that contains a class. Instead of manually loading every class file, the project connects the beginning of a class name to a starting folder. The remaining parts of the name point to folders inside that starting folder. The final class name points to a PHP file. Composer can prepare this setup for the application. This makes larger projects easier to organize because class names and file locations follow one consistent rule. Namespaces provide names for classes, while autoloading provides a way to find their files.
Useful Questions to Ask the Interviewer
Would you like a Composer configuration example?
Should I also explain the difference between namespaces and autoloading?
How to Explain It in an Interview
PSR 4 is a specification from PHP FIG. It defines how a fully qualified class name can be resolved to a PHP file by an autoloader.
For example, suppose the namespace prefix App\ maps to the base directory src/. The class App\Service\PaymentService maps to src/Service/PaymentService.php. The configured namespace prefix is removed first. Each remaining namespace separator represents a directory boundary. The final class name becomes the file name with the .php extension.
Case matters. The namespace parts and class name used for the mapping must match the case of the corresponding directories and file name. This is especially important when code moves between file systems that handle case differently.
Composer is the common tool used to configure and generate PSR 4 autoloading. In composer.json, the autoload section can map a prefix such as App\ to src/. After changing the autoload configuration, run the Composer command composer dumpautoload to regenerate the autoload files. Composer also regenerates them during relevant install and update operations.
The application normally includes vendor/autoload.php once during startup. That file registers Composer's autoloader with PHP. When PHP encounters a class that is not already loaded, registered autoloaders can be called. Composer then uses its generated mapping information to locate and include the matching file.
Namespaces and autoloading solve different problems. A namespace gives a class its qualified name and prevents many naming conflicts. Autoloading controls how the file containing that class is found and loaded. Declaring a namespace by itself does not load a file.
Where it is used
PSR 4 is commonly used in Composer based PHP applications and reusable packages. It is useful when source code contains many classes under directories such as src/ and tests/. Production applications commonly load vendor/autoload.php during startup so application classes and installed package classes can be loaded when PHP first needs them.
Why Interviewers Ask This
Interviewers ask this to check whether the candidate understands how modern PHP projects organize classes and load class files when they are first needed. It also tests whether the candidate can separate namespaces from autoloading and whether they understand how Composer commonly implements PSR 4 mappings in production projects.
Common interview mistakes
Common mistakes include thinking that declaring a namespace automatically loads its file, placing a class in a directory that does not match the configured mapping, using directory or file name case that does not match the namespace or class name, changing Composer autoload configuration without regenerating the autoload files, and forgetting to include vendor/autoload.php in the application startup path.
Interview tip
Start with the mapping rule. Give one simple example such as App\Service\PaymentService mapping to src/Service/PaymentService.php. Then explain that Composer commonly generates and registers the autoloader. Finish by saying that namespaces name classes, while autoloading finds and loads their files.
Interviewer may ask next
What happens if the case of a class name or file path does not match the PSR 4 mapping?
The case should match exactly. PSR 4 requires the relevant namespace and class portions to match the case of their corresponding directory and file names. A mismatch can appear to work on a file system that ignores case but fail on a case sensitive production system. Consistent case therefore prevents environment specific loading failures.
Why use Composer PSR 4 autoloading instead of manually including every class file?
Composer PSR 4 autoloading is usually easier to maintain in a structured application. Code can refer to qualified class names without keeping a long list of manual file includes. Composer also manages autoload information for installed packages and application classes. The main tradeoff is that namespace mappings, directory structure, and file names must stay consistent, and generated autoload information must be refreshed when its configuration changes.
20. What is the difference between session_unset() and session_destroy()?Language SpecificEasy
i Question Details
Explain what each function changes, what remains in the current request, cookie cleanup, and the steps needed for a complete logout.
Short Interview Answer (30-60 seconds)
session_unset() clears all variables from the active session, but it does not end the session. session_destroy() deletes the stored data associated with the active session, but it does not clear the current $_SESSION array or remove the session cookie. For a complete logout, I clear $_SESSION, delete the session cookie when cookies are used, call session_destroy(), and stop further protected processing.
These two actions remove different parts of the information used to remember a signed in visitor. One removes the values available to the page that is running now. The other removes the saved record used by later pages. Neither action alone removes every trace of the old login. A complete logout should clear the current values, remove the small browser marker when it is used, delete the saved record, and stop the page from continuing as the signed in user. This order helps prevent old login information from being reused.
Useful Questions to Ask the Interviewer
Does the application use the normal PHP session cookie?
Should logout remove every session value or only authentication values?
Does the application use a custom session storage handler?
How to Explain It in an Interview
session_unset() removes all variables registered in the active session. With normal modern PHP session code, this clears the values available through $_SESSION. The session identifier still exists, and the session remains active. New values can therefore be added to the same session during the current request.
session_destroy() deletes the stored data associated with the active session. The exact storage operation depends on the configured session handler. For example, the normal file handler removes the stored session record. However, session_destroy() does not clear the $_SESSION array that PHP already loaded into memory for the current request. It also does not remove the session cookie from the browser.
This difference is important during logout. Calling only session_unset() clears the variables but leaves the session active. Calling only session_destroy() deletes the stored record, but later code in the same request can still read values that remain in $_SESSION. The browser can also continue sending the old session identifier if its cookie is not deleted.
A complete logout normally starts or resumes the session, assigns an empty array to $_SESSION, deletes the session cookie using the same cookie path, domain, secure setting, HTTP only setting, and same site setting, and then calls session_destroy(). The application should immediately redirect or return a response so protected code does not continue running.
If the application must keep safe preferences, such as a language choice, it can remove only authentication related keys instead of destroying the entire session. That approach requires careful review so no sensitive value remains.
Example
The code resumes the active session, clears the $_SESSION array for the current request, and reads the existing session cookie settings. When PHP uses cookies for sessions, it expires the session cookie with the same path, domain, secure setting, HTTP only setting, and same site setting. It then calls session_destroy() to delete the stored session data. Finally, it redirects and exits so no protected code continues after logout.
Code
<?phpdeclare(strict_types=1);
// Resume the current session before changing or destroying it.session_start();
// Clear session values that are loaded for this request.$_SESSION = [];
// Remove the browser cookie when PHP uses cookies for sessions.if ((bool) ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(
session_name(),
'',
[
'expires' => time() - 42000,
'path' => $params['path'],
'domain' => $params['domain'],
'secure' => $params['secure'],
'httponly' => $params['httponly'],
'samesite' => $params['samesite']
]
);
}
// Delete the stored data associated with the current session.session_destroy();
// Prevent protected code from continuing after logout.header('Location: /login');
exit;
Where it is used
This behavior is used in login systems, administrator panels, customer accounts, shopping carts, and applications that store temporary user state. session_unset() is useful when all current session variables should be cleared while the session remains active. session_destroy() is used when the stored session should be ended. Production logout code commonly clears the current array, removes the session cookie, destroys the stored session, and immediately redirects or returns a response.
Why Interviewers Ask This
Interviewers ask this question to check whether the candidate understands the difference between clearing session variables and deleting stored session data. It also tests whether the candidate knows what remains available during the current request, how the session cookie behaves, and which separate steps are required for a complete logout.
Common interview mistakes
A common mistake is assuming that session_destroy() also clears $_SESSION. Values already loaded for the current request remain available until the application clears them or the request ends. Another mistake is assuming that session_unset() ends the session. It only clears registered session variables. Developers may also forget to delete the session cookie, use cookie settings that do not match the original cookie, call these functions before starting the session, continue running protected code after logout, or destroy the entire session when only authentication values should be removed.
Interview tip
Explain the distinction first. session_unset() clears session variables, while session_destroy() deletes stored session data. Then state what remains after each call and finish with the complete logout sequence: clear $_SESSION, remove the cookie, destroy the session, and stop further processing.
Interviewer may ask next
Can $_SESSION still contain values after session_destroy() is called?
Yes. session_destroy() deletes the stored session data, but it does not clear the $_SESSION array already loaded for the current request. Code that runs later in the same request can still read those values. This matters because logout code should clear $_SESSION before destroying the session and should stop protected processing immediately afterward.
Should an application always destroy the entire session during logout?
No. Destroy the entire session when all session state should end. If the application must preserve safe preferences, it can remove only the authentication related keys. The tradeoff is that selective clearing preserves useful state, but it requires careful review to ensure that no login token, authorization value, or other sensitive data remains.
More questions load as you scroll
Disclaimer: This interview guide is for educational and informational purposes only. It is designed to help readers prepare, but it does not guarantee any interview result, hiring decision, offer, or outcome. Interview questions, hiring criteria, and preferred answers can vary by employer, interviewer, industry, location, and time. The examples and explanations reflect the authors' research and judgment, are provided without warranties of any kind, and should not be treated as the only correct approach. Diagrams are simplified illustrations intended to highlight the main components and their interactions; actual systems and implementations may be more complex. Alternative approaches may be equally valid or better suited to a particular question, context, or interviewer. To the fullest extent permitted by applicable law, the author, contributors, and publisher are not liable for decisions made, actions taken, or losses incurred based on this guide.
Content Accuracy and Verification: To the fullest extent permitted by applicable law, we do not represent or warrant that interview guides, questions, answers, examples, or diagrams are accurate, complete, current, error-free, or suitable for any particular purpose. You are responsible for independently reviewing and verifying the information before relying on it.