Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Ronaldo100's avatar

When to normalize DB's - and when not?

hi again!

I am just watching a Laravel Tutorial on Youtube where the teacher shows how to work with tags.

In simple terms, he has all the tags saved as a comma-separated list which he passes from the main blade template into a blade "tags" component.

main.blade.php

// $tags contains: "tag1,tag2,tag3,tag4,tag5"

<x-tags :tags="$tags" />

components/tags.blade.php

@props(['tags'])

@php
$new_tags = explode(',', $tags);
@endphp


@foreach($new_tags as $tag)
<a href="/?t={{ $tag }}">{{ $tag }}</a><br>
@endforeach

My questions:

A)

Is it really okay, that the teacher on YouTube uses @php ... @endphp inside a blade template?

A different YouTube teacher once said, that when you have to use @php inside a blade template, you're doing something wrong to begin with, as variables should only come from the controller.

However, I would also not know a better way.

B)

Is it really a good idea, to save tags as a comma-separated-list?

Maybe I am wrong, but I would have probably used 3 tables.

  1. an "entries" table holding all entries (e.g. title, text, creation_date, etc...)

  2. a tags-table holding all available tags (id | name)

  3. an "entries_tags" table which only connects the entries to existing tags.... basically: | entry_id | tag_id ]

Am I wrong?

Is it better what the teacher does?

Sorry, my background is "wild code / spaghetti code" and I am just getting used to Laravel and "best practices" so maybe I am mistaken here.

I believe the term is "normalizing" a table (database?) - but maybe the teacher does it better.

Regards, Ronaldo

0 likes
5 replies
tykus's avatar

A it really is a matter of opinion - different developers will abhor this, and others not so much. I would definitely consider a Component class to organise the data for the view if the operation was non-trivial. In the example you shared, it can be argued that the Component class would be overkill. I'd live with @php, but I wouldn't like myself for it 😂

B I would always normalise in this situation, if the entries table has tags, then someone will eventually want to filter by tag(s)... then you'll need to normalise.

1 like
Ronaldo100's avatar

Dear @tykus,

thank you very much for your answer!

I would always normalise in this situation, if the entries table has tags, then someone will eventually want to filter by tag(s)... then you'll need to normalise.

I kept watching the tutorial and the solution the teacher proposed goes like this:

CONTROLLER

public function index()
{
	return view('listings.index', [
	'listings' => Listing::latest()->filter(request(['tag', 'search']))->paginate(6)
	]);
}

MODEL

if($filters['tag'] ?? false) // WHY do we need null-coalescing operator here??
{
$query->where('tags', 'like', '%' . request('tag') . '%');
}

Is this an acceptable solution?

I feel so lost with Laravel right now.

In the past, I have always done everything by hand (raw mysql queries, vanilla PHP), but now, in Laravel, I am struggling to decide what is good or bad.

PS.: May I kindly ask you for a link to a simple yet well-written tutorial on normalizing in Laravel? I have only done it by hand so far.

tykus's avatar

@Ronaldo100 that solution (what I can see of it) is (i) limited to searching only one tag (you couldn't search PHP and Laravel tags together for example); (ii) will not be very efficient - given the LIKE constraint it is unlikely to be able to use any index for its search (iii) prone to duplicate tags due to mis-spelling and typos (iv) uses more disk space to store same strings over and over.

// WHY do we need null-coalescing operator here??

The null coalescing operator ensures there is not error if the $filters array has no tag key

1 like
Ronaldo100's avatar

Thank you @tykus for your answer!

I still feel somehow lost.

It took me, like, 5 minutes to whip up a working mysql test case for what I want to do.

In Laravel, I would not even have the slightest idea of how to achieve this...


CREATE TABLE `entries` (
`id` INT(255) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`description` TEXT NOT NULL,
UNIQUE KEY(`id`)
);


CREATE TABLE `tags` (
`id` INT(255) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
UNIQUE KEY(`id`)
);


CREATE TABLE `entries_tags` (
`id` INT(255) NOT NULL AUTO_INCREMENT,
`entry_id` INT(255) NOT NULL,
`tag_id` INT(255) NOT NULL,
UNIQUE KEY(`id`)
);


INSERT INTO `entries` VALUES (1, 'First', 'Lorem Ipsum');
INSERT INTO `entries` VALUES (2, 'Second', 'Dolor sit');
INSERT INTO `entries` VALUES (3, 'Third', 'Amet');

INSERT INTO `tags` VALUES (1, 'nice');
INSERT INTO `tags` VALUES (2, 'cute');
INSERT INTO `tags` VALUES (3, 'sweet');

INSERT INTO `entries_tags` VALUES (1, 1, 3);
INSERT INTO `entries_tags` VALUES (2, 1, 2);
INSERT INTO `entries_tags` VALUES (3, 2, 1);
INSERT INTO `entries_tags` VALUES (4, 3, 1);
INSERT INTO `entries_tags` VALUES (5, 3, 3);



SELECT `entries`.`id`, `entries`.`title`, `entries`.`description` FROM `entries` INNER JOIN `entries_tags` ON `entries`.`id` = `entries_tags`.`entry_id` WHERE `entries_tags`.`tag_id` = 3;

Edit:

Maybe somebody can point me to a good resource online?

Googling "normalization" and "mysql" and "laravel" did not lead me to good tutorials.

Tray2's avatar

@Ronaldo100 If you are looking for posts on database design, I can point you to a couple of mine regarding that subject, without any shame what so ever.

https://tray2.se/posts/database-design https://tray2.se/posts/database-design-part-2

Using a comma separated list inside a field in the database is in my opinion a very sloppy solution and as mentioned by @tykus it makes it much more convoluted to search for things that has more than one tag, and using LIKE in your queries isn't good for performance in the long run.

There are some that store the tags as a json string as well and that is something I really hate when they do. it is not quite as bad as the comma seperated list but close second.

I would always go with a many-to-many relationship using a pivot table.

There are so many people making tutorials about Laravel and some of them are pretty new to Laravel, or they have their own opinion on how to do a certain thing.

Please or to participate in this conversation.