Jump to content
fruid

include _main.php only when it's not an ajax call

Recommended Posts

I always thought you can exclude the _main.php file when you include index.php or something.

On some page I do an AJAX-call and with the response text I replace the innerHTML of some div. I put the code that is requested via AJAX on a php-file that I put in the root folder, otherwise it also includes the "head" part which is included on _main.php so I would have the entire page inside the mentioned div, which is of course not what I want.  This works fine. However, I'd like to clean this up a bit and make use of: 

if($config->ajax) :  ; else :  ;

to either only include the header when it's not an ajax request or exclude them when it is.

But include index.php doesn't seem to work.

I tried to disable including of _main.php on the template settings and then do

if ($config->ajax) : 
$config->prependTemplateFile = 'includes/_head.php';
endif;

But that doesn't do anything. What am I not getting?

Share this post


Link to post
Share on other sites

I now got it working like this:

I exclude the _main.php (which includes the _head.php and all) on the template settings.

I then create an if-condition on the template file, dividing the content as follows 

<?php namespace ProcessWire; 
if (!$config->ajax) {
    // here's all my static stuff
    echo '<div id="content">';
    echo '<div id="dynamic">';
    // place for the ajax response text by replacing the innerHTML
    echo '</div>';
    echo '</div>';
    ...
    include 'includes/_main.php'; 
}

and 

else {
    // here's all my ajax loaded code/content from the server
} 

lastly, I put:

<script type="text/javascript" src="path/to/my/javascript.js"></script>

My AJAX request looks as follows

function getContent() {
    var xhr = new XMLHttpRequest();
    if (xhr) {
        xhr.onreadystatechange = replaceContent;
        xhr.open("GET", "./?some=variable&someother=variable, true);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.send(null);
    };
};

function replaceContent() {
    xhr.readyState;
    if (xhr.readyState == 4 && xhr.status == 200) {
    	var str = xhr.responseText;            
        document.getElementById("dynamic").innerHTML = (str);
    };
};        

It works, like it did before, except that now it is very slow. In my console I think I can see that the request gets sent quickly but the server takes about 5 seconds to respond so it's mostly waiting. I tested on my local MAMP machine (which is always slower) and live server, both have the same problem.
So the TTFB is 4.51s, if I put the ajax-requested file in the root folder (as described in the the initial thread) I have a TTFB of 775ms

thoughts?

Share this post


Link to post
Share on other sites

is it a cache problem? some bottleneck? some redundant code? no idea how to even start, tracy debugger is not helping either.

Share this post


Link to post
Share on other sites

I assume you're using the markup regions output strategy ? If so, when getting an ajax call, once you're done in your code and have echoed your response, you can call

$this->halt();

to stop the template output (from https://processwire.com/blog/posts/processwire-2.6.8-brings-new-version-of-reno-admin-theme-and-more/#new-this-gt-halt-method-for-use-in-template-files) (I couldn't find it referenced in the doc though...)

So for example in my case I have (in my page.php)

if ($config->ajax) {
	http_response_code(200);
	header('Content-Type: application/json');
	// code to populate $json
	echo json_encode($json);
	return $this->halt();
}

 

  • Like 2

Share this post


Link to post
Share on other sites

Thanks for the suggestion, however I don't use json output, it's just a php code that is called, that renders html markup. Not sure if that's the issue.

Share this post


Link to post
Share on other sites

It should work for your situation as well. Render your HTML markup and once you're done and want to stop PW output call $this->halt. Try and let me know if it works.

Edit: That is, in your initial setup where you have _main.php included by default after your template

  • Like 1

Share this post


Link to post
Share on other sites

OK I re-activated the automatic inclusion of _main.php on the template settings, added

$this->halt(); // also tried with return $this->halt();

 makes sense and it does the same, so much so that it's not faster either.

Share this post


Link to post
Share on other sites

At least it's cleaner ? 🤷‍♂️

Re: perf difference, I can't say for sure but maybe having the file in the root made it so it's called outside of PW's context ? That may explain why it's faster as it would be raw php.

Share this post


Link to post
Share on other sites

 

3 minutes ago, monollonom said:

maybe having the file in the root made it so it's called outside of PW's context

yes that's exactly what it looks like…

Share this post


Link to post
Share on other sites

do you reckon using json-encoding would speed things up? PW is so proud of being so fast, here it fails 😞 

Share this post


Link to post
Share on other sites

Hm not really since in the end it's about PW outputting data, whether it's within HTML tags or as a json object.

Here you only provide a very small sample of your setup so it's hard to tell, but there could a number of things that impacts the performance of PW. Hooks that take a long time to execute or something... Using TracyDebugger could help you narrow down what's going wrong.

  • Like 1

Share this post


Link to post
Share on other sites

I'm using TracyDebugger but it's a jungle to me, not sure how to use it efficiently. Google PageSpeed Insights can be useful though. 

I will check the hooks then. Thanks so far.

Share this post


Link to post
Share on other sites

it wasn't hooks either. 

I fooled around a bit more and realised that it has to be the code that runs on the server to create the ajax response text. I replaced the entire code with just a simple echo command which was super fast, that's how I knew.

But for some reason, it's faster now, even with the code, I'm not sure what exactly got it to work.

Anyways, hard to say how to improve the code, I use a foreach loop with certain if-conditions to filter instead of proper PW-selectors.

Here's my code:

        $year_start = $y.'-01-01';
        $year_end = $y.'-12-31';
        $year_overview = new WireArray;
        foreach ($all_events as $ae) :
            if ($ae->date_start<=$year_start && $ae->date_end>=$year_start && $ae->date_end>=$ae->date_start) :
                $year_overview->add($ae);
            elseif ($ae->date_start>=$year_start && $ae->date_end<=$year_end && $ae->date_end>=$ae->date_start) :
                $year_overview->add($ae);
            elseif ($ae->date_start<=$year_end && $ae->date_end>=$year_end && $ae->date_end>=$ae->date_start) :
                $year_overview->add($ae);
            endif;
        endforeach;
        echo table_events($year_overview);

The code works fine.

That said, I also still don't know how to save the variables in the in-memory database and then just access and filter what's in that memory instead of fetching from the database every time anew, I guess that would speed things up as well? Where can I see what's "in-memory", Tracy Debugger?  

https://processwire.com/talk/topic/6246-table/?do=findComment&comment=207312

More importantly, I'm facing another problem now which I didn't have in my previous setup, which is that Umlaute äöü don't get displayed correctly, instead I see this stuff: ���. I read online that it has to do with the database of which the collation is set to "utf8_general_ci" when it should be "utf8mb4_unicode_ci"? But I have doubts because it used to work before and I would rather not fool around with the database at all.

Need to fix this quickly, it's live…

Thanks for help

Share this post


Link to post
Share on other sites

put this in your head tag

<meta http-equiv="content-type" content="text/html; charset=utf-8" />

and make sure your PHP files are UTF8. VS Code tells you in the status bar. Notepad++ has “Encoding” in the menu bar. Make sure it isn’t UTF8BOM.

2 hours ago, fruid said:

I use a foreach loop with certain if-conditions to filter instead of proper PW-selectors.

Is $all_events the contents of a FieldtypeTable? How much stuff is there to iterate? If you fetch a large amount of data just do discard it, it might be worthwhile to move the filtering to the database.

Also if you just want all events that interesect the year somehow, you can do this

foreach ($all_events as $ae)
    if ($ae->date_start <= $year_end && $ae->date_end >= $year_start && $ae->date_end>=$ae->date_start)
        $year_overview->add($ae);

 

  • Like 1

Share this post


Link to post
Share on other sites

thanks, I tried, but doesn't help.

Also I can tell the issue doesn't seem to be the database because content from the db with äöüß gets displayed correctly, it's just the date, in German that'd be März (for march) that is displayed wrong. So I understand I don't need to fix the database, just tell php that it should be UTF-8 somehow, it seems to miss that part somehow since I moved some files around.

Also, there's supposed to be a php header (?) like…

header('Content-type: text/html; charset=utf-8');

I put this in the <head> also tried to include it earlier, in _init.php and even earlier in ready.php, doesn't help either. 

Share this post


Link to post
Share on other sites

try putting this somewhere like config.php or something.

setlocale(LC_ALL, 'de_DE.utf8');

 

  • Like 1

Share this post


Link to post
Share on other sites
49 minutes ago, Jan Romero said:

or something

…that was key, because putting it on config.php doesn't do anything. It's like: you had one job!!

Thanks, looks like you were right again after all, kind of 😄

 

Share this post


Link to post
Share on other sites

on the very template itself, outside of any ifs and elses so that it's included with or without ajax making the call. 

You don't have to be sorry, your advice helped a lot!

Share this post


Link to post
Share on other sites

Once you've created your $year_overview PageArray, does the template use custom fields from the pages to generate the output? If so, it may be that the slowness is due to multiple calls back to the db during loops to get the custom fields' data.

Try including the custom fields in the initial selector with 'auto-join' or using the new methods released by Ryan.

https://processwire.com/blog/posts/find-faster-and-more-efficiently/#boost-performance-with-new-programmatic-autojoin-options

 

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...