user guide  »  mvc


Pop PHP Framework is an MVC framework. It is assumed that you have some familiarity with the MVC design pattern. An overly simple description of it is that the "controller" (C) serves as the bridge between the "model" (M) and the "view" (V). It calls the models required to handle the business logic of the request, returning the results of what was requested back to the user in a view. The basic idea is separation of concerns in that each component of the MVC pattern is only concerned with the one area it is assigned to handle, and that there is very little, if any, cross-cutting concerns among them.


There is a controller interface Pop\Controller\ControllerInterface and an abstract controller class Pop\Controller\AbstractController that are provided with the core components of the Pop PHP Framework. The main application object and router object are wired to interact with controller objects that extend the abstract controller class, or at least implement the controller interface. The functionality is basic, as the API manages a default action, a maintenance action and the dispatch method:

  • $controller->setDefaultAction($default)
    • The "setDefaultAction" method sets the default action to handle a request that hasn't been assigned an action. Typically, this would be an "error" method or something along those lines. You can also set the protected $defaultAction property within your child controller class directly.
  • $controller->getDefaultAction()
    • This method retrieves the name of the current default action.
  • $controller->setMaintenanceAction($maintenance)
    • The "setMaintenanceAction" method sets the action to handle a request while the application is in maintenance mode. You can also set the protected $maintenanceAction property within your child controller class directly.
  • $controller->getMaintenanceAction()
    • This method retrieves the name of the current maintenance action.
  • $controller->bypassMaintenance()
    • This method retrieves the flag that determines if the controller can bypass the maintenance mode check. This is useful for back-end applications that help manage the public-facing side of an application. With the $bypassMaintenance property set to false, the back-end side of an application will be allowed to continue to function while the public facing side will display as "down for maintenance."
  • $controller->dispatch($action = null, $params = null)
    • This is the main dispatch method, which will look for the "$action" method within the controller class and attempt to execute it, passing the "$params" into it if they are present. If the "$action" method is not found, the controller will fall back on the defined default action.


The popphp/pop-view component provides the functionality for creating and rendering views. The topic of views will be covered more in-depth in the next section of the user guide, Views. But for now, know that the view component supports both file-based templates and string or stream-based templates. Data can be pushed into and retrieved from a view object and a template can be set in which the data will be rendered. A basic example would be:

$data = [
    'title'   => 'Home Page',
    'content' => '<p>Some page content.</p>'

$view = new Pop\View\View('index.phtml', $data);

echo $view;


There is a base abstract model class provided that can be extended to create the model classes needed for your application. The abstract model class is a simple and bare-bones data object that can be extended with whatever methods or properties you need to work with your model. Data from the abstract model object is accessible via array access and magic methods, and the model object is countable and iterable.

Data Models

Going one level further, the abstract class Pop\Model\AbstractDataModel is also available, which provides a tightly integrated API which some common interactions with a database and its records. The basic requirements are that there is a model class that extends the abstract data model and a subsequent related table class (see the pop-db documentation for more info.) In the example below, the classes MyApp\Model\User and MyApp\Table\Users are created, and by that naming convention, they are linked together.


namespace MyApp\Table;

use Pop\Db\Record;

class Users extends Record


namespace MyApp\Model;

use Pop\Model\AbstractModel;

class User extends AbstractDataModel


The available API in the data model object is:

Static Methods
  • fetchAll(?string $sort = null, mixed $limit = null, mixed $page = null, bool $asArray = true): array|Collection
  • fetch(mixed $id, bool $asArray = true): array|Record
  • createNew(array $data, bool $asArray = true): array|Record
  • filterBy(mixed $filters = null, mixed $select = null): static
Instance Methods
  • getAll(?string $sort = null, mixed $limit = null, mixed $page = null, bool $asArray = true): array|Collection
  • getById(mixed $id, bool $asArray = true): array|Record
  • create(array $data, bool $asArray = true): array|Record
  • update(mixed $id, array $data, bool $asArray = true): array|Record
  • replace(mixed $id, array $data, bool $asArray = true): array|Record
  • delete(mixed $id): int
  • remove(array $ids): int
  • count(): int
  • describe(bool $native = false, bool $full = false): array
  • hasRequirements(): bool
  • validate(array $data): bool|array
  • filter(mixed $filters = null, mixed $select = null): AbstractDataModel
  • select(mixed $select = null): AbstractDataModel
Create new
use MyApp\Model\User;

$user = User::createNew($userData);
use MyApp\Model\User;

$userModel = new User();
$user = $userModel->update(1, $userData);

The update() method acts like a PATCH call and replace() acts like a PUT call and will replace and reset all model data.

use MyApp\Model\User;

$userModel = new User();
$userModel->remove([2, 3, 4]);
use MyApp\Model\User;

$users = User::fetchAll();
$user  = User::fetch(1);
Filter and sort
use MyApp\Model\User;

$users = User::filter('username LIKE myuser%')->getAll('-id', '10', 2);

The above call filters the search by the filter string and sorts by ID DESC (-id). Also, it sets the limit to 10 and starts the page offset on the second page.