1
\$\begingroup\$

In order to improve my PHP skills I decided to implement my own MVC in PHP.

So far it can display movies on the main page and show movies by categories. Obviously I use rewrite mode in .htaccess file. I don't want to show to much at once so I will show the router code and the code that displays movies by category. An URL can look like this /categories/categoryName/ or /categories/categoryName/page/number/

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ router.php

Router code

 function autoloadClass($className) 
{
  if(file_exists("php/model/$className.php"))
  {
    require "php/model/$className.php";
  }
  else if(file_exists("php/view/$className.php"))
  {
    require "php/view/$className.php";  
  }
  else if(file_exists("php/controler/$className.php"))
  {
     require "php/controler/$className.php"; 
  }
  else if(file_exists("php/extra/$className.php"))
  {
     require "php/extra/$className.php";   
  }
}

spl_autoload_register('autoloadClass');

class Router
{
  public $parameters = null;
  public $modelName;
  public $viewName;
  public $controlerName;

  private function getClassName(&$action)
  {
    $classes = array(
    "kategorie" => "Categories" );

    return $classes[$action];
  }

  function __construct()
  {
        $arr = explode("/",$_SERVER['REQUEST_URI']);      
        $userAction = $arr[1];
        $userAction = ($userAction === "" || $userAction === "strona") ? "MainPage" : $this->getClassName($userAction); 

        $arrLength = count($arr);

        $this->modelName = $userAction."Model";
        $this->viewName = $userAction."View";
        $this->controlerName = $userAction."Controler";

        if($arrLength > 3)
        {
            $this->parameters = array(); 

            for($i = 2; $i < $arrLength - 1; ++$i)
            {
              array_push($this->parameters, $arr[$i]);  
            }       

        } 
  }

}

$router = new Router;
$model = new $router->modelName();
$controler = new $router->controlerName($model);
$controler->initiate($router->parameters);
$view = new $router->viewName($model);
$view->render();

Abstract class for all controlers

abstract class Controler
{
  private $model;
  abstract function initiate($parameters);
}

Controler for categories display

class CategoriesControler extends Controler
{
  function __construct($model)
  {
    $this->model = $model;
  } 

  function initiate($parameters)
  {
    $categoryName = $parameters[0];
    $pageNumber = (array_key_exists(2,$parameters)) ? $parameters[2] : 1;
    $this->model->categoryName = $categoryName;
    $this->model->pageNumber = Intval($pageNumber);

  }  
}

Model

class CategoriesModel
{
  public $pageNumber;
  public $categoryName;

     private function createCoreQuery()  
    {

      switch($this->categoryName)  //it is just a part to demonstrate the mechanism
      {


        case "amatorskie-porno" :
         return "poziom LIKE 'amatorski' " ;
        break;

        case "azjatki" :
          return "rasa LIKE 'azjatki' ";
        break;


      } 

    }

    private function modifyQuery(&$coreQuery)
    {

          $number = $this->pageNumber - 1;

          if($number === 0)
          {
            return "SELECT * FROM Pornusy WHERE ".$coreQuery." ORDER BY klucz DESC LIMIT 50";  
          }
          else
          {
            $offset = $number * 50;
            return "SELECT * FROM Pornusy WHERE ".$coreQuery." ORDER BY klucz DESC LIMIT 50 OFFSET $offset"; 
          }

    }

     private function calculatePageControls($total)
    {
      $maxPageNumber = ceil($total / 50);
      $pageNumber = $this->pageNumber;
      $pageControls = new CategoriesControlsData();

      if($maxPageNumber - 5 >= $pageNumber)
      {
        $pageControls->pageControlNumberLeft = $pageNumber;
        $pageControls->activePagePosition = 1;
      }
      else
      {
        $pageControls->pageControlNumberLeft = $maxPageNumber - 4;
        $pageControls->activePagePosition = 5 + $pageNumber - $maxPageNumber;
      }

      $pageControls->maxPageNumber = $maxPageNumber;

      return $pageControls; 
    }

  function getMoviesData()
  {
    $dataBase = mysqli_connect();

        if(!$dataBase)
        {
          return null;
        }
        else
        {
          $coreQuery = $this->createCoreQuery();
          mysqli_query($dataBase,"SET CHARSET utf8");
          $query = "SELECT COUNT(*) as total FROM Pornusy WHERE ".$coreQuery;
          $result = mysqli_query($dataBase,$query);
          $row = mysqli_fetch_assoc($result);
          $moviesNumber = Intval($row['total']);

          $query = $this->ModifyQuery($coreQuery);
          $result = mysqli_query($dataBase,$query);

          $movies = array();

          while($row = mysqli_fetch_assoc($result))
          {
            array_push($movies, new Movie($row['opis'], $row['gwiazdy'],$row['wyswietlenia'], $row['sekundy'],$row['minuty'],$row['godziny'], $row['lektorpl'],$row['klucz']));
          }

          mysqli_close($dataBase);
          $controls = $this->calculatePageControls($moviesNumber);
          return new PagePackage($movies,$controls);
        }
 }
}

View

class CategoriesView
{
  private $data;
  public $pageHeader;
  public $cssClassName;

  function render()
 {

    if($this->model->categoryName === "wszystkie")
    {
        if(file_exists("php/template/AllCategories.php"))
        {
          require "php/template/AllCategories.php";
        }
    }
    else
    {
      $this->data = $this->model->getMoviesData();
      $this->pageHeader =  $this->parseCategory();
      $this->cssClassName = $this->getCSSClassName();

         if(file_exists("php/template/SelectedCategory.php"))
        {
          require "php/template/SelectedCategory.php";
        }     
    }

 }

  private function parseCategory()  
    {
        switch($this->model->categoryName) //just a part to demonstrate
        {
            case "amatorskie-porno" :
              return "Amatorskie";
            break;

            case "biale" :
               return "Białe";
            break;


            default:
             return ucfirst($this->model->categoryName);
            break;
        }
    }

    private function getCSSClassName()  //translates url to css class. Just one to demonstrate
    {
        $arr = array( 
        'amatorskie-porno' => 'amateur-header',

                           );
        return $arr[$this->model->categoryName];
    }

    private function createTimeLabel($movie)
    {
      $seconds = &$movie->seconds;
      $hours = &$movie->hours;
      $minutes = &$movie->minutes;

      $seconds = $seconds < 10 ? "0$seconds" : $seconds;
      $hours = $hours != null ? "0$hours:" : "";

      if($minutes == null)
      {
         $minutes = "00:";  
      }
      else
      {
        $minutes = ($minutes < 10) ? "0$minutes:" : "$minutes:";
      }  

      return $hours.$minutes.$seconds;
    }

    function showMovies() //wyświetla filmy w szablonie
    {
      $movies = &$this->data->moviesData;

      foreach($movies as $movie)
      {
         $timeLabel = $this->createTimeLabel($movie);
         $description = &$movie->tittle;
         $views = &$movie->views;
         $stars = &$movie->stars;
         $id = &$movie->id;

         if($stars != null)
        {
          $stars = 'data-stars="'.$stars.'"';   
        }
        else
        {
          $stars = "";  
        }

         echo '<div class="movie-complete">
               <div class="image-and-duration"><img class="movie-small-image" src="/images/movie/main/'.$id.'.jpg" /><time class="duration">'.$timeLabel.'</time></div>
               <div class="movie-description">'.$description.'</div>
                  <div class="additional-options">
                     <span class="views">'.$views.' odsłon</span>
                     <img alt="podgląd filmu" title="kiliknij aby podejrzeć film" class="magnifier-icon" '.$stars.' data-id="'.$id.'" src="/images/controls/magnifier.png"/>
                  </div>
          </div>';           
      }
    }

    function CreateControls()
    {
      $pagesNumber = &$this->data->pageControls->maxPageNumber;

        if($pagesNumber == 1)
        {
          return;   
        }
        else
        {
            $activePage = &$this->model->pageNumber;
            $categoryURL = &$this->model->categoryName;

            echo '<ul id="bottom-controls" data-active-page="'.$activePage.'" data-last-page="'.$pagesNumber.'" class="page-toggle-controls">';

                if($pagesNumber > 5)
                {

                        echo ' <li class="controls-element">
                                <button id="previous-page" class="page-selection page-selection-first-layer"><<</button>
                            </li>';

                        $leftNumber = $this->data->pageControls->pageControlNumberLeft;

                         for($i = 0; $i < 5; ++$i)
                        {

                            $activeCSSClass = ($leftNumber == $activePage) ? 'active' : '';

                            echo '<li class="controls-element">
                                  <a href="/kategorie/'.$categoryURL.'/strona/'.$leftNumber.'/" id="PageControl-'.$i.'" class="page-selection page-selection-first-layer '.$activeCSSClass.'">'.$leftNumber.'</a>
                                 </li>';

                           ++$leftNumber;
                        }

                        echo '<li class="controls-element">
                              <button id="next-page" class="page-selection page-selection-first-layer">>></button>
                             </li>';


                      $leftAnchor = ( $activePage > 1) ? 'href="/kategorie/'.$categoryURL.'/strona/'.($activePage - 1).'/"' : "";
                      $rightAnchor = ($activePage == $pagesNumber) ? "" : 'href="/kategorie/'.$categoryURL.'/strona/'.($activePage + 1).'/"';

                   echo '<li class="controls-element controls-element-bottom">
                      <a '.$leftAnchor.'  class="page-selection page-selection-second-layer">wstecz</a>
                    </li>';

                  echo '<li class="controls-element controls-element-bottom">
                     <a '.$rightAnchor.' class="page-selection page-selection-second-layer">dalej</a>
                  </li>';    


                }
                else
                {

                    for($i = 0; $i < $pagesNumber ; ++$i)
                    {
                       $caption = $i + 1;
                       $activeCSSClass = ($caption == $activePage) ? 'active' : '';
                       echo '<li class="controls-element">
                                  <a href="/kategorie/'.$categoryURL.'/strona/'.$caption.'/" id="PageControl-'.$i.'" class="page-selection page-selection-first-layer '.$activeCSSClass.'">'.$caption.'</a>
                                 </li>';
                    }
                }

            echo '</ul>';
        }
    }

  function __construct($model)
  {
   $this->model = $model;
  }  
}

Please criticise my code :)

\$\endgroup\$
  • \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How to get the best value out of Code Review - Asking Questions for guidance on writing good question titles. \$\endgroup\$ – BCdotWEB Mar 23 '18 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.