Nov06

Tagged in:Comments:

google cloud run 503 “service unavailable”

503 google cloud run error

Recently I have been deploying PHP service on a google cloud run and I have encountered a 503 service unavailable error.

 

Problem

On the first execution, there is a 503 error, however, any other request after the first one works fine.

 

Solution

After investigation, I have seen that if you are using an image from “webdevops/php-apache” then you will see this error.

I have replaced the image with the original version “php:7.4-apache”

This has resolved the issue and I do not see the initial 503 errors anymore.

Apr12

Tagged in:, , , , Comments:

Sonata Admin Bundle nested list or has child list

Post (parent) to display comments (child) list.

Creating list of rows on sonata admin bundle is fairly easily with there documentation. But when you want to go bit advance on creating sub list of parent entity, then you would be scratching your head.  Luckily this post will help you overcome this very easily.

Assuming you already have PostAdmin and CommentAdmin class to display list individually, if you don’t then please create them first.

We will tell our child class, who is his father (parent). 

// .. YourBundle/Admin/CommentAdmin.php

class CommentAdmin extends Admin
{
    protected $parentAssociationMapping = 'post'; 
    ...
}

Now we can create services for parent and child, if you already have created the services, then please make sure you add call method on parent service. 

// .. service.yml

admin.comment:
    class: Sonata\YourBundle\Admin\CommentAdmin
    arguments: [~, Sonata\YourBundle\Entity\Comment,~]
    tags:
        - {name: sonata.admin, manager_type: orm, group: "Content"}
admin.post:
    class: Sonata\YourBundle\Admin\PostAdmin
    arguments: [~, Sonata\YourBundle\Entity\Post, ~]
    tags:
        - {name: sonata.admin, manager_type: orm, group: "Content"}
    calls:
        - [addChild, ['@admin.comment']]

That’s it!

We can now add links on post list page, but you can add link on any page as you like. 

Create template to add link

// ..YourBundle/Resources/views/CRUD/post_comments.html.twig

<a class="btn btn-sm btn-default" href="{{ path('OUR_NEW_CHILD_ROUTE_ID', {'id': object.id }) }}">Comments</a>

Replace OUR_NEW_CHILD_ROUTE_ID with comment list route id, which you can find it with following command line.

$ php app/console debug:route

Now we are ready to add link on post list page for each post. 

// ..YourBundle/Admin/PostAdmin.php

class PostAdmin extends Admin
{
    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper->add('_action', 'actions', array(
            'actions' => array(
                'show' => array(),
                'edit' => array(),
                'comments' => array('template' => 'YourBundle:CRUD:post_comments.html.twig')
            )
        ))
    }
}

That’s it you are done. Now all post are linked properly with its child comments as oneToMany relationship. 

SonataAdminBundle has so much more to offer, which can be hidden if you are new to it, but once you learn it. Then creating admin area would take you few days or less then week depending on the size of your application. 

Feb16

Tagged in:Comments:

Angular2 ngFor skip first index

Simply use angular2 pipe slice by appending at the end of array.

<li *ngFor="#user of users | slice:1">
  {{ user.name }} is {{ user.age }} years old.
</li>

Feb02

Tagged in:, , , , , Comments:

Symfony 3 should I upgrade or stay with Symfony 2

Everyone is excited about Symfony 3, including myself 🙂

Symfony 3 or Symfony 2?

Symfony 2.8 is exactly same as Symfony 3. But wait, then what’s the difference?

Symfony 3 mostly have new directory structure for logs, cache and console. Also all the previous deprecated functions are removed.

Should I upgrade then, if its same?

No!!!, Even tho it is exactly same, but knowing all the deprecated functions are removed on Symfony 3, you should ask yourself.

Are you going to be using third party bundles?

and thous bundles are update-to-date with Symfony 3. Most likely you will get the answer no.

having third party bundles on Symfony 3 will break your application, If it was using any of the deprecated function.

Soon we can upgrade when everyone upgrades their bundles.

Updated – Wed 17 Feb

You can also check your vendor packages, if they are using any old deprecated functions, check following link for more details – http://symfony.com/blog/paving-the-way-for-symfony-3-with-the-deprecation-detector-tool

Complete list of changes

Jan31

Tagged in:, , , , , Comments:

Symfony3 Auto Wiring – Auto Creating Dependency Services

Previously if you ever had dependency for your object, you had to make sure the names for dependency services are correctly passed down to your new service before you can start using it.

Since Symfony 2.8 which is official exact version of Symfony 3 (removing all the deprecated functions).

Now you can create services without worrying about dependency injection services with auto wiring feature. The key feature in auto wiring is, if one of your dependency injection service does not exist, then it will auto create it and inject it.

Let’s assume we have following object, which needs to be created as service.

namespace AppBundle\Service;

use AppBundle\Service\House;

class Room
{
    private $house;

    public function __construct(House $house)
    {
        $this->house = $house;
    }
}

Old way creating service

services:
    house:
        class: AppBundle\Service\House

    room:
        class: AppBundle\Service\Room
        arguments:
            - @house

New way with auto wiring

services:
    room:
        class: AppBundle\Service\Room
        autowire: true

The above example is very simple. Now imagine you have 5 or even 6 different dependency injections, you would have to waste time on getting each dependency service names and on top, if you later on decided to change the or remove dependency from your object, then you have to update services as well. With auto wiring you don’t have to worry about anything, it worries for you.

What about Performance?

It is exactly as same as before. Compiler builds and save everything in cache, just like before.

Jan28

Tagged in:Comments:

Change input name of the form fields in Symfony3

Remove form type name from the form

Sometimes we need to integrate third party application or form, which requires us to remove any array type form names. 

Problem

Normal form will create FormTypeName[fieldName]

<input type="text" value="" name="formTypeName[fieldName]">

Our final outcome should look like field name only without any form type name.

<input type="text" value="" name="fieldName">

Solution 

Create the form using createNamed method.

$form = $this->get('form.factory')->createNamed(null, new MyFormType(), $dataObject, $formOptions);

When you pass first argument as null, it will remove form type name and make fields as field name only.

Solution 2

You can also change your formType and return blockPrefix null.

class MyFormType extends AbstractType
{
    ...

    /**
     * This will remove formTypeName from the form
     * @return null
     */
    public function getBlockPrefix() {
        return null;
    }
}

I recommend first solution.

Jan28

Tagged in:Comments:

Symfony3 Container Dependency Injection

It’s 2016, you can use trait which will help you extend same class with multiple libraries.

I keep seeing container class get extended into another class, which then extends to another, before you know it you have extended 5 different classes just to use libraries.

What if you can include 5 different libraries into 1 object without extending? Well you can use it with php5.4 trait feature.

Container dependency injection trait class

    
    namespace iBasit\ToolsBundle\Utils\Lib;
    
    use Doctrine\Bundle\DoctrineBundle\Registry;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    
    trait Container
    {
        private $container;
    
        public function setContainer (ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        /**
         * Shortcut to return the Doctrine Registry service.
         *
         * @return Registry
         *
         * @throws \LogicException If DoctrineBundle is not available
         */
        protected function getDoctrine()
        {
            if (!$this->container->has('doctrine')) {
                throw new \LogicException('The DoctrineBundle is not registered in your application.');
            }
    
            return $this->container->get('doctrine');
        }
    
        /**
         * Get a user from the Security Token Storage.
         *
         * @return mixed
         *
         * @throws \LogicException If SecurityBundle is not available
         *
         * @see TokenInterface::getUser()
         */
        protected function getUser()
        {
            if (!$this->container->has('security.token_storage')) {
                throw new \LogicException('The SecurityBundle is not registered in your application.');
            }
    
            if (null === $token = $this->container->get('security.token_storage')->getToken()) {
                return;
            }
    
            if (!is_object($user = $token->getUser())) {
                // e.g. anonymous authentication
                return;
            }
    
            return $user;
        }
    
        /**
         * Returns true if the service id is defined.
         *
         * @param string $id The service id
         *
         * @return bool true if the service id is defined, false otherwise
         */
        protected function has ($id)
        {
            return $this->container->has($id);
        }
    
        /**
         * Gets a container service by its id.
         *
         * @param string $id The service id
         *
         * @return object The service
         */
        protected function get ($id)
        {
            if ('request' === $id)
            {
                @trigger_error('The "request" service is deprecated and will be removed in 3.0. Add a typehint for Symfony\\Component\\HttpFoundation\\Request to your controller parameters to retrieve the request instead.', E_USER_DEPRECATED);
            }
    
            return $this->container->get($id);
        }
    
        /**
         * Gets a container configuration parameter by its name.
         *
         * @param string $name The parameter name
         *
         * @return mixed
         */
        protected function getParameter ($name)
        {
            return $this->container->getParameter($name);
        }
    }

Your custom object, which will be service.

    namespace AppBundle\Utils;
    
    use iBasit\ToolsBundle\Utils\Lib\Container;
    
    class myObject
    {
        use Container;
    }

Your object service settings

     myObject: 
            class: AppBundle\Utils\myObject
            calls:
                - [setContainer, ["@service_container"]]

Call your service in controller

    $myObject = $this->get('myObject');

Jul11

Tagged in:Comments:

Quick Setup Mailgun with CloudFlare + Gmail

Mailgun Setup

  • Create a Mailgun account
  • Add your domain name (no www)
    domain.com
  • Keep the page open and open a new tab to CloudFlare

Cloudflare

  • Choose your site and select DNS Settings
  • Add the two Text records
  • Add the CNAME record
    • Make sure the cloudflare cloud is gray and not orange/active
  • Add the two MX records
    • Name domain.com (no www)
    • Mail handled by mxa.mailgun.org or mxb.mailgun.org

Back at Mailgun

  • Click add
    • Click Check DNS Records Now
  • It’ll tell you once it detects the updated DNS records

Email Forwarding

  • From Mailgun, choose Routes
  • Create Your First Route
  • Priority 10
  • Filter Expression This is where you list the email address you want to forward to gmail
    match_recipient("you@domain.com")
  • Actions This is the gmail address you want to receive your mail
    forward("me@gmail.com")
  • Description Name it something so you remember what it’s for

Use Gmail to send mail from your domain

  • Log in to Gmail and go to settings
  • Go to Accounts and Import
  • Go to Send mail as and select add another email you own
    • name: Anything you want
    • email address: name@domain.com (this should be the email you set up in the steps before)
    • Leave treat as an alias checked
    • Click Next Step
    • For the following info you’ll need to login to mailgun and use the info under Domain Information
    • SMTP Server Use SMTP Hostname from Mailgun
    • Username Use Default SMTP Login from Mailgun
    • Password Use Default Password from Mailgun
    • Leave Secured connection using TLS selected
    • Click add account
  • Once it’s verified you should be able to compose emails and list your new email in the from line so nobody needs to know it’s coming from your personal gmail account.

Jan05

Tagged in:, , , , , , , Comments:

Setup Environment UAT + LIVE – GITHUB (Auto Deploy)

We will cover UAT and Live environments and exclude developer environment.

DEV environment for developer to code and test, before he push his commits to remote repository (github.com),  which will be auto deploy to UAT environment for everyone to test with other developers changes. Note – we wont be covering DEV environment.

UAT environment for testing the site and getting ready to push to live environment after we think all the bugs are fixed.

Live environment to have the latest version of the website.
(more…)

Jan04

Tagged in:, , , , , Comments:

WordPress FIX HTML parsing issue – for Developers

It’s really annoying and waste loads of hours trying to fix how can one show example of php code, while still use visual editor for quick snapshots or fancy tools of tinyMCE and able to show color coding examples using google prettify.
(more…)

Older posts

Back to top