CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

Best CakePHP Plugins

Members of our team had the privilege of helping with CakeFest 2020 this year. One added virtual feature was the giveaways from CakePHP, these were done in the form of fastest-to-answer, trivia, or participation (random draw). 

One of the giveaway games was to share your favorite CakePHP plugin but like, how do we only pick one, right? Anyway… There was a lot of participation in this giveaway! A few people even named our CakeDC Users plugin as their favorite *cue blushing face*. But in all seriousness, I thought it would be a good idea to share with you some of the plugins that were named most useful/helpful by CakeFest attendees this year….

 

Like I mentioned, the CakeDC users Plugin: https://github.com/CakeDC/users

Queue Plugin: https://github.com/dereuromark/cakephp-queue

Bake: https://github.com/cakephp/bake

DataTables: https://github.com/fheider/cakephp-datatables

CakePHP-tools: https://github.com/dereuromark/cakephp-tools

Authentication: https://github.com/cakephp/authentication

CakePHP-image: https://github.com/josbeir/cakephp-image

Fixturize: https://github.com/lorenzo/cakephp-fixturize

CakePHP File-Storage: https://github.com/burzum/cakephp-file-storage

Crud: https://github.com/FriendsOfCake/crud

IDE Helper: https://github.com/dereuromark/cakephp-ide-helper

Asset-Compress: https://github.com/markstory/asset_compress

CakePHP Debug Kit: https://github.com/cakephp/debug_kit

Plum-Search: https://github.com/skie/plum_search

CakePHP API: https://github.com/cakedc/cakephp-api/

Bootstrap UI: https://github.com/friendsofcake/bootstrap-ui

Trash: https://github.com/usemuffin/trash

 

You can check out the full list of CakePHP Plugins at Plugins.CakePHP.org

Have you been utilizing these tools? If not, it may be a good idea to start… while each of these serve their own purpose, using all of them can make your baking process a lot easier. 

 

Perhaps your favorite didn’t make this list? Tell us about it… email HERE. Or, tweet us @CakeDC, @CakePHP

Thanks for baking!

 

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