CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

CakeDC Git Workflow - An Introduction

Its been almost a year now since we released, and then later open sourced, the CakeDC Git Workflow at CakeFest 2013 in San Francisco. Since then, we've had loads of feedback, and have also experienced ourselves how it's revolutionized the way we work on projects.

When we first set out to define the workflow we had some issues which we wanted to resolve. The main ones being broken staging servers due to unstable branches, an unorganized planning of QA on a build, repeated efforts when testing code which is constantly changing, and messy repositories with no clear organization.

Having these problems at hand, we wanted to accomplish a couple of goals:

  • Maintain a master branch which is reliable as a stable and versioned code base
  • Provide a staged code base that's stable and best represents the upcoming version
  • Allow new releases to be comprised of multiple milestones (or sprints)
  • Allow developers to create features from the code developed by others
  • Allow the next milestone to start while the QA process is still active on the previous
  • Allow QA to review code on an isolated branch without affecting the stage server
  • Isolate bug fixing on separate branches to avoid active development during QA
  • Provide a process which can be planned around and scheduled for QA and releases

So, we set out to define a process which would allow us to meet these goals, and help us deliver projects, without the pain of the managing that process itself.

Organize and coordinate

When working with a team of managers, developers and testers, it becomes very important to keep your sanity by organizing and coordinating efforts on projects. When these projects are large in size and scope, that can become a difficult task, especially if you don't have a clearly defined process at hand. And that doesn't just mean defining a series of steps to follow, but a process which sets the team's direction, and facilitates the desired results.

The CakeDC Git Workflow does just that, by setting out a clear path to follow, and key points in which members of the team are involved, from managers and developers, through to QA testers and client review. These break down as the following:

  • Development: After gathering requirements and planning out a milestone this is the first phase. During this time the code base is actively worked on, and can be considered unstable, in a bleeding edge state. Each ticket is developed on a feature branched from the develop branch. Peer review would take place on each feature branch before it reaches develop.
  • QA: Once the first phase of development is complete the QA process begins. This is performed on an isolated branch, so the next milestone could commence. The acceptance criteria defined from the requirements would be applied here. Any bugs found by the testers are fixed on an issue branched from the qa branch.
  • Review: Once testing has concluded and the code base is considered stable it's merged to the stage branch, and a milestone is tagged. The client or product manager would now review the results and provide feedback.
  • Release: Once the work completed in milestones constitutes a new version of the application the code from stage is merged to master, and a release is tagged.

Iterating through milestones

At the core of the workflow is the concept of milestone development. A milestone represents a deliverable, and is broken down into 3 phases: development, qa and staging. Each of these has a dedicated branch in the repository, which holds the work completed at each step of the process, and ensures that all work done on the project follows through these phases.

The milestone also helps organize the development team as well as the client (product owner), as the workflow keeps everyone in a cycle, which helps avoid feature creep and sets clear and coherent objectives and responsibilities at each point in the process.

Quality as the driving factor

At CakeDC our ultimate objective is to deliver the highest quality possible. This means that all members involved with a project need to provide the best possible to meet that common goal. We do it because we care about what we're building, and want the result to match our expectations as to what the "best" means in each case.

Our workflow keeps that philosophy in high regard, as its designed to protect the code base at all times from anything which doesn't meet the grade. Each phase acts as a barrier to avoid the master branch from being compromised.

Latest articles

CakePHP Query Builder

CakePHP’s  database Query Builder provides a simple to use fluent interface for creating and operating database queries. It can be used to accomplish most database operations in your application, and works on all supported database systems.
Query builders allow us to create database queries that work with any supported database, without having to worry about differences between SQL implementations in the different database systems.


The CakePHP query builder uses PDO parameter binding to protect your application against SQL injection attacks. There is no need to clean strings being passed as bindings.
For creating a Query object in CakePHP, the easiest way is using find() from a Table object. In CakePHP, queries are lazily evaluated,  which means that they are not evaluated until any of the following actions happens: the query is iterated through a foreach, it’s called first(), all(), toList(), toArray(). 
You can check all the SQL queries that CakePHP is generating, you just need to enable the Database Logging. See here:  https://book.cakephp.org/4/en/orm/database-basics.html#query-logging
Let’s do a few samples using the Query Builder - this is the ER diagram of the database that we will be using for the queries. We have Orders, ProductsUsers and Items that will store the products sold in each order and the quantity sold. Let’s create some queries using the Query Builder SQL Functions: https://book.cakephp.org/4/en/orm/query-builder.html#using-sql-functions. SQL Functions as part of the Query Builder are abstractions of  some commonly used SQL functions,  and they allow the ORM to choose the specific implementation your application needs based on the Database that is being used. For example, CONCAT is implemented in a different way in MySQL and Postgres, using concat() function will work if you use MySQL or Postgres   Imagine we want to build a report of the products sold, including the following:

  1. Display the product in the following format “Products.name - Products.description”.
  2. Total of products sold.
  3. Total of products in stock..
  4. Total amount on sold products.
First, we need to build the Query object using find(), this needs to be done from the Table. $query = Table->find();. We want to get a report of the products sold and the current stock. Initially, we would need to build a subquery using ItemsTable where the information related to the products sold is present.  Don’t forget to use identifier() when referencing any column. This will tell us  the items sold per product. 

$itemsQuery = $this->Items->find() ->where(['Items.product_id' => $query->identifier('Products.id')]);

Now, let’s build each query needed for the information required:
  1. Let’s start displaying the  product in the following format: “Products.name - Products.description”. Using concat() we could get it: $query->select([             'display_name' => $query->func()->concat([                 $query->identifier('Products.name'), ' - ',  $query->identifier('Products.description')]),         ]);
  2. Total of products sold. Using sum() we could get it, we just need to sum Items.quantity per each product,  this  is why we use $itemsQuery and then we sum the quantity per each product. $query->select([
      'quantity_sold' => $itemsQuery->select(['sum' => $itemsQuery->func()->sum($query->identifier('Items.quantity'))]),
    ]);
     
  3. To get the income, we need to multiply the Quantity of items  *  Price  and sum all of them.    $query->select([
              'income' => $itemsQuery->select(['sum' => $itemsQuery->func()->sum($query->newExpr('Items.quantity * Items.unit_price'))
                ])]);
     
  4. Stock. to get the stock we need to take advantage of the quantity_sold we just got in #2, and subtract it from the real quantity Products.quantity. For getting this, we would need to create a subquery in the FROM clause using the previous queries, and then subtract in the target query something like quantity - quantity_sold. $products = $query->cleanCopy()->select([
                'id' => 'ProductDetails.id',
                'price' => 'ProductDetails.price',
                'quantity' => 'ProductDetails.quantity',
                'display_name' => 'ProductDetails.displaye_name',
                'quantity_sold' => 'ProductDetails.quantity_sold',
                'income' => 'ProductDetails.income',
                'stock' => $query->newExpr('ProductDetails.quantity - ProductDetails.quantity_sold'),
            ])->from([
              'ProductDetails' => $query->cleanCopy()->select([
                    'id' => 'Products.id',
                    'price' => 'Products.price',
                    'quantity' => 'Products.quantity',
                    'display_name' => $query->func()->concat([$query->identifier('Products.name'), ' -  ', $query->identifier('Products.description')]),
                  'quantity_sold' => $itemsQuery->select(['sum' => $itemsQuery->func()->sum($query->identifier('Items.quantity'))]),
                  'income' => $itemsQuery->cleanCopy()->select(['sum' => $itemsQuery->func()->sum($query->newExpr('Items.quantity * Items.unit_price'))]),           ])
        ]);
     
Notice that we are using cleanCopy(), this is useful when the same Query object is affected previously by a select(), from() or where clauses, if you run this same example without using cleanCopy() you will get unexpected results.  The SQL query generated is this: SELECT ProductDetails.id AS id, ProductDetails.price AS price, ProductDetails.quantity AS quantity, ProductDetails.display_name AS display_name, ProductDetails.quantity_sold AS quantity_sold, ProductDetails.income AS income, (ProductDetails.quantity - ProductDetails.quantity_sold) AS stock FROM (SELECT Products.id AS id, Products.price AS price, Products.quantity AS quantity, (CONCAT(Products.name, :param0, Products.description)) AS display_name, (SELECT (SUM(Items.quantity)) AS SUM FROM items Items WHERE Items.product_id = (Products.id)) AS quantity_sold, (SELECT (SUM(Items.quantity * Items.unit_price)) AS SUM FROM items Items WHERE Items.product_id = (Products.id)) AS income FROM products Products) ProductDetails
CakePHP QueryBuilder gives a ton of possibilities to create queries with clean and robust code. So go play with it and enjoy!  

Are you ready for PHP 8?

In just two days we will get a new PHP release, PHP 8. It’s been almost  5 years since PHP 7 was born and now we are about to enjoy the new major version, which will include some breaking changes and performance improvements.   It comes with a lot of new features, including:  

  • PHP JIT
  • Union types
  • Named arguments
  • Attributes
  • Match expression
  • Constructor property promotion
  • New static return type
  • New mixed type
  • Throw expression
  • Inheritance with private methods
  • Weak maps
  • Allowing ::class on objects
  • Non-capturing catches
  • Trailing comma in parameter lists
  • Create DateTime objects from interface
  • New str_contains() function
  • New str_starts_with() and str_ends_with() functions
  • New fdiv() function
  • New get_debug_type() function
  • New get_resource_id() function
  • Abstract methods in traits improvements
  • Object implementation of token_get_all() 
  • Variable syntax tweaks
  • Type annotations for internal functions externals
  • ext-json always available
  We will explain some of these features in future posts.   Remember that PHP 7.4 active support will remain until November 2021, with security fixes until November 2022. PHP 7.3 active support is almost over and the team will provide security fixes for 1 more year. Finally, PHP 7.2 is already out of active support, and almost out of security fixes (in 5 days). If you want to check PHP versions and support you can go HERE.   So, Are you ready for PHP 8?  

The Making of a Marketing Plan

Listen, although 2020 felt like it lasted 25 years, it’s still hard to believe that we are wrapping up this roller coaster of 12 months.  As companies prepare for 2021, crossing their fingers and wishing for a better Q1… it is important to start thinking about marketing strategies and plans for the next year. Without ideas and a solid goal for your company, it is very unlikely that things will change.   Reasons that making a marketing plan is important:  1. It organizes your goals and provides clear plans of actions to achieve them  2. It keeps everyone on track and on the same page  3. Promotes motivation and accountability
  I know making a marketing plan can sound time consuming, and a little complex, but it doesn’t have to be! I am going to walk you through the steps of making clear cut goals and plans for 2021 (with some actual examples!).  

1. Brainstorming

Our team is great at making notes of things that need attention, whether it's good or bad. We keep open lines of communication on things that are going well, or may need some extra work. It is important for everything to bring their ideas together, no matter how big or small.  I suggest keeping a notepad with things / ideas you have for your team moving forward, and organize them in a way to present to your marketing team.  

2. Team meeting

Now it is time for a group session to compare ideas, talk about what should be the priorities and get approval on anything needed. These meetings are super beneficial, because it is always refreshing to see if your team’s ideas mimic yours, or perhaps they even have some additional great ideas.   

3. Start building your plan

There are ample amounts of templates and checklists that you can find online to ensure that you’re including important information on your strategy plan. Some of the things I recommend including are:
Of course your main table of contents - easy to view for your team     Company mission - WHO ARE YOU?  
  Product Overview - what are you offering your clients?     Goals / Challenges - we all have them, don’t be shy  

Target market - Who are you working for?       Expansion Plan - how will you make it to the next level?   Upcoming Actions - Making a clear timeline for the next year. It is important to make the timeline obtainable... in other words, don’t make goals that are impossible to meet.   Other important topics include additional small actions, goal timeline, campaign calendars, advertising outlets, social media platforms (and the importance, utilization for each one).  

So making a powerpoint or pdf presentation for your team will allow all of the ideas and goals  to come together and be available in one place. I am a big checklist type of person, so in addition to my marketing plan, I always create a document.   

4. Create a spreadsheet

A spreadsheet doesn't have to be fancy, but it holds the team accountable, and we are able to make notes so that we can track the status of certain actions. This also helps me stay on track, and know what actions need to be executed next.    Something like this for internal works just fine:  
 

5. Budget & Execution 

It is extremely important that your team supports the marketing efforts. It is also important to know what your marketing budget will allow. Will you have additional funds for new goals? Will you need to reduce funds on other outlets to allow for new ideas? These are things that will need to be discussed with your financial department.   This is a good reason to create a marketing metrics / budget spreadsheet to track these items. I will share my examples on this in a future blog.    So, once your team is on the same page, and they have clear goals…. IT’S GO TIME. Start working on your plan of actions and preparing to let them fly. For us, some of our goals will take some prep work, so we are gearing up in Q4. 
  Hopefully, you have helpful ideas that you implement on your marketing plan… maybe it’s something I haven’t thought of (i’d love to hear yours! Email me - amanda.goff@cakedc.com). Either way, I wish everyone good luck on their strategies, and may all of your goals come true in 2021. If you’d like more insight on any of the ideas I have included, feel free to reach out, I’d be happy to chat!   

We Bake with CakePHP