Implement an external table

Hello everyone,

i have a php questions which hopefully will result in a plugin. for your understanding, i am planning to switch from a wordpress site to kirby for my local sports club.

for all teams i need to implement a results table. but i dont want to maintain every single table on my own, instead i want to implement an external results table (for exemple: Ergebnisse/Tabellen | HVW - Handballverband Württemberg e.V.)

how could i implement this table? my idea was to use a php function like ```
file_get_contents() or something like this: https://simplehtmldom.sourceforge.io/
unfortunately my php knowledge is not this good. I only want the DOM nodes of the .

Anyone a smarter or better idea or am i on the right direction?

That library looks a bit outdated.

Either use PHP’s built-in DomDocument class: PHP: DOMDocument - Manual

Or a more modern library: GitHub - paquettg/php-html-parser: An HTML DOM parser. It allows you to manipulate HTML. Find tags on an HTML page with selectors just like jQuery.

I have used this one in the past which supports PHP 7 and 8

Ah great! Thank you guys. I will try to play with those and hope get what I want to achieve.

Best regards
Timo

So, I tried the library from @jimbobrjames and @pixelijn and was able to test with some simple selectors to get the title tag for expamle. So thanks again for those tips.

But my main intention to implement the table is still not working. I suspect it has something to do with the fact that the tables content is generated by the filter above the table.

So if try I scrape the hole page I dont get the tables content.

Maybe you two or someone else any more ideas to solve this?

Regrads,
Timo

That’s right, but each filter results in a different URL. So of course you have to know in advance which table you want to get and use the corresponding URL parameters, for example:

https://www.hvw-online.org/spielbetrieb/ergebnissetabellen#/schedule?oId=4&pId=91&wId=2020-09-28

Unfortunately, the parameters and their values are not intuitive at all.

@texnixe

yeah right, thanks. So this url here:
https://www.hvw-online.org/spielbetrieb/ergebnissetabellen#/league?ogId=3&pId=91&wId=2020-09-28&lId=58956
is the table which I need and so I know the url in advance. Thats fine. But still this is not working. If I use the selectors of the php library above I cant render the table.

Another idea I’ve found is:
the table is generated by a JSON file which is the following:
https://spo.handball4all.de/service/if_g_json.php?ca=0&cl=45906&cmd=ps&do=2019-09-23&og=3&p=83
But thats the next problem. I have no experience with JSON. When I format the content here for example: http://json2table.com/
I now know that I only need the part “score” of the JSON (which is the table).

The basic code would be this:

$results = [];
$request = Remote::get('https://spo.handball4all.de/service/if_g_json.php?ca=0&cl=45906&cmd=ps&do=2019-09-23&og=3&p=83');
if ($request->code() === 200) {
  $results = $request->json(true);
}
$scores = $results[0]['content']['score'] ?? null;
dump($scores);

Edited with response code check.

I was just start googleing it… but your too fast! thank you!
Hope I come closer to a solution now.
thanks again…

I’ve edited the code above a bit.

$scores will then contain an array like this

Array
(
    [0] => Array
        (
            [tabScore] => 1
            [tabTeamID] => 535126
            [tabTeamname] => TSV Schmiden 1902
            [liveTeam] => 1
            [numPlayedGames] => 20
            [numWonGames] => 15
            [numEqualGames] => 1
            [numLostGames] => 4
            [numGoalsShot] => 592
            [numGoalsGot] => 547
            [pointsPlus] => 31
            [pointsMinus] => 9
            [pointsPerGame10] => 155,0
            [numGoalsDiffperGame] => 225,0
            [numGoalsShotperGame] => 2960,0
            [posCriterion] => 
        )

    [1] => Array
        (
            [tabScore] => 2
            [tabTeamID] => 535131
            [tabTeamname] => VfL Waiblingen Handball
            [liveTeam] => 1
            [numPlayedGames] => 19
            [numWonGames] => 14
            [numEqualGames] => 1
            [numLostGames] => 4
            [numGoalsShot] => 589
            [numGoalsGot] => 504
            [pointsPlus] => 29
            [pointsMinus] => 9
            [pointsPerGame10] => 152,6
            [numGoalsDiffperGame] => 447,4
            [numGoalsShotperGame] => 3100,0
            [posCriterion] => Td/Sp
        )

    [2] => Array
        (
            [tabScore] => 3
            [tabTeamID] => 535086
            [tabTeamname] => TSV Alfdorf/Lorch
            [liveTeam] => 1
            [numPlayedGames] => 19
            [numWonGames] => 13
            [numEqualGames] => 3
            [numLostGames] => 3
            [numGoalsShot] => 584
            [numGoalsGot] => 507
            [pointsPlus] => 29
            [pointsMinus] => 9
            [pointsPerGame10] => 152,6
            [numGoalsDiffperGame] => 405,3
            [numGoalsShotperGame] => 3073,7
            [posCriterion] => Td/Sp
        )
//...
)

You can then loop through the array and build your table from the data.

Ideally you would also implement caching so that you don’t have to query the file all the time.

Oh great, thank you so much.

I dont know how long I would have to search for all of this…

@texnixe
I added a text field to enter the url in the panel and in the template there is a check if the field is empty and if not than it get rendered. it works just fine.

but I’m stuck at how to check if the field is filled out wrong, for example if someone pasted the wrong url or something like that.
I get the following error:
TypeError thrown with message "array_keys(): Argument #1 ($array) must be of type array, null given"

This is the template code:

if ($page->tabelle()->isEmpty()) {
} else {
    $url = $page->tabelle();
    $results = [];
    $request = Remote::get($url);
    if ($request->code() === 200) {
        $results = $request->json(true);
    }
    $scores = $results[0]['content']['score'] ?? null;
}

On which line exactly is this error thrown? Could you post the stack trace please?

And when exactly?

Oh, of course:

TypeError thrown with message "array_keys(): Argument #1 ($array) must be of type array, null given"

Stacktrace:
#10 TypeError in /Users/timobetz/websites/hsg2b/site/templates/mannschaft.php:91
#9 array_keys in /Users/timobetz/websites/hsg2b/site/templates/mannschaft.php:91
#8 include in /Users/timobetz/websites/hsg2b/kirby/src/Toolkit/F.php:402
#7 Kirby\Toolkit\F:loadIsolated in /Users/timobetz/websites/hsg2b/kirby/src/Toolkit/F.php:379
#6 Kirby\Toolkit\F:load in /Users/timobetz/websites/hsg2b/kirby/src/Toolkit/Tpl.php:35
#5 Kirby\Toolkit\Tpl:load in /Users/timobetz/websites/hsg2b/kirby/src/Cms/Template.php:167
#4 Kirby\Cms\Template:render in /Users/timobetz/websites/hsg2b/kirby/src/Cms/Page.php:1181
#3 Kirby\Cms\Page:render in /Users/timobetz/websites/hsg2b/kirby/src/Cms/App.php:687
#2 Kirby\Cms\App:io in /Users/timobetz/websites/hsg2b/kirby/src/Cms/App.php:1040
#1 Kirby\Cms\App:render in /Users/timobetz/websites/hsg2b/index.php:5
#0 require in /Users/timobetz/.composer/vendor/laravel/valet/server.php:219

But this time it’s another error. this happens when the textfield input has the word “test” in it.

The first error was with the letters “sd” in the textfield.

Without knowing what is in line 91 of mannschaft.php, I cannot help with this.

With textfield you probably mean the tabelle() field?

Hi @texnixe

of course, here you go:

    <table>
        <tr class="text-left">
            <th class="">Verein</th>
            <th class="w-2/12">
                <span class="hidden md:inline">Spiele</span>
                <span class="inline md:hidden">Sp</span>
            </th>
            <th class="w-1/12">S</th>
            <th class="w-1/12">U</th>
            <th class="w-1/12">N</th>
            <th colspan="2">Punkte</th>
        </tr>

        <?php
        if ($page->tabelle()->isEmpty()) {
            echo "<p><strong>Tabelle folgt...</strong></p>";
        } else {
            $keys = array_keys($scores);
            for ($i = 0; $i < count($scores); $i++) {
                echo "<tr class='text-left'>";

                foreach ($scores[$keys[$i]] as $key => $value) {
                    echo "<td>" . $value . "</td>";
                }
                echo "</tr>";
            }
        }
        ?>

    </table>

and yes, tabelle() is the panel text field

$scores in that case doesn’t seem to be an array but null.

So you need to check with is_array() first, if you have an array before you can get the array keys.

Thanks, @texnixe.
This check was the missing part.