Using PHP and MySQL: Novice to Ninja for a new site

Hi.

This is really a question only for those who have read Tom and Kevin’s book. I honestly wouldn’t bother unless you are fairly up to speed with this actual book :).

I have and I think I “get it” in terms of the IJDB Website. I am now looking closely at exactly how to use the framework for a new site.

My specific question is this: what “logic”, “rationale”, “thought process” should be applied when we ask ourselves the question “How should we divide up the functionality of our new site into controllers?

I have identified (and please correct me if I’m wrong) that there are four elements that are project-specific: controllers, the routes, the database connection and all templates.

Templates are basically HTML layout; the database connection is just a case of credentials, the routes are essentially every possible page in the site but here we are getting into controllers as the route is a controller->method combo.

So, if I’m right, the real issue when taking the framework forward to a new site is “What controllers are required?” and the answer will help with our routes as well as, obviously, the controllers.

So. How to approach the division of the new site into controllers? I’m thinking… divide it up into “entities” (I will already have done this to an extent when I divided up the site’s data into tables in the database.) But is there more to it than this? I think so as the JokeController doesn’t just work with the jokes table: there are requirements on the authors table, so it’s not that black and white.

To help you think, let’s put together a hypothetical website from a high level perspective. Suppose my next site is for a business.

  • There will be “loose” pages such as contact form and T’s&C’s and location on a map. The kind of links you may find in a footer that lead to single pages.

  • There will be “grouped” pages such as “Services” (say, 10 different services with a page each) and “Courses” (say, 10 different courses with a page each). These will form the main navigation: “Services”, “Courses”, etc. which may lead to a landing page of 10 links to individual pages or which may have the 10 individual links in a nav drop down sort of thing.

  • There may be a “nested nav” situation. Let’s say “Vacancies” as a main link which leads to “Areas of Work” such as “Production”, “Analysis”, “Admin”. And each of these three has 5 jobs.

This, to me, is the “kind” of website I design, my bread and butter. So how to think about Controllers in this scenario: single unrelated pages, one-level groups, and two-level groups.

Hope that makes sense. I’m not asking for anyone to design a site for me :), just some pointers to the “logic”… how to “approach” it?

Cheers, guys.
Mike

Hey @mike324

I’ll be honest, i haven’t yet read this book but its definitely on my to do’s.

I’ve been spending a lot of time in Laravel recently which is very much MVC and i can only offer my experience & thoughts.

Personally from a design standpoint i try to keep things clean, scalable & relative as possible. I try to go on a 1:1 basis i.e one controller for one page.

For the static pages i.e. pages requiring no content from the database, i used a function in the routes page to return the view page based on what was requested as there was no need for a controller.

For other pages such as the recently added customers page, this required data from the database and therefore required a CustomerController. Inside there i wrote all of my logic and passed it to the view accordingly.

I would try to keep my logic & views separate by having folders retrospectively i.e

--/Controllers
     /Admin
        /AdminDashboardController
        /NewCustomersController
     /Customer
        /CustomerDashboardController
     /Frontend
        /CustomerSignUpController

--/Views
     /Admin
        /admin-dashboard.php
        /new-customers.php
     /Customer
        /customer-dashboard.php
     /Frontend
        /sign-up.php
        /contact.php

In your case, i would recommend a 1:1 basis wherever possible.

Hope this helps. Let me know if you have any questions.

Hi, oli_d111,

Thank you very much for that.

OK, a 1:1 approach certainly makes the logic easy and this would work for much of my sites (although I have little voices in my head… they’re Tom and Kevin’s… they’re saying: “after all we’ve said about reducing code and then reducing it again, you’re going one controller for one page? Really, Mike?”) but maybe I’m just over-thinking it. It’s tempting: simple logic… can’t go wrong.

Tell me, if you take this 1:1 approach, would you end up with this…
If I had a table: “services”… let’s say there are 100. I don’t want 100 controllers. So I would have ONE controller (ServiceController, say) which would have an action (“display”, say) which used “findById()” logic to return something like this:

    'template' => 'displayservice.html.php',
    'variables' => [
        'serviceText' => $service->description,
        'title' => $service->page_title,

where description and page_title are column data for a specific service, which I could access with a url something like:
www.domain.com/service/display?id=45

I’d rather use urls like:
www.domain.com/service/title-of-service-with-id-of-45

and this is easily achieveable with one controler per page but then… hundreds?.. no.

How would you handle/achieve this?

Hey @mike324

No worries.

Yeah i get what you mean, i’ve been in the same position spending ages over thinking it trying to map out in my head what i want to do lol.

You’re absolutely right, you wouldn’t want 100 controllers for 100 pages. Are your “service” pages going to display dynamic or static content?

If the pages are static, then a controller probably isn’t needed and you could just use a function in your routes file. Something like:-

Route::get('home', function () 
{
    return view('frontend.home');
});

Out of curiosity what framework are you using?

Also is there a particular reason your “displayservice” view page is ends with .html.php?

Hey, oli_d111.

Glad I’m not the only one. I do wonder sometimes if I could have used the time I’ve spent working out how to integrate project content with framework content in just developing the website without a framework. I’m hoping that I’ll just “get it” one day as currently using a time-saving framework is taking me twice as long :slight_smile:

Right, in answer to your questions:

  1. My services would contain content held in a database (thus allowing for a cms at a later stage possibly) but it is, usually, just text and HTML to format a heading or two and a few paragraphs, maybe a link or two. I think I do need a controller for the whole section as it makes that cms possible with actions such as adding new services, editing services, deleting services, etc.
  2. The framework I’m using is a custom one developed by Tom and Kevin through the book. That’s the point of the book: to teach programming skills (via PHP) by developing a re-usable framework. I am aware that there are others, like Laravel and Symphony but my goal is to learn to program rather than just use a framework so I’d like to stick woth Tom and Kevin’s as it’s a body of code that I understand inside out - “ish”.
  3. My displayservice.html.php page ends like this because that is the convention used by Tom and Kevinthroughout the book. They use this for all template/view pages to show that they are essentially HTML while still needing to be parsed by the PHP pre-processor as thet frequently contain PHP (usually foreach loops and always the use of $output which is the content for specific page requested.

The book is PHP and Mysql: From Novice to Ninja (6th Edition) by SitePoint. What it teaches is excellent. I doubt if it’s ever been proof read as it’s riddled with errors (that seem like copy and paste between edition errors where part but not all of the text/code for a problem has been updated) but, ironically, this makes you learn better as you have to “really” follow Tom and Kevin’s logic to know when the text is just wrong. My copy is full of red ink!

If you want to take a look at the code for the website, check out this link: https://github.com/spbooks/phpmysql6/tree/CMS-EntryPoint-Interface. This branch is not the “finished” framework but I have chosen to stop here temporarily and give integrating it into a real-world project a go as, at this point, it is a fully working framework minus some bells and whistles I don’t need right now such as authentication.

Although you haven’t read the book, I’m grateful for you help and I’m getting where you’re coming from as our frameworks seem to be working in similar ways.

Have another look at the problem I’m having:


Tell me, if you take this 1:1 approach, would you end up with this…
If I had a table: “services”… let’s say there are 100. I don’t want 100 controllers. So I would have ONE controller (ServiceController, say) which would have an action (“display”, say) which used “findById()” logic to return something like this:

    'template' => 'displayservice.html.php',
    'variables' => [
        'serviceText' => $service->description,
        'title' => $service->page_title,

where description and page_title are column data for a specific service, which I could access with a url something like:
www.domain.com/service/display?id=45

I’d rather use urls like:
www.domain.com/service/title-of-service-with-id-of-45

and this is easily achievable with one controller per page but then… hundreds?.. no.

How would you handle/achieve this?


The lovely url’s in the book such as www.domain.com/joke/list (where joke is a controller containing a list method - a single page listing all the jokes in the jokes table in the db) don’t seem achievable for me as my database is more complex: I can’t list 100 services on one page so I inevitable (or, hopefully NOT inevitably) end up with ugly urls (as above).

Is this just a matter for url_rewriting in Apache or (and this is my main question, I guess) am I looking at controllers from the wrong point of view? Do I need to set up my controllers differently?

Cheers,
Mike

Hey @mike324

Haha i know what you mean lol. I’m actually thinking about making a SAAS project aswell and trying to think on that scale definitely requires some planning in advance.

Cool thanks for confirming on the questions.

So as for the 1:1 approach and pages + controllers, in my head, if the content is dynamic, then you would only need one controller for the services pages and you would be returning the data based on the id selected. Same as if you had a row of records (eg invoices) and you wanted to view the invoice for that record ID. The invoice view would be populated with data based on that ID with various relationships to orders, users etc.

So for instance let’s say the user selected Services Near Me in the nav bar, to keep the URL’s pretty, i would recommend omitting the ID from the URL. You could have a column in your database called slug. In this example the slug would be services-near-me.

When the user clicks on the link

<a href="services-near-me">Services Near Me</a>

the slug is sent via the route as a wildcard to the ServicesController.

Something like

Route::get('services/{slug}', 'Services\ServiceControllerController@show');

The ServicesController then receives the request, queries the database using the slug and returns data based on the slug.
Once the query has executed then return the services-near-me view page based on the request and pass the query to the view to be used to populate the page.

//pseudo code example
public function show(Slug $slug)
{
    
    $service = Service::where('slug', $slug)->with('content')->get();

    return view('services/'.$slug, compact('service'));

}

The services-near-me page is then populated with the relevant information in your database.

In your database, i’m guessing you’ll have one table for pages,
and another table for content with a foreign key that links the two together etc etc.

Let me know if you have any questions.

1 Like

This really has nothing to do with the controller, and everything to do with the routes. To achieve this, you’ll have to add some additional processing at the routing stage.

You can either do it with pattern matching as oli_d111 suggests or you can use a standardised structure.

Both require a fair amount of additional logic, however, for the standardised structure you can do this:

Use a common character as your separator e.g. /

Someone visits

/service/display/45/

Split the route on / so you get the array $parts = > ['service', 'display', '45']

Use the controller called $parts[0] call the function called $parts[1] and then pass in any remaining variables as arguments to the function when it’s called.

1 Like