1

First problem:
Main url: site-test
1. I clicked on the link <a href="tasks/">tasks</a> -> url: site-test/tasks
2. i click next link <a href="tasks/page/2">next page</a> (Where "tasks" - contoller, "page" - action, "2" - action value) -> url: site-test/tasks/page/2
3. i pressed again <a href="tasks/">tasks</a> and url -> site-test/tasks/page/tasks instead site-test/tasks/ what i need.

<a href="tasks/">tasks</a> is located in template view.

Second problem:
When url is: site-test or site-test/tasks all files loading from root_directory/images or root_directory/css, when url is: site-test/tasks/page/2 he tries to find these files in root_directory/tasks/page/images

My route:

static function start()
    {
        $controller_name = 'add_task';
        $action_name = 'index';

        $routes = explode('/', $_SERVER['REQUEST_URI']);

        if ( !empty($routes[1]) )
        {   
            $controller_name = $routes[1];
        }

        if ( !empty($routes[2]) )
        {
            $action_name = $routes[2];
        }

        $model_name = 'Model_'.$controller_name;
        $controller_name = 'Controller_'.$controller_name;
        $action_name = 'action_'.$action_name;

        $model_file = strtolower($model_name).'.php';
        $model_path = "application/models/".$model_file;
        if(file_exists($model_path))
        {
            include "application/models/".$model_file;
        }

        $controller_file = strtolower($controller_name).'.php';
        $controller_path = "application/controllers/".$controller_file;
        if(file_exists($controller_path))
        {
            include "application/controllers/".$controller_file;
        }

        $controller = new $controller_name;
        $action = $action_name;

        if(method_exists($controller, $action))
        {
            if ( !empty($routes[3]) )
            {
                $controller->$action($routes[3]);
            }
            else{
                $controller->$action();
            }   
        }

    }

My controller:

class Controller_tasks extends Controller
{
    function __construct()
    {
        $this->model = new Model_tasks();
        $this->view = new View();
    }

    function action_index()
    {    
        $data = $this->model->get_data_from_server();
        $this->view->generate('tasks_view.php', 'template_view.php', $data);
    }

    function action_page($page = 1)
    {
        var_dump($page);
        $data = $this->model->get_data_from_server($page);

        $this->view->generate('tasks_view.php', 'template_view.php', $data);       
    }
}

Thx for any help, coz im rly confused.

rantihawk
  • 59
  • 1
  • 7

3 Answers3

1

use base_url() in the link.

<a href="<?php echo base_url() ?>tasks/">tasks</a> 
<a href="<?php echo base_url() ?>tasks/page/2">next page</a>

before that set base url to the root of your framework folder in the config page

eg: if u r using codeigniter. config.php file is located at codeigniter/aplication/config.php

set this in that page $config['base_url'] = 'http://localhost/codeigniter';// change the path according to yours.

Ithink this will solve your first problem. may be it could be the solution for the second problem also.(using base_url in all links)

Anandhu Nadesh
  • 672
  • 2
  • 11
  • 20
1

First question:

The first problem happens because you are loading and rendering the view files IN the action context/scope of the controller. That's why your url in the point 3. is "incorrect", e.g. site-test/tasks/page/tasks, e.g '///`. So, other said, because you are actually seeing the rendered html content from inside the controller folder, where it was the view file rendered.

In order to resolve this you have to options:

Option 1) Use absolute paths in all the anchors in your view/template files, like for example:

<a href="http://site-test/tasks/">tasks</a>
<a href="http://site-test/tasks/page/2">next page</a>

Here you can of course use a variable in your view/template files instead, like:

<a href="<?php echo $host; ?>/tasks/">tasks</a>
<a href="<?php echo $host; ?>/tasks/page/2">next page</a>

I showed you just pure php code, but you can use syntaxes provided by a diversity of template engines, if you decide to use one, one then PHP engine.

Option 2) Use relative paths in all the anchors in your view/template files, like for example:

<a href="/tasks/">tasks</a>
<a href="/tasks/page/2">next page</a>

The key is of course the slash (/) at the beginning of each anchor's href attribute. It ensures that all the links are "joined" to the host http://site-test of your MVC website.

Personally I use the second option in my own MVC framework and it works smooth and is... pretty.

Second question:

When url is: site-test or site-test/tasks all files loading from root_directory/images or root_directory/css, when url is: site-test/tasks/page/2 he tries to find these files in root_directory/tasks/page/images

Well, here is the need of a discussion:

When url is site-test, then the default action of the default controller is called, e.g. Controller_add_task::action_index(). You didn't show the code for that controller, so I can't say nothing about from where and how are the asset files (css, images, js) loaded in the views.

Same goes for the url site-test/tasks/page/...: you showed the code for the controller, but I can't say nothing about how and where are the asset files (css, images, js) loaded in the views. Are the asset paths loaded from inside the Controller (parent class) methods? Are they written - as normal - in the view/template files (using <script src=...>, <link href=...>, <img src=...>)? Are they loaded from inside the View::generate?

In principle, they can be passed to the view/template files as variables, or they can be written - as normal - in the view/template files.

The context/scope theory of the first question applies here too. And the key here is the same as in the first question: the asset paths should be passed/written as absolute paths or relative paths as shown above in the options 1) and 2).

Recommendations:

Note: Seeing that you want to learn clean MVC, I thought you would allow me to give you some tips:

*) Don't use any static classes/functions, singletons or so called service locators. Trust me, you don't need them at all if you are writing a clean, good testable MVC.

*) Use a dependency injection container like Auryn, which you will implement only on the entry point of your app, e.g. bootstrap.php or index.php. The next point tells you why.

*) Inject your dependencies, don't create them in the places where they are needed. So not like this:

function __construct()
    {
        $this->model = new Model_tasks();
        $this->view = new View();
    }

but like this:

function __construct(Model_tasks $model, View $view)
    {
        $this->model = $model;
        $this->view = $view;
    }

Read:

*) Use namespaces! Read PSR-4: Autoloader (yes, it's correct).

*) Read all the first 8 recommendations in PHP Standards Recommendations. They are very important if you want to correctly learn how to develop a PHP MVC.

*) Learn the five SOLID principles in OOP (just search for "solid principles" in web).

*) Use a corresponding view class for each controller class (1:1). For example: if you have TasksController, then also create a class TasksView. And what you are using there as view files - tasks_view.php, template_view.php, etc - are actually template files. And you should implement a Template class, which is to be injected in the corresponding view class. The template class is actually responsible for rendering/loading the template files. The view class should be responsible to output the rendered content (or to pass it to a Response class to be outputed).

Read: Understanding MVC Views in PHP

*) Don't use names like Controller_tasks for the class names. Use the syntax like this - I forgot the name: TasksController, TasksModel, TasksView.

*) Don't use names like action_index for the class methods or members. Use the camelCase syntax. And don't use action in the controller methods, because you already know that. So write the methods just like this: index(), page(), listBooks. If you use ajax you can name them like ajaxGetUsers(), etc. Just make sure that your routing system make the correct syntax-mapping between the controller/action names in url and the actual controller/action names.

Resources:

Good luck.

  • thx for ur answer and time. U solved my problems. In the second question, I changed the path to css and images on absolute and its works good now too. – rantihawk Jul 04 '17 at 04:19
  • 1
    I'm glad it worked. But wait, now come the... cookies. Give me 5 mins. –  Jul 04 '17 at 04:29
  • 1
    @rantihawk I reedited my answer with some recommendations about a clean MVC. –  Jul 04 '17 at 04:40
0

What framework are you using? Based on what I see you are not using one, it's better and recommended to use a framework, especially if you are using MVC design

vladjamir
  • 124
  • 1
  • 1
  • 14