CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

Dependency Injection with CakePHP

Dependency Injection is some of the bigger buzzwords in PHP frameworks.  Historically, CakePHP application logic didn’t support that, until the version 4.2 was released last December. You can do that on your own and have a few plugins for that. This is a new chapter of the framework, let's see how to bake it.  

Use Case

First, let’s talk about a classic Use case on real applications. Our application will include an address form, such as the shipping address for an online order, or provide information about User, Company, etc. Autocomplete can help users supply the details.   We will use the Geocoding API from Google Maps Platform, making a HTTP request for API with json output format and address parameter: https://maps.googleapis.com/maps/api/geocode/json?address=89104&key=****** And here we go, we will get this result:  

Baking a Address Service

After seeing the Use case, all we need on our backend is to make a HTTP request for API and return the JSON result for the frontend to populate related fields.   1. First, let’s exposing our application for accept “.json” requests:   2. Now, we can bake a Address Controller and let’s request an empty result: $ ./bin/cake bake controller Address --actions index   Now our app requests /address.json will return an empty JSON.   3. Let’s bake (manually) the Address Service:   Basically I’m using Cake\Http\Client to make the API request. Also I read Geocode.key from Cake\Core\Configure, we don't want to expose our key on public requests (add the key on config/boostrap.php).   4. Let’s rewrite our Controller:   5. Finally, let’s add our Service on Application.php:   That’s all bakers! Now our endpoint /address.json will support query parameters and return the result of the API request.  

The cost of shiny

I’m here selling an idea and I don't start with the cons. Unfortunately, the Dependency Injection container is an experimental feature that is not API stable yet.  The support is a bit limited, CakePHP will inject services into: constructors of Controllers and Commands and Controller actions. The core team hopefully stabilizes the feature on version 4.3, or at most 4.4. They need your help testing and finding cases, and feedback always is welcome.   I hope this post can be useful for you and your projects.  See you next time!  

Planning For Your Upgrade

Having a successful upgrade implies not only upgrading the code itself, but also identifying the different tasks that will be part of the Upgrade Plan. Making a good plan for an upgrade requires identifying the current status of the application. A good plan is based upon clear, well-defined, and easily understood objectives.   After years of experience with CakeDC making upgrades, migrating applications from CakePHP 1 to CakePHP 4 in all possible combinations, we have noticed there are a set of elements or characteristics that are useful to evaluate and identify before starting the upgrade. Having a clear understanding of these elements will be helpful to define the different tasks that will be included in the Upgrade Plan, and reduce any risk while upgrading and delivering.   Imagine that you want to run a marathon - but before starting any of the thousands of plans you can find on the internet about “How to run a Marathon”, you must know where you are. You could ask yourself:  How many miles per week are you currently running? What is the base training needed to start this program? What is the distance of your longest run in the past 3 weeks? How many days per week do you have available to exercise?, etc. This will help you to choose the plan that better fits you. It’s important to identify where you are, where you want to get and how to get where you want.    Wondering how  to evaluate where you are for the Upgrade? Evaluate the status of your application. You could consider the following points as reference:

  • What is your current CakePHP version? 
  • Identify the weaknesses and the strength of the current code by making a code review.
  • Identify the versions of the packages, plugins, libraries that your application is using. 
  • If you are using CakePHP Third Party plugins, figure out if those plugins have already been upgraded.
  • Identify any third party integration and how the upgrade could affect it. 
  • What is the unit test coverage, if any? 
  • Is there any existing documentation?
  • Is there any custom change in the CakePHP core? (I hope there is not!)
  The complexity, time, cost, and resources required to upgrade your application will depend on the status of your application. Once you know where you are, it’s the time to plan how to get where you want.  Let’s talk about this in a future article. In case you are looking for some guidance on preparing your Upgrade Plan, don’t hesitate to contact us, we could help you to identify your current status, define the plan and execute the whole plan for you. We can also work together with your team on the upgrade, helping them understand the upgraded codebase so you can maintain the project with your own team as you did before.  

Modifying Requests Like A Chef

Since the version 2.x of CakePHP has a requests and response objects, they are provided an abstraction around HTTP Requests and responses. If you are not familiar with CakePHP, it’s a common step when you bake and use $this->request->data instead of $_POST. Most of the time, we need to modify and append values on our Request data. This can be an identifier of logged user or values for any fields. In many situations, implementations will like this: Data can be modified easily - you just need to call withData or withParsedBody method and after set the Request  (you can also modify the query calling withQueryParams): Both implementations will generate the same value, but if you have a keen eye, you will see that the second implementation is more clear. Also, our Request has these values on data. This information can be useful when you use Components from Plugins, as they will expect the values on Requests.   That’s all bakers! I hope this content is useful for you and will improve your requests!  

Where you SHOULD be marketing your bus...

Marketing is an essential part of your business’ success. I don’t just say this because I myself am a marketing connoisseur... or maybe I do. But either way, I’m going to shoot you some quick knowledge about getting your name out there... specifically into the cyber world.   

Social media 

Branding is very important here. This will be another blog for another time... but having a uniform look, format, font, etc will help you look professional and stand out. Some of the platforms I work with for our company is Facebook, Instagram, Twitter. In our industry, Twitter is our cake and frosting (see what I did there). Most developers have a Twitter and use this to interact with other developers, frameworks, and companies. Having a company page allows you to engage with your followers, have conversations, and build relationships. Remember, you need to be posting things that are important for those who follow you to see, and when they reach out, be ready to respond.  For business contacts and networking, I am a big fan of LinkedIn. This platform is an easy way to connect and search for others in your field. Also, it's a good way to find people looking for your specific services. Very business. Very professional.  You definitely need to get to know your audience. Tracking your social analytics will tell you where you stand out most. Then, you utilize that information!  

Ads

 I’m a fan of Google Ads. While I know that the idea of paid advertising isn’t ideal or financially possible for everyone, there are other options. Keeping up with your SEO, or search engine optimization, will help with organic ads. Organic ads is a fancy way of saying free clicks, or free adveritsing. When people are searching Google for services or phrases pertaining to your business, then your site will show in the results. Obviously if you pay for ads, you can manually add phrases and terms that may be searched for... and these are called keywords. I think Google Ads pointers may be a good blog for me to share in the future *makes mental note*.    Speaking of Google, make sure your “my Google business” account is up to date, otherwise you will literally NEVER show up on the search engine. Even when someone specifically searches for you or your company.   

Email Marketing

We must be careful here. Gone are the days of spam emailing... and cold calling? Please don’t. I’d say most people are ready to get restraining orders against telemarketers. Just me?  However, if you have specific things (sales, offers, important news) to share with your customer base, then by all means - onward. At least emails can be ignored if they are unwanted. If you want your email to be opened, make sure that you are offering your recipients something worth clicking (specials. Giveaways. Etc.). A good platform to help you with this is MailChimp, but there are soo many ways to generate these emails, and many even offer pre-made templates... so no excuses.   

Newsletters

Similar to email marketing, there are newsletters. The difference here is that the people who will be receiving your monthly (most likely) newsletter are only those that have chosen to. “Subscribers” sign up to receive these emails. Usually, these aren’t offers of sales, but rather news, events, tips etc. You can get an idea of what I mean by checking out the CakePHP Newsletter archives. 
  So let's close with some quick facts: Newspaper advertising? Out Telemarketing? Out  Print? Maybe  Billboards? If the price is right and you are local to certain areas. International companies, like CakeDC do not benefit from this type of print, unless we could put one in every city around the world. I think that would blow my marketing budget pretty quick.  If you are a freelancer, I definitely suggest Fiverr. Let people find you. Essentially you get quality leads for free.    All of these marketing platforms and items need to be explained in deeper detail, so if you have any questions feel free to reach out to me!  

Benefits Of Upgrading

Let’s talk more about upgrading your CakePHP application. In last week’s blog, we talked about why you should hire externally for all of your upgrade needs. You may have been thinking… but why would I (or my company) even need to spend the time, effort, and money on upgrading our projects. Well… for many reasons. You need better security, compatibility, functionality.  You’ve seen our posts, you know what needs to be done. Your old CakePHP application needs to be updated.  I want to remind you about some of the benefits that there is to upgrading.   

SECURITY

The more maintained a CakePHP version is, the more security it can provide. This not only protects the projects themselves, but can also give you peace of mind knowing that the latest versions will be functional a lot longer than say CakePHP 2.x. And of course, the latest releases fix a number of security issues. No company wants to offer quality services to their customers,  and end up with a security breach that was out of their control. It is extremely important to get ahead of the security issues on the front end. Be proactive, and you won’t have to be reactive.  The biggest concern is that many hosting providers are abolishing old PHP branches, essentially overnight. This is why it is important to be aware of when to migrate/upgrade and do it before it is too late. You can see a list of the end of life date for each unsupported branch of PHP HERE.   

PERFORMANCE

CakePHP 4 follows the latest conventions, helping your application run faster and smoother. Old sites / applications run slow… that is no secret. I promise you one thing, today’s Google searcher will not think twice to do a different search if the site is lagging (ain’t nobody got time for that).  Also, migrating to a current PHP release over 5.6 and using the new ORM, could lead to improvements over 50%. So I mean, win-win.    If you are wondering about your performance, speed, or  which versions of PHP you are running on, you can use tools like Pingdom - https://tools.pingdom.com/ or Google Chrome Devtools - https://developers.google.com/web/tools/chrome-devtools.  

SCALABILITY & TOOLS

CakePHP 4 is shipped with best practices to streamline horizontal scaling and deployment into containers. As new tools and plugins are released, they may only be compatible with the latest versions. Currently, there are over 900 updated plugins, see here: https://plugins.cakephp.org/, covering from background job processing, image processing, CMS, file upload and management, cache, and more. This provides more features and results in developers WANTING to use and work with the framework. 

Of course there is a long list of additional benefits, but these are some of the most important. 2021 seems to be turning into the year of upgrades. Don’t get left behind!

Why You Should NOT Upgrade Your CakePH...

There are many reasons that CakePHP recommends upgrading. But should you, really? Contrary to what you would expect, I am here to tell you that maybe you should not upgrade your application. WHAAAAAAT? I said what I said. The answer is no… but yes, the application should be upgraded. What do I mean? I mean that SOMEONE should upgrade to CakePHP 4, but that someone should not necessarily be you or your team.  Let’s be real… upgrading takes time. It will take priority and focus. Is extra time something your team has? Usually not. This is why I suggest outsourcing for any upgrading.   

Prioritization

Perhaps your team is extremely busy with internal work, and you just can't fathom the idea of utilizing your resources on a time consuming project, such as upgrading. I would imagine that it’s not an easy task to go to your CEO / IT manager and explain why you were unable to meet a deadline due to unexpected complications during a migration. This is one reason that it would be beneficial to hire a team. Then, you are able to keep your team working on tasks that actually add value to your business, providing the best service for your customers…. What I am trying to say is let us doing the boring tasks of upgrading    

No Training / New Skills

Even if a junior level developer was tasked with upgrading one or all of the company's projects, why pay for their time when it is not advancing them in any way? During an upgrade, the tedious work is not resulting in any new skills for the developer. There is no training, or development skills to be learned during an upgrade process. This is a huge factor for a lot of CakeDC’s upgrade clients. The money and time spent for doing these actions internally does not provide long term gains. For us - we need to know the ins and outs of upgrading, and we can prioritize these items for our client work. We actually learn from each migration that we do and we can utilize those skills in future upgrades.    

Hire A Team

Obviously, I am going to tell you to hire CakeDC for upgrading, but truthfully that is because we have done many upgrades (and learned the mistakes / solutions to many problems that occur) and have well experienced developers in most time zones  This allows us to have great relationships with our clients, and stay in constant contact. The biggest benefit is that hiring externally will not disrupt your routine, and it gets the upgrading / migration done a lot quicker. We are all tempted with distractions, prioritized work, etc. Save time, and probably money by looking into a company to do the work for you, and I promise you will thank me later.    Another shameless plug: see our development service details HERE. Need more reason to upgrade? Check back to read next week’s blog for the many benefits.   

CakeFest 2021 Decisions

Well… 2021 is already feeling a little 2020ish to me, what about you? While I had high hopes of things being back to normal as far as travel, events, etc. It seems as though we still have a ways to go in that department.  

Difficult Decisions

Our events are no exception to this. While virtual CakeFest was a great success, I think that the CakePHP team, as well as the community had hoped for an in-person event… sooner, rather than later. Everyone is missing the adventures and camaraderie that physical meet-ups bring. Unfortunately, we may be waiting a little longer. The team couldn’t stand to make the tough call on the event alone, without consulting with the community.  

The Community Has Spoken

So, CakePHP took to the polls. The question was posted via social media, and included in the January newsletter: Should CakeFest be virtual or in-person (Los Angeles, specifically)? The consensus was no surprise, and 85%+ of bakers voted for a virtual event this year. One follower mentioned that he “wasn’t ready to risk the event not happening at all, so a virtual event is better than no event”. I couldn’t agree more.    A virtual conference was uncharted territory for CakeFest planners and attendees, but in my opinion.. it came together so wonderfully, that it is hard to be disappointed that it will be happening again. So here’s to gathering once again from the comfort of your own space, and hoping that everyone remembers to have their cake ready! Mark Story can even (virtually) cut it for you if you prefer.   The call for sponsors and speakers will be opening soon, so make sure to contact the CakePHP / CakeFest team with any questions you may have ahead of time.  Planning on attending? We would love to hear from you! What are some topics that you would like covered in the workshops or talks? EMAIL US HERE.   *Digital hug*  

Baking Smarter, Not Harder in 2021

After the year we had… our new motto should be work smarter, not harder, in 2021? Am I right? Luckily, CakePHP community and core members are extremely helpful and constantly working to make baking easier. Here are some things that will assist you with your CakePHP projects….

Plugins:

I recently wrote a blog featuring some of the best (voted by the community) CakePHP plugins - you can see it HERE. A full catalogue of CakePHP plugins is available at https://plugins.cakephp.org. It is no secret that plugins are essential for developers. CakeDC has a few of our own as well, you can get details at:  https://www.cakedc.com/plugins. The good news is, if you don’t see one, but have a great idea, you can build and release your own! To learn more about this process, Jose Gonzalez explains it in his CakeFest 2021 Talk.     Lots of other videos / talks / tutorials are located in the CakePHP Youtube channel as well.
 

Tools:

If you follow us on social media, we highlight a lot of tools released from the community.  One of the most popular is the debugging tool: https://book.cakephp.org/4/en/development/debugging.html A commonly used one is to help updating your composer.json while upgrading https://toolbox.dereuromark.de/utilities/upgrade   You can see more on THIS cakePHP tools list from Dereuromark!
 

Support:

I talk about support channels a lot… because well… what is open source without them? Every time I take a virtual stroll to the slack channels, I am amazed at the participation and interaction between community members. It’s like having your own development team available anytime you need them. Rest assured that if you have an issue that's causing a blocker, someone in the chat will (most likely) have a solution. A full list of support channels was listed in our last blog, but if you missed it, here you go: Discourse forum: https://discourse.cakephp.org Stack Overflow: https://stackoverflow.com/tags/cakephp IRC: https://kiwiirc.com/nextclient/irc.freenode.net#cakephp Slack: https://cakesf.herokuapp.com
 

The Book:

If you’re a veteran baker, you already know this. However, this wouldn't be a helpful blog without mentioning the all mighty book… The CakePHP bookThis is where you should start on your cake journey… read it… read it again. Then, reference back to it when you need it. There is an average of 46k users utilizing the book monthly (184k sessions). That should speak for itself.
 

Newsletter:

The CakePHP team releases a newsletter each month. This is a good resource if you’re looking to catch up on a month’s worth of news in one place.  Usually included is: releases, helpful tools, training/event dates, specials, surveys, and more.  You can see previous newsletters & subscribe HERE.   I will close this with a shameless plug: if you want to work a whole lot smarter this year, let someone else do the work for you. Check out all of the CakeDC services offered at cakedc.com/services.    Here’s to 2021 being a lot easier… more peaceful… and tasty!  

Saying Goodbye To 2020 Is A Piece of Cake

I never thought that I would be so excited to say… the year is coming to an end. What a year it has been. Let’s focus on some good things that happened for us this year.

CakePHP Community

Our team worked as closely as ever with the CakePHP community. We have hosted training sessions and multiple online meetups - for which we had consistent attendance and involvement. We have enjoyed getting to know each baker that attends and interacts with us. It was a great year for releases, too. If you follow the social media pages, you’re up to date with all of the new features and tools that are released in real time. Not to mention new and updated plugins. You can see all of the latest releases in the BAKERY.  

CakeFest

While we usually get to travel to some amazing city in the world and meet with the attendees in person, clearly that was not going to be an option this year. For the first time ever, the event was held virtually. Being so involved, and responsible for the success of the event, was stressful and frightening to say the least, but alas…it came together wonderfully.  We were able to have attendees that may not have been able to join us otherwise, and the participation was unprecedented. I am so thankful for the wonderful sponsors, speakers, attendees, and contributors that made the event possible.  In case you didn’t know, all of the CakeFest 2020 videos have been released. You can view them in the CakeFest archive, or on the CakePHP Youtube channel. Don’t forget to subscribe to the channel, and I will tell you why later.    Now… what can be expected in 2021? LOTS!

Increased Involvement

We want to expand the kitchen, if you will. We have an amazing group of core developers, and they would love to have more involvement from the community. If you’ve ever thought about contributing and getting involved, there are many options, you can check out details HERE.   

More documentation / blogs

Speaking of getting more people involved, this will include blogging. We have so many great plugins, but maybe not enough documentation to support the training on them. The core team is on board and we will all be working hard to provide more documentation for the framework. In fact, we even some some community members that have already volunteered to provide more blog contributions to the bakery. Maybe you’d like to as well?!  

Video Tutorials

One suggestion that we get consistently is that we need more video tutorials. We agree! We are going to be updating our YouTube channel and will hopefully be adding more video tutorials as soon as Q1. We will also make sure that training sessions / meetups will be available to subscribers for playback. We would love to hear your suggestions for content, you can email us at community@cakephp.org and let us know what you’d like to see. 
 

Support

As always, CakePHP has many support channels, and this will not change in the new year. In fact, we plan to make it even easier to connect with other bakers.   Here are some current available support options: Discourse forum: https://discourse.cakephp.org Stack Overflow: https://stackoverflow.com/tags/cakephp IRC: https://kiwiirc.com/nextclient/irc.freenode.net#cakephp Slack: https://cakesf.herokuapp.com
  Want to have your opinion heard? The core team wants to know what you want for CakePHP 5. Please take a moment and fill out a quick SURVEY to let them know.    We can’t wait to bake with you in 2021. Wishing you all a happy holiday season and a very happy new year!  

Baking With Attributes

Tasting the cake with attributes

Attributes is a declarative way to pass information about the behaviors of various elements like classes, methods, properties, and even method parameters in your programs. In fact, attributes are used for adding metadata to existing code, and could be used as a way to reduce visual debt, and this way simplifies how code looks like.  

Defining an attribute

An attribute is simply an object whose class inherits from the Attribute class. However, attributes are not used in the same way as a typical object. They often add some additional semantics about the class or method, or to toggle behavior on or off. Some attributes specify functionality. For example, an attribute may contain a method that defines security behavior.  

Declaring Attributes

The attribute itself may be declared as a class. This is validated only when the attribute is fetched, and not immediately when the code is parsed. A PHP attribute is a class, declared with #[Attribute] attribute. In the following example we define an attribute class which allows us to specify what methods are allowed for controller actions.     Take note that in PHP 8 you can declare properties directly in class constructors, which is really handy for data classes.
 

Consuming reflection API to define meta behaviors

Just defined attributes have not added new code logic. To add new behavior we should implement it. Attributes could be fetched using the reflection API. PHP engine knows about attributes but does not instantiate it’s classes, so we have to do it ourselves. Reflection provides getAttributes() methods to fetch a list of associated attributes.   The following  example shows how we can add permissions checks for controller actions using attributes. In this example, the code is stored in beforeFilter of the controller class itself, but it could be an AppController or more generic solution.    

Where to use Attributes

Here are some areas where web frameworks could use attributes:
  •  Routes definition for the controller methods;
  • Validation rules as attributes for entity properties;
  • Smart object serialization, which defined as properties attributes
  • Security rules defined for classes and methods.
  • Static code analyzers.
  • IDE code hinting.
  The attributes are very handy and powerful, they could reduce visual debt and improve code quality. Hopefully this helps with your future projects!  

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!   

Baking With Traits

Traits are a mechanism for code reuse, the convention traits in CakePHP are suffixed with Trait so they can be discernible from classes or interfaces. Our book has a basic sample of Trait. For me, writing code with Traits it's not a regular daily job, but last week I found myself writing a Trait for handling the Theme of an Application.  We need to define the theme on AppView and AppController, and we don't want to repeat ourself:  Beyond re-use code, we can use Traits to separate our code by responsibility.  We like this approach so much that our Users Plugin utilizes it.:   Basically, instead of creating a regular controller with many methods, we create Traits and group the actions by domain business. Sometimes we need to override the functions, and we want add our custom logic after -before or replace the function on Traits: If you wanna bake Traits more complexly I recommend you check out the PHP manual… there,you can see how to fix conflicts, change the visibility of methods and so much more.
That's all bakers! I hope you’ve found this information to be helpful!  

Using CakePHP ORM in your app

CakePHP ORM in your app

We all know that CakePHP is a Full Stack framework, but you may not know that you can pick some of the components and use it in your app when you need. The ORM is not the only one available - you could also have filesystem, validation, utility, core, collection, database, cache, event, form, log, datasource, console and i18n. In this article, we are going to show how to use the ORM component in your slim framework app. You can find the component at: https://github.com/cakephp/?q=read&type=&language=  

Why should we use the componentes

You may be asking why to use as component instead of using the framework as it is, and one of the reasons would be that you already have an application, perhaps using slim framework, and now you need to retrieve data from database. This would be a good moment to use a lib to help you, and here is where cakephp/orm comes in handy. With the componentes you can now solve things with your knowledge in CakePHP, even when your application was not built with CakePHP.  

Setting up cakephp/orm in a slim application

The code used in this article can be found at: https://github.com/CakeDC/slim-cakephp4-packages We could use the package in any PHP application, but for this article we are going to use a slim application skeleton https://github.com/slimphp/Slim-Skeleton. In this app we’re going to change the routes /users and /users/[id] to fetch data from database instead of in-memory data.  

Install the package with composer

We are going to install the version 4.0 of the ORM package:   composer require cakephp/orm:~4.0  

Update config

The app uses the file app/settings.php to set up the main configs, so we need to add a config for database and set cakephp’s App.namespace config. First: add this line after the use declaration. Don’t worry about this config now. We’re setting this to avoid error with PHP 7.4.   Configure::write('App.namespace', 'App');   Then add your database config key inside settings array - in this case we’re using mysql database from a docker service:               'database' => [                 'className' => \Cake\Database\Connection::class,                 'driver' => \Cake\Database\Driver\Mysql::class,                 'database' => 'my_db',                 'username' => 'root',                 'password' => 'secret',                 'host' => 'mysql',             ]   See https://github.com/CakeDC/slim-cakephp4-packages/blob/main/app/settings.php  

Add TableLocator to app dependencies

The app uses the file app/dependencies.php to configure the container of dependencies, and this is a good place for us to define TableLocator as dependency since we normally would use it In my places. Let’s add this inside $containerBuilder->addDefinitions:   \Cake\ORM\Locator\TableLocator::class => function(ContainerInterface $c) {             $settings = $c->get('settings');             \Cake\Datasource\ConnectionManager::setConfig('default', $settings['database']);               return new \Cake\ORM\Locator\TableLocator();  }   See https://github.com/CakeDC/slim-cakephp4-packages/blob/main/app/dependencies.php     This service gets the settings we defined before,sets the configuration to CakePHP, and returns an instance of TableLocator. We could use this service in any route action with:    $locator  = $this->get(\Cake\ORM\Locator\TableLocator::class); $users = $locator->get('Users')->find()->all()->toArray();   But for this app it will make sense to use the TableLocator in a custom persistence class.  

Using the ORM to fetch data

Now, we are finally going to replace the current way of retrieving data to be able to use CakePHP OR. Since our idea is to have a minimum impact in the app, the best way for this app is to replace the current UserRepository. Keep in mind that you could use the following steps with any other class you have.   Create a new persistence class DatabaseUserRepository: Create the class at src/Infrastructure/Persistence/User/DatabaseUserRepository.php Define a constructor method with tableLocator parameter       public function __construct(\Cake\ORM\Locator\TableLocator $tableLocator)     {               $this->tableLocator = $tableLocator;     }          Now we can use the tableLocator to fetch data:         $this->tableLocator->get('Users')->find()->all();       $this->tableLocator->get('Users')->get(10);       ////   To make the app work correctly, we need  to add the required method findAll  and findUserOfId   See: https://github.com/CakeDC/slim-cakephp4-packages/blob/main/src/Infrastructure/Persistence/User/DatabaseUserRepository.php      Now that the repository persistence class was created, we need to connect using dependency injection. Update the UserRepository::class entry in repositories with:   UserRepository::class => \DI\autowire(\App\Infrastructure\Persistence\User\DatabaseUserRepository::class),   https://github.com/CakeDC/slim-cakephp4-packages/blob/main/app/repositories.php   That’s it! Now we can access /users and see the users stored in our database.   I hope you’ve found this information to be helpful! Let us know! For more information check out: https://github.com/cakephp/orm.

Playing with the new CakePHP Queue

One of the topics discussed in the community is the benefit of a unified, officially supported, CakePHP Queue plugin. Queues are used in most of the projects nowadays and are a central utility plugin. During the CakeFest 2020 event, there were also a couple direct references from speakers: (https://speakerdeck.com/josegonzalez/building-and-releasing-a-cakephp-plugin/?slide=15c) and this comment from Mark Story: https://cakesf.slack.com/archives/C172CS4TE/p1602257791377500.   This motivated me to take a deeper look at the cakephp/queue plugin and write this blog post.   Here at CakeDC we've been using queues for a looooong time. Initially in CakePHP 2, we've used plugins like CakeResque with redis or custom workers tied to Amazon SQS queues. Then in CakePHP 3 & 4 we've been using mostly https://github.com/josegonzalez/cakephp-queuesadilla with redis or mongodb backends. https://github.com/cakephp/queue   First thing would be setting up the plugin in your project, we are going to use the example project we used in CakeFest 2020: https://github.com/cakephp/cakefest2020/#using-docker   So after setting up the project and running it via docker compose, we can proceed to setup the plugin via composer. We will need to add it as a repository and set  

Install via composer

  After the first release it'll be much easier, but for now you'll need to add the package to your composer.json   "repositories": [         {             "type": "vcs",             "url": "https://github.com/cakephp/queue.git"         }     ]   Then do composer require cakephp/queue -W   And install some transport as stated in the official documentation https://book.cakephp.org/queue/1/en/index.html#installation composer require enqueue/redis:^0.9 composer require predis/predis:^1   Ensure your redis server is up and running, you can check the commands sent to your local redis server using redis-cli monitor   Now we are ready to configure the queue, we'll create 1 default queue adding this to the config/app.php file       'Queue' => [         'default' => [             'url' => 'redis:',         ],     ],   Add a Job using `bin/cake bake job Example` and add some code to the execute method       public function execute(Message $message): string     {         $data = $message->getArgument('data');           // do some long operation with data         Debugger::log($data);         sleep(2);           return Processor::ACK;     }   I've added a command utility to enqueue a test message bin/cake bake command addJob       public function execute(Arguments $args, ConsoleIo $io)     {         $callable = [ExampleJob::class, 'execute'];         $arguments = ['id' => 1, 'data' => ['some' => 'data']];           QueueManager::push($callable, $arguments);     }   And finally we can start our worker using bin/cake worker to pull jobs from Redis and process them using the ExampleJob::execute method   Here's all the example code created: https://github.com/cakephp/cakefest2020/tree/feature/cakephp-queue - for your reference.   Please note the plugin is still a work in progress and there is no stable release as of now.  It's looking great so far and we plan to include it in our next projects!  

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, @CakePHPThanks for baking!  

CakeFest 2020 recap

Taking a deep breath….. We have made it through another successful CakeFest event.    We didn’t know exactly what to expect with a fully virtual event, as it opens the door for a list of things that can (and most likely will) go wrong. Would the speakers show up? Would the internet connections keep things from running smoothly? Would attendees enjoy the information?   The answer to all of those questions is yes.    The lineup this year was amazing, and we had speakers from 6 different countries! With the ever changing way of life, our team wanted to have a diverse group of speakers, with some talking about some pretty serious subjects - like Dr. Jennifer Akullian and the mental health issues faced in the tech world. Jen allowed for questions and how-to-handle scenarios, and worked through some tough issues with attendees. Workshops from Mark Story, Jorge Gonzalez, Mark Scherer and Jose Lorenzo provided incomparable information while building projects in real time. All of the talks provided useful information that we hope all attendees will take with them as they bake in the future.    Now, does all of this bragging mean we didn’t have any issues? No. As I said in our opening, I think our group is pretty awesome and perfect, but the fact of the matter is, no one is. When bringing people together from all over the world, it is hard to test and check every connection multiple times. We had our fair share of internet lag, connection problems and audio issues. You know what we did? We worked together, fixed it, switched around the schedule and made it happen.   Virtual CakeFest 2020 was a great success, and exceeded our expectations. We were able to gather bakers from all over the world, in real time, and host a live event! I couldn’t believe how interactive the audience was, and everyone is still baking together in our #cakefest chat channel. I hope everyone is as impressed with the turn out as our team is. I know what you’re thinking… when will the recordings be released. We are working on uploading, editing and releasing the videos ASAP. While we tried to find the best universal timezone, we understand that other obligations kept some from attending, and we want to share these videos with you quickly, so know that we are working on it.    To our attendees: THANK YOU. Thank you for joining, supporting our framework and keeping CakePHP alive.   

I would like to thank all of our speakers:

  Remy Bertot  Junichi Okuyama Mark Story Jorge Gonzalez Jose Lorenzo Mark Scherer Jose Gonzalez Cal Evans Ed Barnard Jennifer Akullian Mariano Iglesias Chris Nizzardini Juan Pablo Ramirez
 

A HUGE THANK YOU TO OUR SPONSORS:

   Cake Development Corporation
  Passbolt 
  Marks Software
  RingCentral  


  Here’s to planning next year’s event to be even bigger and better!  

How to take a rest in five minutes

There are a lot of toys these days. Let me show you one very simple and powerful brick for your next revolutionary invention. Let's assume that you're either:

  • A curious person, and you like to play with things you don't know, just for the case
  • A frontend developer with no PHP coding experience, and your javascript components could use some dynamic backend json resource. Maybe you want to do this without playing with all mocking options or Node.js modules out there...and you don't want to set up MySQL database, user, grant permissions and all that stuff
  • building dynamic user interface, and your code needs to be aware of continuously changing structure of databases using unpredictable table names
  • A creator of a wireless network of IoT devices or swarm of flying educational robots. Or, looking for some stable and performant data backend running on your central Raspberry Pi Zero W with tmpfs mounts and ridiculously huge memory card, while sniffing around for bluetooth signatures
  • aware of services like ngrok and wanting to consume payloads of some IFTTT webhooks locally. Or, allowing a friend with Postman to access and/or feed up your database created (or temporarily exposed) just for that reason.
  • Having a rich html application and flirting with the idea of full blown CakePHP backend running in kiosk mode of the DraftCode application right on your iOS device
  • able to pack a PHP application as a single file Phar archive. For example: to simplify all sorts of domain logic/responsibility distribution across bazillions of machines spawned on demand and utilizing jq in your provisioning scripts
  • praying for headless access to any database that your CakePHP application is able connect to, bypassing implemented validation, callbacks, events, and even sneaking through your authentication/authorization backdoor if you want to
  • going to try following example right away, or at least very soon
If your machine meets the CakePHP Requirements, and you have composer in your $PATH then we are good to go for a CakePHP application using SQLite database accessible through REST. This would have obvious api goodies like CRUD, CORS, HATEOAS, versioning, list, describe, relations, sorting and pagination included by default.

Clock is ticking, time to rest with some book(s)

I don't know how much time of the rest limit we lost on the preface (quick learners are quick readers), but don't worry, unless you are on the slow internet connection and packagist is taking a break - we are almost done. We have a clear picture of what we're going to create, so the rest is a piece of cake.
  • create a CakePHP 4.x project named rest with CakeDC/Api plugin unlocked and loaded:
composer create-project \ --prefer-dist --no-interaction \ cakephp/app:~4.0 rest cd $_ composer config \ minimum-stability dev composer require \ cakedc/cakephp-api:~8.0
  • Unlock and load! Auth bypass, "allow all" switch (don't try this at home)
cp vendor/cakedc/cakephp-api/config/api_permissions.php.default \ ./config/api_permissions.php bin/cake plugin load CakeDC/Api
  • manually (meh, we should be resting now) configure Database.default connection in the file config/app_local.php
'database' => TMP . 'rest.sqlite', 'driver' => 'Cake\Database\Driver\Sqlite',
  • create example table books in the database and start local server
bin/cake bake migration create_books \ title:string:unique \ description:text \ price:integer:index \ available:boolean:index \ created \ modified bin/cake migrations migrate bin/cake server Open http://localhost:8765/api/books in your browser to see the (empty) list of your books, then pick some RESTful Route and take a rest from the back end, even without backend coding, scratching who knows where, etc. You maybe have some SQLite databases laying around, and that would be also worth a try. I forgot to remind you to stop that 300s timer, sorry. You will get lost in time as well, once you'll realize what all is possible with the CakeDC/Api plugin using little to no configuration, and what dimensions are opening to you. If you combine its powerful multilayer services approach with solid implementation of your custom ORM classes embraced by CakePHP core and conventions, the results are amazing. Oh, and a quick note for CakePHP 3.x developers - we like you, but please take your time to upgrade your toolset. Feel free to ask us for help, or use following warranty-limited commands: composer create-project \ --prefer-dist --no-interaction \ cakephp/app:^3.9 rest composer require \ cakedc/cakephp-api:~7.0 bin/cake plugin load -b -r CakeDC/Api

What's next

CakeFest 2020 of course. I hope you all are as excited as we are, together in these hard times. Be safe and take care, folks! And rest too, even if it's a quick one :-)

We Bake with CakePHP