Ain’t gonna need the Symfony bundle!

Often we think a bundle is the solution to our problems and we try hard to fit it into our app. Then developing an app becomes developing hacks to work around things extra-nous to our domain into our domain forcefully or as some could say “cleverly”.

Screenshot 2014-09-04 10.37.44

Lately I did a PR to a repo of an angularjs and RESTful implementation with the FOSRest libraries from symfony. But then I got this response to my PR:

Screenshot 2014-09-04 10.48.19
https://github.com/bayne/symfony-angular-todomvc/pull/1

So to try to prove the point of keeping it simple I went ahead and discovered some nice features from heroku. It will become certainly one of the tools i use if I can pay for it since development is faster, compilation is faster, everything is faster, even I am thinking running jolici or running tests suite in heroku if possible.

I had to use the buildpack for php from @chh and you can literally build the app clicking your iphone.

+        },
+        "heroku": {
+            "framework": "symfony2",
+            "compile": [
+                "cd web; ./../node_modules/.bin/bower install"
+            ]

This thing that was the big reason why plugging a bundle to plug composer hooks was a simple line of code added to the composer thanks to the buildpack. Everything else went quickly in the flow using bower.io and just the tools we know about.

Check the app, I can’t believe it is so easy 🙂

http://here-quick-cordoval-3.herokuapp.com/#/

Now you can PR and show it is working with one click:

Screenshot 2014-09-04 11.30.45

Enjoy!

Free HTML, CSS, PHP, JavaScript editor (IDE) – Codelobster PHP Edition

Screenshot 2014-09-04 08.50.16

In the world of open source softwares Codelobster is an integrated development environment which is fulfilling the requirements of all newbie’s in web programming world. Being a fresher if we have some freeware in hand then we can start our work without many thoughts. Obviously if the start is nice one can go far.

Some commendable features of Codelobster:

  • To highlight the code for different file tyes Codelobster has different color schemes. Being a developer I find it a tremendous feature to have highlighted code to easily differentiate it in complex coding.
  • Codelobster is providing auto completion feature for PHP, HTML, CSS and Javascript, along with HTML5 and CSS3. Full concentration on logical aspect is very necessary when one wants to do extensive coding.
  • Pressing F1 will open help for tags and attributes. There is plenty of information available. For few supported languages Context help is also available.
    Code based variable values can be seen using PHP debugger. By debugging; developer can look for errors and proceed further.
  • After successful coding it is also necessary to deploy code on remote servers and Codelobster offers FTP support.
  • Codelobster comes with portable versions that means there is no need to install it. One can immediately start using it just by keeping it on system disk.
  • Along with data exporting feature Codelobster provides base for CRUD operations. This can be achieved using SQL manager which highlights sql files and also the auto completion.
  • To relate code pages; Codelobster has inspector functionality like we see in Mozilla plugin.
    Codelobster is offering few more nice features like: navigating files & functions along with their descriptions by keep pressing the CTRL key, block selection possibilities, tool-tips, code collapsing, highlighting of pairs, bookmarking, file-view & folder structuring along with browser preview.
  • Few special plugins to work with are following:
  • JavaScript libraries: JQuery, Node.js
  • CMS: Drupal, WordPress , Joomla
  • Template engines: Smarty and Twig
  • PHP frameworks: Phalcon, CodeIgniter, Yii, CakePHP, Laravel, Symfony

Developer Site: http://www.codelobster.com/

Doctrine Simple Mapping and Repository Compiler Pass

Recently I stumble upon some doctrine repository definition situation where there were many definitions of custom doctrine repositories. Instead of having a long list over and over of a custom doctrine service definition I started to look at simpler ways this can be just done and let that adapt within a compiler pass and be customized further down the road as much specific to the application as possible.

I checked out https://github.com/mmoreram/SimpleDoctrineMapping and even though this package seems to be interesting to simplify the auto-mapping in some way I wanted to really have a way to do the simplification not for the mapping of the entities but for the custom repository service definitions. One good thing about this library is that is not a bundle! yey!

So I ended up with just passing an array of parameters, with keys being the model classes, and the values being the repository fqcn’s.

<?php
 
namespace Vendor\Package\DependencyInjection\Compiler;
 
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
 
class CustomRepositoryPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getParameter('repositories') as $model => $class) {
            $definition = new Definition();
            $definition
                ->setClass($class)
                ->setArguments([$model])
                ->setFactoryMethod('getRepository')
                ->setFactoryService('doctrine')
                ->setPublic(true)
                ->setLazy(true)
            ;
 
            $container->setDefinition(
                'vendor.repository.'.$this->slug($class),
                $definition
            );
        }
    }
 
    private function slug($fqcn)
    {
        $fqcn = str_replace('Repository', '', $fqcn);
        $names = explode('\\', $fqcn);
        $string = end($names);
        $string = preg_replace('/([A-Z])/', '_$1', $string);
 
        return strtolower(substr($string,1));
    }
}

This as a first approach is simple and straight to the point. Now my 100’s of lines on service definitions for custom repositories were downed to just specifying the key value pairs as parameters:

parameters:
    repositories:
        Vendor\Package\Model\Action: Vendor\Package\Repository\ActionRepository
        Vendor\Package\Model\Tenant: Vendor\Package\Repository\TenantRepository
        // ...

This compiler pass can be used as i have shown in previous posts without the need of a bundle fortunately! And it can be further taylor to meet the domain needs of your domain packages.

Although in early stage I just wanted to put it out so it could benefit someone with the same problem. Take it just as an initial idea and then improve upon it like I am doing in other projects.

Encouragements, thanks for reading. Appreciated!

Code Nuances, Important to Who Hears/Reads

This is a long promised post.

Let’s start.

What is wrong with the following picture?

$subject        = $actionManager->findOrCreateComponent($user);
$someMorelonger = $actionManager->execute($subject);

First, the brain look for differences to understand what is being written. You don’t see a book aligning their similar *Howevers* across pages. What you see is in a poem the font is well taken care and the procedures administered to markup based on syntax.
Aligning equals in this case makes it harder to maintain. Suppose you add a third line, that has a longer property name, now you need to change three lines instead of one. Makes no sense right?

Second, the brain works reading from left to right and from top down. You don’t gain anything by indenting weirdly spaces like this before an equal sign. It is code, poetry, not a senseless computer matrix.

The other example aligned with this mindset is. What happens when the word is too long like here:

    "phpunit/phpunit":                      "~4.1.4",
    "matthiasnoback/symfony-service-definition-validator": "~1.2.0",
    "raulfraile/ladybug": "~1.0.8"

All plot to have neatly aligned versions is thrown to the trash can! Just don’t waste time doing this is my advice.

Let’s see another of this well known hassles:

<?php
 
namespace Bafford\PasswordStrengthBundle\Validator\Constraints;
 
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
 
class PasswordStrengthValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        if($value === null)
            $value = '';
 
        if($constraint->minLength > 0 && (strlen($value) < $constraint->minLength))
            $this->context->addViolation($constraint->tooShortMessage, array('{{length}}' => $constraint->minLength));
 
        if($constraint->requireLetters && !preg_match('/\pL/', $value))
            $this->context->addViolation($constraint->missingLettersMessage);
 
        if($constraint->requireCaseDiff && !preg_match('/(\p{Ll}+.*\p{Lu})|(\p{Lu}+.*\p{Ll})/', $value))
            $this->context->addViolation($constraint->requireCaseDiffMessage);
 
        if($constraint->requireNumbers && !preg_match('/\pN/', $value))
            $this->context->addViolation($constraint->missingNumbersMessage);
    }
}

This time in a known password strength bundle. Notice the hassle in maintaining these conditional without braces. It just makes it harder to read and maintain. If one makes a mistake there, hunting the bug could be very tedious and cryptic.

The importance of use for a cs fixer tool cannot be underestimated. For a code that is changing continually, error prone, introducing an error happens at a fast rate. Therefore we should be more careful and integrate the fixer into the cycle.

Picture now simple code turned into a nightmare:

function it_does_the_job();

Into:

/**
 * It does the job.
 * It does some very complicated stuff, but gets the job done.
 *
 * @author Luis Cordova <cordoval@gmail.com>
 * @author Some other author <etc@gmail.com>
 * @package my package
 * @license MIT
 *
 * @param void
 * @return void
 */
public function it_does_the_job();

It just does not make sense when git and services like github et al help us find who did what in a project.

Let’s jump to another nuance, this time is getting into the custom of locking the composer to 3 digits. Some people do:

"jms/di-extra-bundle": "1.4.*",
"jms/aop-bundle": "1.0.*"

Instead of:

"jms/di-extra-bundle": "1.4.1",
"jms/aop-bundle": "1.0.1"

Or similar. The thing is sometimes when they just do 1.4 or ~1.4 some have the wrong idea. You should read this https://igor.io/2013/01/07/composer-versioning.html. However an improvement on top of it is the custom to specify 3 numbers like in:

"jms/di-extra-bundle": "~1.4.1",

This is a better practice since it allows only the minor number to sweep. It does not leave any doubt as to which number is flexible and helps avoiding some undesired scenarios like:

Hm, why 2.2.1 are older then 2.1 ?
I use this format in composer
 
"apy/datagrid-bundle": "~2.1"
And i have 2.2.1 version

:), then you wonder!

There are more nuances but i am shipping this blog to help today rather than later!

Elcodi Ecommerce Going Components (Symfony-based): Review and Startup your store!

Sometime ago I wrote a book on Symfony Ecommerce at http://pilotci.com. This blog post expands to cover a solution that has taken a good decision lately. The decision of Elcodi to go components. This is packages, somewhat decoupled at first but aiming to more decoupled type packages.

The quick way to see how a store can be put together with Elcodi components is by clonning its flag store https://github.com/elcodi/bamboo-store:

git clone git@github.com:elcodi/bamboo-store.git
cd bamboo-store
composer install

You will need my PR https://github.com/elcodi/bamboo-store/pull/29 to get the right dependencies and the basic store working.

Also you will need this https://github.com/elcodi/elcodi/pull/252/files. Because there is an error when the database is not setup and the command is set as a service.

After running creating the database and schema and running the fixtures:

~ php app/console doctrine:fixtures:load
Careful, database will be purged. Do you want to continue Y/N ?y
  > purging database
  > loading Elcodi\Bundle\LanguageBundle\DataFixtures\ORM\LanguageData
  > loading Elcodi\Bundle\AttributeBundle\DataFixtures\ORM\AttributeData
  > loading Elcodi\Bundle\RuleBundle\DataFixtures\ORM\ExpressionData
  > loading Elcodi\Bundle\MenuBundle\DataFixtures\ORM\NodeData
  > loading Elcodi\Bundle\UserBundle\DataFixtures\ORM\CustomerData
  > loading Elcodi\Bundle\BannerBundle\DataFixtures\ORM\BannerZoneData
  > loading Elcodi\Bundle\CurrencyBundle\DataFixtures\ORM\CurrencyData
  > loading Elcodi\Bundle\ProductBundle\DataFixtures\ORM\CategoryData
  > loading Elcodi\Bundle\ProductBundle\DataFixtures\ORM\ManufacturerData
  > loading Elcodi\Bundle\ProductBundle\DataFixtures\ORM\ProductData
  > loading Elcodi\Bundle\CartBundle\DataFixtures\ORM\CartData
  > loading Elcodi\Bundle\CouponBundle\DataFixtures\ORM\CouponData
  > loading Elcodi\Bundle\CartCouponBundle\DataFixtures\ORM\CartCouponData
  > loading Elcodi\Bundle\BannerBundle\DataFixtures\ORM\BannerData
  > loading Elcodi\Bundle\CurrencyBundle\DataFixtures\ORM\RatesData
  > loading Elcodi\Bundle\AttributeBundle\DataFixtures\ORM\ValueData
  > loading Elcodi\Bundle\ProductBundle\DataFixtures\ORM\VariantData
  > loading Elcodi\Bundle\RuleBundle\DataFixtures\ORM\RuleData
  > loading Elcodi\Bundle\RuleBundle\DataFixtures\ORM\RuleGroupData
  > loading Elcodi\Bundle\MenuBundle\DataFixtures\ORM\MenuData

You can see the store with php -S localhost:8000 -t web. And opening the browser on app_dev.php.

Screenshot 2014-08-28 18.57.30

The construction of the store is very simple and even though we can improve removing the nightmare of annotations, it seems like the power of the services is the real meat there:

    /**
     * Cart view
     *
     * @param FormView      $formView Form view
     * @param CartInterface $cart     Cart
     *
     * @return array
     *
     * @Route(
     *      path = "",
     *      name = "store_cart_view"
     * )
     * @Method("GET")
     * @Template
     *
     * @AnnotationEntity(
     *      class = {
     *          "factory" = "elcodi.cart_wrapper",
     *          "method" = "loadCart",
     *          "static" = false,
     *      },
     *      name = "cart"
     * )
     * @AnnotationForm(
     *      class = "store_cart_form_type_cart",
     *      name  = "formView",
     *      entity = "cart",
     * )
     */
    public function viewAction(
        FormView $formView,
        CartInterface $cart
    )
    {
        $relatedProducts = [];
 
        if ($cart->getCartLines()->count()) {
 
            $relatedProducts = $this
                ->get('store.product.service.product_collection_provider')
                ->getRelatedProducts($cart
                        ->getCartLines()
                        ->first()
                        ->getProduct()
                    , 3);
        }
 
        $cartCoupons = $this
            ->get('elcodi.cart_coupon_manager')
            ->getCartCoupons($cart);
 
        return [
            'cart'             => $cart,
            'cartcoupon'       => $cartCoupons,
            'form'             => $formView,
            'related_products' => $relatedProducts
        ];
    }

The annotations are basically boilerplate code for param converters and getting the form sorted out. All in all, it is spread out in various endpoints/links that do the work of the store. In the end is a clean simple store solution that does not get on the way. If you don’t understand or a component does not fit certain needs you can obliterate it by just unplugging the respective bundle. This latter of course can be further improved defining compiler passes in a respective package so that we can forget about bundles once and for all as it is the trend of modern developments.

The good thing is it is an open source project. I have seen various frameworks, sylius, vespolina, thelia, leaphly, akeneo and others, my advise is always to strive for simplicity and less strings attached. Readability of code is paramount because you cannot design with something you disagree with or cannot read very well. Just to name a few, vespolina is a bit dead, thelia is one unit and not exactly components, leaphly misses a bit of other components, and akeneo is more a backend, and sylius well it follows a similar approach to Elcodi and it has been for a bit longer but it is a bit hard to chew and challenging to implement features consistently with a different approach sometimes. All have pros and cons, but the idea of a good ecommerce is one does not get on the way, your app will be domain driven and so the components should just support your design not the other way around.

Next steps, homework, is to probably get rid of the annotations of the top layer in Elcodi bamboo and see how to make that more streamlined.

Hope you try elcodi!