inklabs / kommerce-core

PHP shopping cart core platform
https://kommerce-laravel-demo.jamieisaacs.com/
Apache License 2.0
65 stars 14 forks source link

Choose a Template Engine #45

Closed pdt256 closed 8 years ago

pdt256 commented 8 years ago

This does not relate to Core per se; however, it may be included if a good solution presents itself.

Must have features:

Nice to have:

pdt256 commented 8 years ago

Twig vs native PHP using Yii helpers: http://www.yiiframework.com/forum/index.php/topic/67999-pros-and-cons-of-template-engine/page__p__290179#entry290179

pdt256 commented 8 years ago

A swimwear company heard about Zen Kommerce and wants to start using it. We should prioritize this issue for the next release.

pdt256 commented 8 years ago

I'm leaning towards keeping templates in native PHP. These templates could be placed into a separate github project.

Pros:

Cons:

pdt256 commented 8 years ago

When to use template engines: http://stackoverflow.com/questions/5888089/when-to-use-php-template-engines

jasonraimondi commented 8 years ago

Picking on your Pros/Cons List

When to use template engines: http://stackoverflow.com/questions/5888089/when-to-use-php-template-engines

That post, I cant.

His arguments for why you should not use a tempting language include ‘no syntax highlighting and harder to learn/explain’. Any IDE or even text editor worth anything will be able to syntax highlight any tempting language, be it natively or through supported plugins. The pros include ‘extreme boredom’. Basically that was a garbage answer by an obviously biased individual.

I can get behind using pure php as a templating language to keep compatibility open amongst all front ends, that is a totally legitimate reason.

Readability and maintainability

Some of the benefits that I think a templating language are readability and maintainability, and auto escaping is always nice. See the following snippets:

Pure PHP

<?php foreach($somethings as $something) : ?>
<?= $something ?>
<?php endforeach; ?>

// or even worse
<?php foreach($somethings as $something) : ?>
<?= htmlspecialchars($something, ENT_QUOTES, 'UTF-8') ?>
<?php endforeach; ?>

Twig

{% for something in somethings %}
{{ something }}
{% endfor %}

Laravel Blade

@foreach ($somethings as $something)
{{ $something }}
@endforeach

Actually. Templating.

Using a templating language helps keep your projects front end organized by extending views.

I know, all of this can be done in pure PHP.

Most people who are talking about templating in pure PHP because templating languages are too heavy or pointless, usually arent developing the front end in a really maintainable way through layouts and extending views.

pdt256 commented 8 years ago

For context, below is a sample of what we are doing right now. The syntax highlighting and autocomplete in PhpStorm is crucial.

HTML::chars() comes from the Kohana view helpers, but we are planning on taking that out soon. It is a wrapper for htmlspecialchars(). We are also using the Kohana Form helpers that will likely get the boot if we can find a better fit.

screen shot 2016-06-20 at 9 32 58 pm

<?php
/**
 * @var \inklabs\KohanaKommerce\EntityDTO\ProductDTO $product
 */
?>

<h1><?=HTML::chars($product->name)?></h1>

<?php if (! empty($product->images)) { ?>
    <div class="row">
        <?php foreach ($product->images as $image) { ?>
            <div class="col-lg-3 col-xs-4">
                <a href="<?=$image->pathUrl?>" class='product-image'>
                    <img src="<?=$image->pathUrl?>" />
                </a>
            </div>
        <?php } ?>
    </div>
<?php } ?>

<?php if ($product->isInStock) { ?>
    <?=Form::open('cart/add_item', [
        'id' => 'cart_add_item',
        'method' => 'POST',
        'class' => 'form-inline',
    ])?>
        <?=Form::csrf()?>
        <div class="actions">
            <input type="hidden" name="id" value="<?=$product->id->getHex()?>" />
            <button type="submit" class="btn btn-success pull-right">
                <i class="fa fa-shopping-cart"></i> Add to Cart
            </button>
            <div class="input-group input-group-sm col-xs-4 col-sm-3">
                <span class="input-group-addon"><label for="quantity">Qty:</label></span>
                <input class="form-control quantity" type="text" id="quantity" name="quantity" value="1" />
            </div>
        </div>
    <?=Form::close()?>
<?php } ?>
jasonraimondi commented 8 years ago

I've just ported the above to blade, without using the form helpers because I personally dont really like them.

<h1>{{ $product->name }}</h1>

@unless (empty($product->images))
    <div class="row">
        @foreach ($product->images as $image)
            <div class="col-lg-3 col-xs-4">
                <a href="{{ $image->pathUrl }}" class="product-image">
                    <img src="{{ $image->pathUrl }}" />
                </a>
            </div>
        @endforeach
    </div>
@endunless

@if ($product->isInStock) 
    <form action="/cart/add_item" method="PUT" id="cart_add_item" class="form-inline">
        <input type="hidden" name="_token" value="{{ csrf_token() }}"
        <div class="actions">
            <input type="hidden" name="id" value="{{ $product->id->getHex() }}" />
            <button type="submit" class="btn btn-success pull-right">
                <i class="fa fa-shopping-cart"></i> Add to Cart
            </button>
            <div class="input-group input-group-sm col-xs-4 col-sm-3">
                <span class="input-group-addon"><label for="quantity">Qty:</label></span>
                <input class="form-control quantity" type="text" id="quantity" name="quantity" value="1" />
            </div>
        </div>
    </form>
@endif

While this does show a little bit of a cleaned up view, you cant really see the power of using a templating language without seeing the layouts and extends.

Syntax highlighting should work fine for most any templating language, as well as autocomplete.

screen shot 2016-06-20 at 10 02 54 pm

screen shot 2016-06-20 at 10 03 34 pm

fulopattila122 commented 8 years ago

@jasonraimondi I wonder why are you manually coding forms with blade, by hardcoding the action (instead of a url or named route), also the token field instead of eg. laravel forms. Not that it's bad, but it seems you're a big proponent of template engines and their features, so that's why I wonder why not using it's goodies.

I am actively working with twig, blade and plain PHP, all are working pretty well. Twig is the most 'fascist' template engine, but sometimes it's pretty time consuming to work with. Blade templates are actually php files you can do anything you want in php, thus not a real separation of concerns. Still my favourite though :)

On the other hand as far as I understand (Zen) Kommerce Core is an e-commerce library (and not a platform) which IMHO should not be dealing too much with template engines. Maybe I'm not interpreting it correctly, but it is aimed to be framework agnostic so that one should take it and "import" into an arbitrary framework. Then you can use any template engine of your (or the framework's) choice.

bryan-maxwell commented 8 years ago

The idea is to be framework agnostic. We want to have a simple to use plugin and theme system that follows SOLID principles. Kommerce could provide a base theme for the admin panel as well as the front end store with the ability to extend and or modify that through some sort of presentation layer that's exposed to themes and or plugins.

Right now all of that is in Kohana Views that could be ported over to twig, mustache, blade, or kept as pure PHP. I'm not really fighting for one or the other, I just want it to be clean and easy to adopt without a lot of learning curve. Pure PHP templates offer this without any additional overhead IMHO. I also don't see why, with using some kind of inheritance model, you can't use whatever you prefer and just register your theme to override or extend other portions of the presentation layer.

This wouldn't be apart of core necessarily but more a specific set of presentation layers for core to show people how to skin Kommerce and how to develop plugins that can modify behavior based on domain events.

jasonraimondi commented 8 years ago

@fulopattila122 I do actually use the route helper in my projects, in the example above I just quickly ported the example above into blade.

I like template engines as a whole, but I don't prefer using form helpers because I think they are a pointless abstraction that do not really bring any benefits.

bryan-maxwell commented 8 years ago

That being said Twig looks promising from the stand point of a front end developer and some of the features you get out of the box. I'm personally just not a big fan of blade, but could be persuaded.

I like the idea of defining blocks within Kommerce that are themeable and using inheritance in child themes to implement customizations.

<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css" />
            <title>{% block title %}{% endblock %} - My Webpage</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                &copy; Copyright by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>
jasonraimondi commented 8 years ago

Right now all of that is in Kohana Views that could be ported over to twig, mustache, blade, or kept as pure PHP.

Realistically, all that is in any of the proposed views or templating could be just as easily ported over to / from eachother.

I like the idea of defining blocks within Kommerce that are themeable and using inheritance in child themes to implement customizations.

I totally agree that layout inheritance is one of the primary benefits of using a templating engine that you get out of the box. Of course you can do all of this in pure PHP, I just think that using a templating tool can help encourage it.

What does Kommerce need to know about the presentation layer (if anything)? I would imagine nothing.

I agree, I do not think Kommerce needs to know anything about the presentation layer, except what data it needs to pass to it.

I really think that Kommerce needs to define one method as the 'preferred' or 'official' way to build layouts and themes, while also keeping flexible to allowing end devs to use a different templating option if they choose so.

pdt256 commented 8 years ago

Thanks everyone for bringing up valid points in this discussion.

The reality of the situation is that we need to solve these problems:

I have read more about Twig and feel it is the best option moving forward with the above constraints in mind. I will likely be the one implementing the first version into our closed-source Kohana application.

Please let me know your concerns in this thread, and reasons for/against creating a new Github project to hold the default Twig theme skin for Zen Kommerce. We can take a vote if necessary.

fulopattila122 commented 8 years ago

@jasonraimondi

I don't prefer using form helpers because I think they are a pointless abstraction that do not really bring any benefits.

An example benefit is eg. when using blade, Form:: helpers are bound to Laravel's validation engine, and are quite beneficial if you want to use either a controller's validate(..) helper or validation + redirect ->withInput(). (The former actually does internally the latter.)

This results your users don't have to re-enter the form data again in case the validation fails.

pdt256 commented 8 years ago

The following projects have been created to address this issue: