Xdebug has detected a possible infinite loops, and aborted your script with a stack depth of 256 frames
- Cupara
- Member | 90
I'm not really understanding what the issue is. If I look at the
Presenters-templates-@layout.latte--6858b406f6.php
in the
temp/cache/latte/
directory then at line 133 this is there
$this->renderBlock('title', get_defined_vars(), function ($s, $type)
but I am not understanding how it can get an infinite loop from title.
In my presenter I figured it might be, the query looks fine.
HomePresenter.php
public function renderDefault(): void
{
$this->template->news = $this->facade
->getPublicArticles()
->limit(5);
}
That is the only thing being called on my index page that could even remotely have anything to do with an infinite loop not something to do with title.
If anyone can advise me on this I would greatly appreciate it. If you need more information or specific outputs, please let me know.
- Infanticide0
- Member | 103
@Cupara
Try clean cache (remove temp/cache folder).
If that doesn't help, show your template file (templates/Home/default.latte)
- Cupara
- Member | 90
@Infanticide0 that didn't do any good so here is my default.latte template.
{block content}
<h1>Serenity Development</h1>
<div><a n:href="Edit:create" n:if="$user->isLoggedIn()">Create Article</a></div>
<div>Motto: Empowering Creators, Enriching Communities</div>
<div>Summary: We are a pioneering hub where visionary content creators and tech innovators unite to collaborate and build the future of online entertainment as well as digital engagement.
Ditch the dusty dev studios, ditch the clunky tools. Serenity Development isn't just building tech, we're recharging the content creator universe. Think high-octane collaborations with fellow visionaries, where killer tools fuel epic online communities.
Tired of wonky giveaways? We built a platform so smooth, it'll make your viewers squeal with excitement. Need a bot that dances between Discord and Guilded like a party panda? Got you covered. We even crafted a Twitch and SharePlay chat bot so smart, it practically reads minds (and announces winners on point, obviously).
But it's not just about gadgets. We're obsessed with user experience so seamless, it'll feel like magic. Think chat moderation that melts away negativity, leaving pure community gold. Think a future where engagement isn't a chore, it's a thriving, vibrant explosion.
Stop creating in the shadows. Join the revolution. Reimagine content. Unleash Serenity.</div>
{foreach $news as $new}
<div class="post">
<div class="author">{$new->author}</div>
<div class="date">Posted: {$new->created_at|date:'F j, Y'}</div>
<h2><a href="{link News:show $new->id}">{$new->title}</a></h2>
<div>{$new->content|truncate:256}</div>
</div>
{/foreach}
{/block}
- Marek Bartoš
- Nette Blogger | 1261
Your code looks fine.
Does it happen without xdebug enabled?
If you have Tracy enabled, it should be able to show you if there is an actual
problem.
Also I noticed in your previous post that you setup Latte\Engine manually.
Is it still a case? You shouldn't need that with full Nette setup.
Make sure that you set up Latte temp directory as an absolute path. Generally,
any path in PHP should be absolute, if you don't have some abstraction that
works with relative paths. You will avoid a lot of potential
issues. $latte->setTempDirectory(__DIR__ . '/temp');
Last edited by Marek Bartoš (2023-12-24 15:22)
- Cupara
- Member | 90
@MarekBartoš Yes this happens with Xdebug disabled. I'm not sure how to check if I have Tracy enabled or not.
No I did not setup Latte\Engine manually this time around, I used the web-project.
I have the Latte temp directory as an absolute path. Here is my Bootstrap.php file:
<?php
declare(strict_types=1);
namespace App;
use Nette\Bootstrap\Configurator;
class Bootstrap
{
public static function boot(): Configurator
{
$configurator = new Configurator;
$appDir = dirname(__DIR__);
//$configurator->setDebugMode('cupara790482@72.206.26.238'); // enable for your remote IP
$configurator->enableTracy($appDir . '/log');
$configurator->setTempDirectory($appDir . '/temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig($appDir . '/config/common.neon');
$configurator->addConfig($appDir . '/config/services.neon');
$configurator->addConfig($appDir . '/config/local.neon');
return $configurator;
}
}
- Infanticide0
- Member | 103
You are including block title in block title.
Try this in layout
<title>{ifset title}{include title|stripHtml} | {/ifset}default title</title>
You define new {block title}news page{/block} or <h1 n:block=title>news page</h1>
Last edited by Infanticide0 (2023-12-25 01:56)
- Infanticide0
- Member | 103
@Cupara
How does look generated url?
That href should look for domain.com/css/style.css → www/css/style.css
Folder www is at the same level as your app, temp, log folders.
Make sure you have debug mode enabled, if it is disabled (you are in production mode), layouts are cached you won't see changes until you clean cache manually.
You can see Tracy debug bar when debug mode is enabled.
Last edited by Infanticide0 (2023-12-25 02:06)
- Infanticide0
- Member | 103
Is your css file in /www/css/style.css and is name of that file style.css and not styles.css?
White page? 404 errors are in Nette style by default, not a blank page, is your style empty?
- Infanticide0
- Member | 103
https://doc.nette.org/…on/bootstrap#…
You can force debug mode with $configurator->setDebugMode(true); in
app/bootstrap.php file
It is not safe (for production) and you should use it only for this testing.
When you are on localhost, Nette should enable it automatically.
Last edited by Infanticide0 (2023-12-25 02:20)
- Cupara
- Member | 90
Yeah, I'm using localhost for building right now, when I move it to my server then I'll turn it back off.
Nette didn't enable it automatically because I use domains through my
virtualhost files via WAMP to run it like sdmain.local
or
test.local
so I can enable SSL and test out things that deal
with SSL.
I got the bar showing now though, thanks for all your help @Infanticide0
- Cupara
- Member | 90
@Infanticide0 next issue is if my page is active it's not including
the active
class.
Here is the line:
<li class="nav-item"><i class="fa-solid fa-house"></i><a n:href="Home:" class="nav-link {if $presenter->isLinkCurrent('Homepage')}active{/if}"{if $presenter->isLinkCurrent('Homepage')} aria-current="page"{/if}>Home</a></li>
Do you see anything wrong with my if condition?
Last edited by Cupara (2023-12-25 02:48)
- Infanticide0
- Member | 103
@Cupara
you are creating href link to “Home:” (HomePresenter) and checking current link of Homepage (HomepagePresenter)
does isLinkCurrent(‘Home:’) work?
- Infanticide0
- Member | 103
https://doc.nette.org/…ms/rendering#…
To style Forms you can create your own Form renderer or just use package with Bootstrap v4/5 renderer already defined.
https://componette.org/…s-bootstrap/
https://contributte.org/…otstrap.html#…
- Cupara
- Member | 90
Infanticide0 wrote:
@Cupara
you are creating href link to “Home:” (HomePresenter) and checking current link of Homepage (HomepagePresenter)
does isLinkCurrent(‘Home:’) work?
Ok, I understand that. Yes the isLinkCurrent(‘Home:’) is working after I changed it from ‘Homepage’ to ‘Home:’.
- Cupara
- Member | 90
Infanticide0 wrote:
https://doc.nette.org/…ms/rendering#…
To style Forms you can create your own Form renderer or just use package with Bootstrap v4/5 renderer already defined.
https://componette.org/…s-bootstrap/
https://contributte.org/…otstrap.html#…
I'm using the package with Bootstrap 4/5 already defined but it's not styling the sign-in form.
- Infanticide0
- Member | 103
To keep your layouts nice and clean, try using n: attributes
your <li> can look like this:
<li class="nav-item">
<i class="fa-solid fa-house"></i>
<a n:href="Home:" n:class="nav-link, isLinkCurrent('Home:') ? active" n:attr="aria-current => isLinkCurrent('Home:') ? page">Home</a>
</li>
- Infanticide0
- Member | 103
Cupara wrote:
Infanticide0 wrote:
https://doc.nette.org/…ms/rendering#…
To style Forms you can create your own Form renderer or just use package with Bootstrap v4/5 renderer already defined.
https://componette.org/…s-bootstrap/
https://contributte.org/…otstrap.html#…I'm using the package with Bootstrap 4/5 already defined but it's not styling the sign-in form.
you have to create instance of BootstrapForm class instead of Nette\Application\UI\Form
- Cupara
- Member | 90
Infanticide0 wrote:
Cupara wrote:
Infanticide0 wrote:
https://doc.nette.org/…ms/rendering#…
To style Forms you can create your own Form renderer or just use package with Bootstrap v4/5 renderer already defined.
https://componette.org/…s-bootstrap/
https://contributte.org/…otstrap.html#…I'm using the package with Bootstrap 4/5 already defined but it's not styling the sign-in form.
you have to create instance of BootstrapForm class instead of Nette\Application\UI\Form
Gotcha, I'll give that a try here shortly and report back if I need assistance.
- Cupara
- Member | 90
Infanticide0 wrote:
To keep your layouts nice and clean, try using n: attributes
your <li> can look like this:
<li class="nav-item"> <i class="fa-solid fa-house"></i> <a n:href="Home:" n:class="nav-link, isLinkCurrent('Home:') ? active" n:attr="aria-current => isLinkCurrent('Home:') ? page">Home</a> </li>
Thanks, I updated my code to make it look better.
- Cupara
- Member | 90
@Infanticide0 So I have another question, I have my news articles stored in one table in my database and my comments in a different table in the database, is there any way to count the comments for each article without doing a secondary call to the database to just grab the comment count?
Here is the snippet from my default.latte template:
{foreach $news as $new}
<div class="card">
<div class="card-header">Author: {$new->author}</div>
<h2 class="card-title"><a href="{link Post:show $new->id}">{$new->title}</a></h2>
<div class="card-text">{$new->content|truncate:200}</div>
<div style="text-align: right;">
<a href="{link Post:show $new->id}">Read More...</a>
</div>
<div class="card-footer">
<p style="align: left;" class="date">
Posted: {$new->created_at|date:'F j, Y'}
</p>
<p style="align: right;">
<a href="{link Post:show $new->id}#comments">Comments: {$new->comments->count()}</a>
</p>
</div>
</div>
<div> </div>
{/foreach}
Here is my HomePresenter.php file:
<?php
declare(strict_types=1);
namespace App\Presenters;
use App\Model\PostFacade;
use Nette;
use Nette\Application\UI\Form;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private PostFacade $facade,
) {
}
public function renderDefault(): void
{
$this->template->news = $this->facade
->getPublicArticles()
->limit(5);
}
}
And here is my PostFacade.php file:
<?php
namespace App\Model;
use Nette;
final class PostFacade
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function getPublicArticles()
{
return $this->database
->table('news')
->where('created_at < ', new \DateTime)
->order('created_at DESC');
}
}
Last edited by Cupara (2023-12-25 05:47)
- Infanticide0
- Member | 103
@Cupara
It's not possible (in easy way) in plain SQL query so Nette Database can't do it either. You can cache comment count and set expire time or invalidate by tag when any user creates new comment, or admin deletes/edits existing one.
https://doc.nette.org/en/caching#…
Last edited by Infanticide0 (2023-12-25 16:46)
- Infanticide0
- Member | 103
@Cupara
If you need more complex queries, use $explorer->query(“sql query with
variable placeholders ?”, $value1, $value2 …)
Explorer optimize sql queries to keep your app fast even when you are selecting
complex relations (I am talking about N+1 queries)
- Cupara
- Member | 90
One last thing, how do you form an n:tag-if
that needs to
parameters to work? Such as one parameter I have is if they supplied their
email and the second parameter is if they check the box to show
their email.
<p>
<b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
{$comment->name}
</a></b> said:
</p>
That is the snippet where I need to use two if conditions. So it would have to be provided email AND want to show their email.
Last edited by Cupara (2023-12-26 09:31)
- nightfish
- Member | 517
@Cupara
ad date/time format: date
filter (|date
) takes as
its argument a PHP date formatting string. See documentation for various date and time parts you
can use.
ad n:tag-if: the expression inside n:tag-if
is a standard PHP
expression, so you can use &&
(logical AND) to merge
multiple conditions. Could be something like
n:tag-if="$comment->email && $new->author->emailVisible"
(you'll need to change the second part of the condition to match what you have
in database).
- nightfish
- Member | 517
@Cupara
ad “comment count”: There are several options how to implement counting
comments for articles.
If you want to use Database Explorer (which allows you to easily traverse from one table to another), following options come to mind:
- You can add
comment_count
to your news table and populate it with after insert/after delete trigger on comments table. After a comment is added/removed, thecomment_count
in your news table will get updated. (https://www.mysqltutorial.org/mysql-triggers/) - You can do something similar, but the calculation and updating of the
comment_count
will be done from PHP. After you save a new comment to the database, you will execute a query to return a count of all comments for the current article and save it tocomment_count
. - You can create a VIEW on your
news
table that will contain both columns ofnews
table and an additional columncomment_count
, that will be calculated on the fly whenever you SELECT from the view. This could get slow with a large number of news and comments, but also should be easiest to implement. (https://www.mysqltutorial.org/…utorial.aspx)
You can also implement the third solution using PHP – collect IDs of news items and execute another query (using Database Core) to retrieve a number of comments for each ID (in a single query, result would be an array of ID ⇒ COUNT), then pass the result to the template and use it when rendering news items.
- Cupara
- Member | 90
nightfish wrote:
@Cupara
ad date/time format:
date
filter (|date
) takes as its argument a PHP date formatting string. See documentation for various date and time parts you can use.ad n:tag-if: the expression inside
n:tag-if
is a standard PHP expression, so you can use&&
(logical AND) to merge multiple conditions. Could be something liken:tag-if="$comment->email && $new->author->emailVisible"
(you'll need to change the second part of the condition to match what you have in database).
Thanks
- Cupara
- Member | 90
nightfish wrote:
@Cupara
ad “comment count”: There are several options how to implement counting comments for articles.If you want to use Database Explorer (which allows you to easily traverse from one table to another), following options come to mind:
- You can add
comment_count
to your news table and populate it with after insert/after delete trigger on comments table. After a comment is added/removed, thecomment_count
in your news table will get updated. (https://www.mysqltutorial.org/mysql-triggers/)- You can do something similar, but the calculation and updating of the
comment_count
will be done from PHP. After you save a new comment to the database, you will execute a query to return a count of all comments for the current article and save it tocomment_count
.- You can create a VIEW on your
news
table that will contain both columns ofnews
table and an additional columncomment_count
, that will be calculated on the fly whenever you SELECT from the view. This could get slow with a large number of news and comments, but also should be easiest to implement. (https://www.mysqltutorial.org/…utorial.aspx)You can also implement the third solution using PHP – collect IDs of news items and execute another query (using Database Core) to retrieve a number of comments for each ID (in a single query, result would be an array of ID ⇒ COUNT), then pass the result to the template and use it when rendering news items.
I went with option 2. I just need to implement the deleting process for just me being able to delete comments until I implement a user system.
- Cupara
- Member | 90
nightfish wrote:
@Cupara
ad date/time format:
date
filter (|date
) takes as its argument a PHP date formatting string. See documentation for various date and time parts you can use.ad n:tag-if: the expression inside
n:tag-if
is a standard PHP expression, so you can use&&
(logical AND) to merge multiple conditions. Could be something liken:tag-if="$comment->email && $new->author->emailVisible"
(you'll need to change the second part of the condition to match what you have in database).
In regards to the date
filter I added time
to it
like so datatime
then added HH:mm
after
F j, Y
but it just errors out so I'm not sure how it would look in
the code for Nette as datetime
is the only PHP way I know to
do it.
- Cupara
- Member | 90
@Infanticide0 I did that and it still didn't work. I'll try again. What is the letter to get AM or PM to display?
Can you show me an example using https://doc.nette.org/…ls/paginator ?
I'm trying to figure it out but I'm struggling. Since I'm using PostFacade.php above, I can't figure out how to implement it from the doc I linked.
- Cupara
- Member | 90
Infanticide0 wrote:
@Cupara
Ok so it worked this time but I don't like that it uses 24 hour format. I prefer it using 12 hour format and use AM/PM.
- Cupara
- Member | 90
@Infanticide0 instead of an example here is my code that I have so far.
PostFacade.php
<?php
namespace App\Model;
use Nette;
final class PostFacade
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function getPublicArticles(int $page, $itemsPerPage)
{
return $this->database
->table('news')
->where('created_at < ', new \DateTime)
->order('created_at DESC')
->limit($itemsPerPage, $page);
}
public function getArticlesCount(): int
{
return $this->database->fetchField('SELECT COUNT(*) FROM news WHERE created_at < ?', new \DateTime);
}
}
HomePresenter.php
<?php
declare(strict_types=1);
namespace App\Presenters;
use App\Model\PostFacade;
use Nette;
use Nette\Application\UI\Form;
use Nette\Utils\Paginator;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private PostFacade $facade,
) {
}
public function renderDefault(): void
{
$page = 1; // Initialize the variable '$page' with a default value
$itemsPerPage = 10;
$getArticlesCount = $this->facade
->getArticlesCount();
$paginator = new Paginator;
$paginator->setItemCount($getArticlesCount);
$paginator->setItemsPerPage($itemsPerPage);
$paginator->setPage($page);
$this->template->news = $this->facade
->getPublicArticles($page, $itemsPerPage);
$this->template->paginator = $paginator;
}
}
paginator code in default.latte
<div class="d-flex mb-5 pagination">
{if !$paginator->isFirst()}
<a n:href="default, 1">First</a>
|
<a n:href="default, $paginator->page-1">Previous</a>
|
{/if}
Page {$paginator->getPage()} of {$paginator->getPageCount()}
{if !$paginator->isLast()}
|
<a n:href="default, $paginator->getPage() + 1">Next</a>
|
<a n:href="default, $paginator->getPageCount()">Last</a>
{/if}
</div>
- Infanticide0
- Member | 103
@Cupara
you need to read current page number instead of setting it always to the
first page
public function renderDefault(int $page = 1): void
{
$itemsPerPage = 10;
$getArticlesCount = $this->facade->getArticlesCount();
$paginator = new Paginator;
$paginator->setItemCount($getArticlesCount);
$paginator->setItemsPerPage($itemsPerPage);
$paginator->setPage($page); // use page number from URL parameter or first page by default (you get these variables in renderDefault(parameters) automatically)
$this->template->news = $this->facade
->getPublicArticles($page, $itemsPerPage);
$this->template->paginator = $paginator;
}
public function renderDefault(int $page = 1, int $perPage = 10): void
{
$getArticlesCount = $this->facade->getArticlesCount();
$paginator = new Paginator;
$paginator->setItemCount($getArticlesCount);
$paginator->setItemsPerPage($perPage);
$paginator->setPage($page); // use page number from URL parameter or first page by default (you get these variables in renderDefault(parameters) automatically)
$this->template->news = $this->facade
->getPublicArticles($page, $itemsPerPage);
$this->template->paginator = $paginator;
}
<a n:href="default, 1">First</a> // navigate to action=default with first parameter=1
<a n:href="default, $paginator->getPage() + 1">Next</a> // navigate to action=default with first parameter=(current page - 1)
<a n:href="default, page: 1, perPage: 5">set 5 items per page</a> // calls renderDefault(1, 5) and keep new values in get parameters in url
Last edited by Infanticide0 (2023-12-27 16:49)
- Cupara
- Member | 90
Infanticide0 wrote:
@Cupara
you need to read current page number instead of setting it always to the first pagepublic function renderDefault(int $page = 1): void { $itemsPerPage = 10; $getArticlesCount = $this->facade->getArticlesCount(); $paginator = new Paginator; $paginator->setItemCount($getArticlesCount); $paginator->setItemsPerPage($itemsPerPage); $paginator->setPage($page); // use page number from URL parameter or first page by default (you get these variables in renderDefault(parameters) automatically) $this->template->news = $this->facade ->getPublicArticles($page, $itemsPerPage); $this->template->paginator = $paginator; } public function renderDefault(int $page = 1, int $perPage = 10): void { $getArticlesCount = $this->facade->getArticlesCount(); $paginator = new Paginator; $paginator->setItemCount($getArticlesCount); $paginator->setItemsPerPage($perPage); $paginator->setPage($page); // use page number from URL parameter or first page by default (you get these variables in renderDefault(parameters) automatically) $this->template->news = $this->facade ->getPublicArticles($page, $itemsPerPage); $this->template->paginator = $paginator; }
<a n:href="default, 1">First</a> // navigate to action=default with first parameter=1 <a n:href="default, $paginator->getPage() + 1">Next</a> // navigate to action=default with first parameter=(current page - 1) <a n:href="default, page: 1, perPage: 5">set 5 items per page</a> // calls renderDefault(1, 5) and keep new values in get parameters in url
Thanks for all the help. That is all covered now I can move on to finishing everything up and upload the site.
Is there way to implement a WYSIWYG editor in my forms so it saves new lines
without using <br />
in the article? If you can point me to
an article for implementing that would suffice.
- Infanticide0
- Member | 103
@Cupara
WYSIWYG editor is more javascript problem, you can use any editor (CKEditor,
TinyMCE…) and load editor in your Form input.
Input value will be HTML code, by default Latte escapes all tags when you try to
print it. To render HTML code you have to use noescape filter (it is security
risk, read docs)
https://latte.nette.org/en/tags#…
Or you can use Texy or Markdown syntax renderers.