HNHacker News
TopNewBestAskShowJobs

tored

1,022 karma · joined October 29, 2020

submissionscomments
tored··on Oink: An API for PHP in a single file
No, functions are never autoloadable in PHP (except with nasty hacks).
tored··on Oink: An API for PHP in a single file
Yes, the paradox with ORMs are that you actually need caching because they are typically very slow, with raw SQL and good indexes you can usually query database live for most of it.

I find it usually better to have short timed cache in front of the renderer instead, like caching the HTML or JSON output of a view, then you don't end up with inconsistent data because one table was cached and another wasn't.

tored··on Oink: An API for PHP in a single file
I wouldn't pick an ORM even for caching, ORMs are typically a multi-layered blackbox magic based God class, thus very hard to debug when things hit the fan.

Here is I how I do it with simple SQL and built in PHP constructs, easy to read, debug and implement.

First part of the example is class based and the second one function based if you are more into that.

    <?php
    declare(strict_types=1);

    // SQL with classes

    namespace {
        $pdo = new PDO('sqlite::memory:');
        $pdo->exec(
            "CREATE TABLE article (
                    article_id INTEGER PRIMARY KEY,
                    name TEXT NOT NULL
                )
        ");
        $pdo->exec("INSERT INTO article (name) VALUES('My Article')");

        interface Cache
        {
            public function get(string $key): mixed;

            public function set(string $key, mixed $data): void;
        }

        final class RuntimeCache implements Cache
        {
            private array $cache = [];

            public function get(string $key): mixed
            {
                return $this->cache[$key] ?? null;
            }

            public function set(string $key, mixed $data): void
            {
                $this->cache[$key] = $data;
            }
        }

    }

    namespace Article {

        use Cache;
        use PDO;

        readonly class Article
        {
            public int $article_id;
            public string $name;
        }

        interface ArticleRepository
        {
            public function getArticleById(int $article_id): Article|null;
        }

        final class SqlArticleRepository implements ArticleRepository
        {
            public function __construct(private readonly PDO $pdo)
            {
            }

            public function getArticleById(int $article_id): Article|null
            {
                $stmt = $this->pdo->prepare(
                    "SELECT article_id, name
                       FROM article
                       WHERE article_id = ?");
                $stmt->execute([$article_id]);
                $article = $stmt->fetchObject(Article::class);
                return $article === false ? null : $article;
            }
        }

        final class CachedArticleRepository implements ArticleRepository
        {
            public function __construct(private readonly Cache             $cache,
                                        private readonly ArticleRepository $articleRepository)
            {
            }

            public function getArticleById(int $article_id): Article|null
            {
                $key = "article-{$article_id}";
                $cached = $this->cache->get($key);
                if (!empty($cached)) {
                    return $cached;
                }
                $article = $this->articleRepository->getArticleById($article_id);
                if ($article !== null) {
                    $this->cache->set($key, $article);
                }
                return $article;
            }
        }
    }

    namespace {
        $repo = new Article\CachedArticleRepository(
            new RuntimeCache(),
            new Article\SqlArticleRepository($pdo)
        );
        var_dump($repo->getArticleById(1));
        var_dump($repo->getArticleById(1));
    }


    // SQL with functions

    namespace {
        function curry(callable $f, ...$args): callable {
            $rf = new ReflectionFunction($f);
            $count = $rf->getNumberOfParameters();

            return function (...$arguments) use ($f, $rf, $count, $args) {
                if (count($args) + count($arguments) >= $count) {
                    return $rf->invokeArgs(array_merge($args, $arguments));
                }
                return curry($f, ...array_merge($args, $arguments));
            };
        }
    }


    namespace Article\SqlRepository
    {
        use Article\Article;

        function getArticleById(\PDO $pdo, int $article_id): Article|null
        {
            $stmt = $pdo->prepare(
                "SELECT article_id, name
                           FROM article
                           WHERE article_id = ?");
            $stmt->execute([$article_id]);
            $article = $stmt->fetchObject(Article::class);
            return $article === false ? null : $article;
        }
    }

    namespace Article\CachedArticleRepository
    {
        use Article\Article;

        function getArticleById(callable $cacheGet, callable $cacheSet, callable $getArticleById, int $article_id): Article|null
        {
            $key = "article-{$article_id}";
            $cached = $cacheGet($key);
            if (!empty($cached)) {
                return $cached;
            }
            $article = $getArticleById($article_id);
            if ($article !== null) {
                $cacheSet($key, $article);
            }
            return $article;
        }
    }

    namespace {
        // for this example, just reuse existing class based implementation
        $runtimeCache = new RuntimeCache();
        $getArticleById = curry(Article\CachedArticleRepository\getArticleById(...),
                    $runtimeCache->get(...), $runtimeCache->set(...),
                    curry(Article\SqlRepository\getArticleById(...), $pdo));

        var_dump($getArticleById(1));
        var_dump($getArticleById(1));
    }
tored··on Oink: An API for PHP in a single file
Native SQL is the way to go, I always push for SQL over ORM in every project I'm in.
tored··on Oink: An API for PHP in a single file
Personally I believe that you should always use require (require_once) instead of include (include_once) to be sure that a failure to load file creates an E_ERROR instead of an E_WARNING, this both for loading the framework but also when the framework when loading the api file.

E_ERROR is a fatal error thus it will throw (I think since PHP 7) an Error exception that can be catched with a normal try/catch and thus possible to return a proper response.

tored··on Ask HN: What is your go-to stack for the web?
For web PHP.

PHP has many stable frameworks if you are in to that and if you don't want to use a framework you can run vanilla PHP without a problem.

Dependency management is done these days with composer and it is easy add a dependency, like framework or library, from composer.

PHP has has lot of good tooling like IDEs, linters, testing etc.

Here is a short intro to PHP I wrote a few years ago.

https://news.ycombinator.com/item?id=25222509

tored··on jQuery v4.0 Beta
Loading jQuery twice is a band aid solution.

However the jQuery 4 announcement page linked to this jQuery migration plugin that I was unaware of. Perhaps it can help in some old projects.

https://github.com/jquery/jquery-migrate

tored··on jQuery v4.0 Beta
Worst part of jQuery is actually upgrading it to a new version, because the api design that made jQuery powerful is also what makes it quite difficult figure out if you broke anything.
tored··on Passwordless: a different kind of hell?
Sweden has universal healthcare and education is free, but still Sweden suffers from massive crime wave.

Sweden's welfare state is a left wing dream come true, however the bad news for the left is that it empirically disproves every left wing idea about crime and society.

tored··on Passwordless: a different kind of hell?
Please explain what is the root problem and how solve it.
tored··on Passwordless: a different kind of hell?
Why don’t thieves stop being thieves after they can afford food?
tored··on Passwordless: a different kind of hell?
If what you are claiming is true then the welfare state of Sweden wouldn’t experience almost any crime at all because no one in Sweden suffers from food insecurity.

The educated middle class can afford to hold the most out of touch abstract theories because they don’t need to suffer the consequences.

tored··on Late 70s and 80s: forget BASIC, we had Pascal and C
There is an unwarranted hate against BASIC. BASIC has of course also evolved since then and you can still write professional software in numerous BASIC dialects just as in Pascal.

Few years ago I evaluated FreePascal for writing desktop applications, I ended up instead with the BASIC dialect PureBasic (albeit commercial), better out of the box experience. Pascal is also slightly more verbose than BASIC.

tored··on Late 70s and 80s: forget BASIC, we had Pascal and C
My first programming language was Commodore BASIC. It was already there when you booted up the machine, loading another compiler never crossed my mind.
tored··on PHP 8.3
I should be, it already exist a .NET implementation of PHP.

https://www.peachpie.io/

https://www.peachpie.io/usecases

tored··on HTML Web Components
> What is that, exactly?

Component rendered before client side JavaScript.

> Web components quite literally don't work without Javascript.

That is why I'm not using them.

tored··on HTML Web Components
Sure, the article is incomplete in the sense that it doesn't fully commit to the idea of HTML Web component as opposed to JavaScript Web components, but it is the correct way of thinking about this.

There will almost always be a roundtrip, either to fetch HTML segments or to ask for more JSON data, except for the rare cases you already have everything, because that is the nature of client-server paradigm.

By putting all your templates in the backend you can render them as a whole document or in parts in one go and send them wherever, to the browser, over Ajax or in the email. No need for buggy asynchronous SQL JOINs over HTTP and infinite state handling.

If you always start with a JavaScript function, and all that comes with that, you need a programmer to be able to create the web, but with HTML (and CSS) first you can have other categories of people do that, like designers. And combine that with a library like htmx you can then enhance that experience for interactive parts and still keep everything in the same backend template. And if it still a need for more complex interactive parts a programmer can can add that with JavaScript afterwards. That is a much better division of labour.

And it is not outdated, browser actually excel in rendering HTML documents, that is what they are designed to do, thus it will always be faster to render the HTML document as it is rather than building it on the fly.

And also the core idea of reaching for JavaScript before HTML will result in suboptimal solutions, I have seen so much unnecessary JavaScript code that could have been easily solved with a few lines of HTML. This change of perspective changes how we think and reason about a problem and therefore our solutions as well. That is why the bootstrapping of a "modern" web app has become more and more asinine.

Another problem with frameworks like React, Vue, Angular and et al have is that they have their own lifecycle and that has made the web closed and not open how it once was, closed in the sense that you can't enhance the HTML document from the outside after it been rendered, thus this leads to the assumption that the person(s) who wrote the site is also the person(s) that manages or uses it, that is a bad assumption.

tored··on HTML Web Components
The article argues between the difference of a JavaScript Web component and a HTML Web component, you describing the former, thus the need for JavaScript.

Personally I think the main problem here is client side rendering to begin with, with a modern server side templating library you get a component based structure too and can abstract whatever HTML tags you want in your component before client side JavaScript.

Problem with React is that it is JavaScript first, you always begin with a JavaScript function, but in my opinion the web should be HTML first.

tored··on jQuery 4.0 99% Complete
It depends, if the page is very dynamic the element may or may not be there.

Point is that the DOM API version of the initial jQuery snippet are not equivalent. $() statement does a bit more than that.

This becomes obvious if the requirement are a bit more complex than the example, perhaps we want to chain more expression on at the end, then the DOM API version becomes more convoluted.

tored··on Windows 11 adds native support for RAR, 7-Zip, Tar and other archive formats
In theory that sounds like a great idea, however in practice it isn't, because all you have done is compiled your own custom made distro that no one else uses and benefits from, thus just a waste of time and resources.
tored··on Windows 11 adds native support for RAR, 7-Zip, Tar and other archive formats
If the problem is in the desktop environment why then replace the kernel? Doesn't make much sense.
tored··on jQuery 4.0 99% Complete
However getElementById() can return null, thus that entire statement can error. In the old days you had to sprinkle your code with if checks when using the DOM API.
tored··on The future of warfare: A $400 drone killing a $2M tank
That longbow shot was still most of the time within the combat zone, you as an individual knew that we can get ambushed here.

Today you can get killed even far away from the front in a place that was considered mostly safe in previous wars.

The psychological effect today is much worse than anytime in history.

tored··on Varoufakis: Capitalism is dead, long live Technofeudalism
Why not? Non-engineers seems always be the most eager to use the cloud to the most extreme.

It is your tech-illiterate friends that hook you into the toxic cloud merely by having your contact information.

Technology changes social interactions.

tored··on Varoufakis: Capitalism is dead, long live Technofeudalism
There is no functioning market if it is a monopoly.
tored··on Varoufakis: Capitalism is dead, long live Technofeudalism
And what group today is the "right people" that these corporations push for?
tored··on Varoufakis: Capitalism is dead, long live Technofeudalism
But how is it fascism? These corporations are above the nation state.
tored··on Varoufakis: Capitalism is dead, long live Technofeudalism
I guess it comes down to the definition of capitalism, Mr Varoufakis says that it is markets and profits. I'm not an economist, thus a layman, but I can't entirely agree with that, in my opinion it is perfectly fine to have capitalism without markets, e.g. private monopoly (or oligopoly). From that perspective you can argue that is sort of like feudalism where privileges where used to create monopiles.
tored··on Varoufakis: Capitalism is dead, long live Technofeudalism
You may have the skill, knowledge and wealth to pay for email, news and services, but a large part of the population doesn't and they will drag you down with them.

Edit: typo, 'to' instead of 'the'

tored··on Richard Stallman reveals he has cancer in the GNU 40 Hacker Meeting talk [video]
Common argument from Free software advocates is that violation of user's rights is a consequence of proprietary software.

With Google you can even make an argument that they can violate more user's rights because of Free software.

Don't get me wrong, I'm not against Free software per see, the topic is just more complex than what is presented.

← PreviousPage 5 of 26Next →