CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

10 Features Of A User Friendly Website

Let’s talk about appealing web presence. There are a lot of factors to consider when determining if a site is “user friendly”, and I’m going to give you some tips to make sure yours makes a good impression.

 

Here are some of the top must-haves for a good web page:

 

1. Layout and design

This is extremely important as it is the first thing a visitor will see. If your layout is scattered, or pages are hard to find, they will be running to the red x. In this case, less is more. I am a firm believer in simple clean layouts - I mean it works for Google, right? 

Make sure your pages are seen and easy to access. Make sure your design is aesthetically pleasing, and that is easier than it sounds. 

This brings me to the next point.

 

2. Good, easy to read content

Not only is accessibility important, but the content that the visitor is reading is a direct reflection on your brand. Users are generally on a website for a very specific reason, and if they have landed on yours, then you need to make sure they know that they are in the right place. It is important to immediately list who you are and what you do.

It’s okay to have detailed pages to navigate to, but always make sure your homepage illustrates the services that you provide. Don’t lose a good lead due to bad content, that’s just embarrassing. 

Speaking of good leads, a lot of people search for services on the go which means…
 

3. Be mobile compatible 

More than ever, consumers are using mobile devices to browse the web. You can even order groceries for pickup using your phone. It is absolutely essential that your website is mobile friendly - if you want added success.

If you aren’t sure how your site appears to mobile users, it’s an easy investigation. If searching for your site via mobile device isn’t enough, Google actually offers tools to do it for you. A good developer and design team can assist in making sure that your website is mobile compatible, but there are also some third party providers that you can rely on after your initial site build, if mobile wasn’t included. Basically… just make sure it happens.
 

4. Have ways to be contacted

If someone is on your site, and can’t find an answer to their questions, do you want them to leave? The answer is no, obviously. It is important to have multiple ways to reach some sort of customer service. I personally like a number, chat, and email option, but I guess that is being demanding.
 

5. Browser compatibility

A lot of times, as we are editing or designing sites, our team will compare screen grabs and the site looks totally different on each one. This is a top priority and it gets fixed ASAP. I really don’t understand why this happens, but it must be combated nonetheless.

Mostly, it has to do with sizes, layout, background images, etc. It is just important to make sure that your site looks the same no matter who is looking at it and no matter which browser they choose to do so with. These issues are easy to fix, but sometimes tedious. ALWAYS check each popular browser before deploying. 

 

6. Speed

I’m impatient, and I don’t care to admit it. I would say most people have a short attention span. If I land on a website and I get the spinning wheel, I will give it a chance. If every page has slow loading speed, I am probably going to move on. It’s easy to tell if it’s a webpage causing the issues, so it’s always better to troubleshoot this ahead of time. Once again, there are a lot of free tools you can use to test your speeds. A good free one to try is: wpengine.com - and they will even provide issues & fixes for your slow page. 
 

7. Hosting

Good speed and function is a result of a good hosting service, too. This is something that may not even cross your mind as you are building your brand and your website, but it is so important. The hosting provider you choose can make or break your impression. Pick wisely, and do your research. There is no reason to risk security or your site breaking every time there is an update. You’ll thank me later for this one
 

8. Security

I mean this goes without explanation, right? Especially for e-commerce sites - online shopping - anything that requires customer information. Nothing will ruin a reputation faster than a compromised system. PLEASE make sure all backend security options are locked tight.
 

9. Be Transparent - and bug free

There are going to be errors. No one is perfect - no website is perfect. I always appreciate when a site provides on-screen error descriptions so that I know where I (or the page) has gone wrong. It opens up the trust door with your visitor, and makes them more likely to stick around or retry the action. This also requires the developer to stay in tune with these errors and provide fixes. We want a robust site, right? 

An important thing to remember is always check the status of your webpage, and fix issues fast. Many development companies that offer these services, are avialable to help round the clock. For example, CakeDC offers project management services (see here), which allows client to rely on us for development services long term on the existing projects. 
 

10. Be ever changing

It is important for a business, entrepreneur or developer to adapt. This is especially true for long lasting websites. Say a page has been around for 15 years - things have changed - new features are available… keep up with the times. It is a competitive market that one must always stay in front of. Don’t be afraid of change. 
 

Now go… go out there and make your website great again

 

Latest articles

Improving your mental health while working at home

We’ve previously covered tips, tricks and resources to improve your working at home productivity - today we chat about how to improve your mental health!  There are currently more and more people switching over to remote working - perhaps your company has changed policies, or maybe you’ve been forced to work at home due to a stay-at-home order - whatever the case, mental health while working at home is vitally important. Some of us are made to work at home - working from an office, may not be your jam, and the peace and serenity that a home office offers completes the mood.  However, there are some of us that enjoy the daily routine, the commute to the office and the morning catch up around the coffee machine!  So have you been stuck lately feeling a little more down than usual? Here are some tips to increase your mental health during this time.

Keep your morning routine

Even though you are working from home, and technically can get away with wearing your pajamas all day - you definitely shouldn’t! A morning routine helps set the mood for the day. Perhaps this includes getting ready, dressed or going for a morning run. 

Exercise and eat well

We aren’t talking about a full gym session - merely taking some time to move around. A walk around the block or a bit of stretching will help get those endorphins going. A good diet also goes a long way to helping you feel better - unfortunately too much sugar and too many carbs can have a negative impact on your mental health.

Focus on the now

Practice mindfulness - the ability to focus in on the here and now helps us to drop the negative or difficult emotions that weigh us down. 

Open up to someone

You are valued by others - knowing that is important. Finding a safe space to chat about things goes a long way to lifting the mood. Not sure where that safe space is? Check out https://osmihelp.org/ for some great resources and information.

Take a break

Working from home can sometimes feel endless - some of us struggle to log off at “home time” because, well, you are at home. But this important step is essential to your mental health. Take moments throughout the day to step away - just a couple of minutes to grab some water and take a break. If you haven’t already, please sign up and donate to OSMI - Open Sourcing Mental Illness. We’ve previously chatted with Ed Finkler, OSMI’s founder. CakeDC fully supports OSMI and we love opening up the conversation around mental health - Do you?

Introduction to CakeDC Api plugin

 

The CakeDC API plugin was created with the goal to prepare abstract solutions that solve generic tasks -in case of creating a rest API. It provides such features like automatic rest API generation based on db schema, support nested routes. It also allows the use of different formats like json or xml, and easily adds their own custom format. It helps to solve generic tasks appearing in development of any API, like pagination, data validation, adding common data to response, or building metadata, about data objects.

Dependencies

The CakeDC API plugin hardly depends on the CakeDC Users Plugin. For authentication it is highly recommended to use CakePHP Authentication plugin configured as middleware.

Installation

You can install this plugin into your CakePHP application using composer. The recommended way to install composer packages is: composer require cakedc/cakephp-api  

 Load the Plugin

Ensure  The CakeDC API Plugin is loaded in your src/Aplication.php in bootstrap method. php     $this->addPlugin(\CakeDC\Users\Plugin::class);     $this->addPlugin(\CakeDC\Api\Plugin::class, ['bootstrap' => true, 'routes' => true]);

Configuration

Minimal configuration to allow non authorized requests require you to copy file: ./vendor/cakedc/cakephp-api/config/api_permissions.php.default to ./config/api_permissions.php

Examples

Lets bake table blogs with two fields id and name. After that, the next requests would be possible to perform to api. Requests would be performed using curl. Request: curl http://localhost:8765/api/blogs Response: {     "status": "success",     "data": [         {             "id": 1,             "name": "blog001"         }     ],     "pagination": {         "page": 1,         "limit": 20,         "pages": 1,         "count": 1     },     "links": [         {             "name": "self",             "href": "http:\/\/localhost:8765\/api\/blogs",             "rel": "\/api\/blogs",             "method": "GET"         },         {             "name": "blogs:add",             "href": "http:\/\/localhost:8765\/api\/blogs",             "rel": "\/api\/blogs",             "method": "POST"         }     ] } Request: curl -d "name=blog001" -H "Content-Type: application/x-www-form-urlencoded" -X POST http://localhost:8765/api/blogs Response: {     "status": "success",     "data": {         "name": "blog001",         "id": 1     },     "links": [] } Request: curl -d "name=blog002" -H "Content-Type: application/x-www-form-urlencoded" -X PUT http://localhost:8765/api/blogs/1 Response: {     "status": "success",     "data": {         "id": 1,         "name": "blog002"     },     "links": [] } Request: curl -X DELETE http://localhost:8765/api/blogs/1 Response: {     "status": "success",     "data": true,     "links": [] } For more complex features about plugin initialization and configuration based on routes middlewares, we plan to create an additional article.

Services and Actions

In the REST recommendations documents names defined as a noun. Here, services come into play. It describes business entities. From other side actions define the verbs that describe the operations that should be performed on the actions. Common and difference between controller classes and services. The common part is the service is the managing the choosing action to execute. The primary difference is that service could be nested, if this is defined by request url. Common and difference between controller actions and service actions. The common part is the action defined logic of the request. The primary is that each service’s action is defined as a separate class. This means that generic actions could be defined as common class and reused in many services. From the other side, an action class is able to extend if the system has slightly different actions. This way it is possible to build actions hierarchy. Both service and actions define an event during this execution flow.  Main service events: * Service.beforeDispatch * Service.beforeProcess * Service.afterDispatch Main action events: * Action.beforeProcess * Action.onAuth * Action.beforeValidate * Action.beforeValidateStopped * Action.validationFailed * Action.beforeExecute * Action.beforeExecuteStopped * Action.afterProcess Crud actions define events that depend on the type of action, and more details could be checked in documentation. * Action.Crud.onPatchEntity * Action.Crud.onFindEntities * Action.Crud.afterFindEntities  * Action.Crud.onFindEntity

Nested services

Consider we have request with method POST /blogs/1/posts with data like {"title": "...", "body": "..."} As it is possible to see there is nothing in the given data about the blog_id to which the newly created post should belong to. In the case of controllers we should define custom logic to parse a route, and to consume the blog_id from url. For nested service all checks and records updates are automatically executed. This will happen for any crud operations, when detected by the route parent service. So for example: GET /blogs/1/posts, will return only posts for the blog with id 1. Logical checks are also performed, so for request: DELETE /blogs/1/posts/2, a user gets an error if the post with id 2 belongs to the blog with id 2.

Action inheritance

As each action can be defined as a separate class, it is possible to use class inheritance to define common logic. For example:  Add and Edit actions.

Extending services and actions with shared functionality

The alternative way for defining common logic actions is using action extensions. Action extension is a more powerful feature and could be used for global tasks like search or pagination. It is also possible to create service level extensions. Those extensions work on the top level of the execution process, and could be used for things like adding cors feature, or to append some counter into response.

Add service actions from service::initialize

This is a recommended way to register non crud actions. The mapAction uses the Router class syntax for parsing routes. So on any special use cases well described in cakephp core.     public function initialize()     {         parent::initialize();         $this->mapAction('view_edit', ViewEditAction::class, [             'method' => ['GET'],             'path' => 'view_edit/:id'         ]);     }

Configure actions using action class map.

Each action class uses $_actionsClassMap for defining a map between crud (and non crud) actions on the name of the action class. Non crud actions should be additionally mapped, which is described in the previous step. use App\Service\Protocols\IndexAction; class ProtocolsService extends AppFallbackService {     /**      * Actions classes map.      *      * @var array      */     protected $_actionsClassMap = [         'index' => IndexAction::class,     ];

Configure service and action in config file

Service options are defined in the config/api.php in Api.Service section. Let's consider configuration options for ArticlesService. Configuration are hierarchical in the next sense: 
  • define default options for any service within the application in the Api.Service.default.options section.
  • define options for any service within the application in Api.Service.articles.options section.
All defined options are overridden from up to down in described order. This allows common service settings, and the ability to overwrite them in bottom level.
  •  Api.Service.classMap - defines name map, that allows defining services action classes with custom location logic.
    Any action, that could be loaded as default action defined in fallback class, or specific action class could be configured using configuration file.
    Let's consider how one can configure options for IndexAction of ArticlesService.
    Configuration are hierarchical in the next sense: 
  • one can define default options for any action for all services in the application in the Api.Service.default.Action.default section.
  • one can define default options for index action for all services in the application in the Api.Service.default.Action.index section.
  • one can define options for any action in the specific (articles) service in the Api.Service.articles.Action.default section.
  • one can define options for index action in the specific (articles) service in the  Api.Service.articles.Action.index section.

Crud and non crud methods. Mapping non-crud actions.

Crud services mapped automatically in two levels routing by FallbackService.

Index and view. Formatting output

The CakeDC Api Plugin is flexible and provides multiple ways to prepare result data for the response objects. There is a list of main options.

Use Entity serialization

The most trivial way to convert data is using entity serialization. When converting an entity to a JSON, the virtual and hidden field lists are applied.  Entities are recursively converted to JSON as well.  This means that if you eager, and loading entities and their associations, CakePHP will correctly handle converting the associated data into the correct format. Additional fields could be defined using Entity::$_virtual and hidden using Entity::$$_hidden.

Build object manually from Action::execute

In this case users manually perform mapping of requests received from model layer to output array. public function process() {     $entity = $this->getTable()->get($this->getId());     return [         'id' => $entity->id,         'name' => $entity->name,     ]; }

Use Query::formatResults in model layer

The request could be formatted in model layer using: Query::formatResults. So in this case, the process action just calls for a needed finder from the model layer and returns the result. public function findApiFormat(Query $query, array $options) {     return $query         ->select(['id', 'body', 'created', 'modified', 'author_id'])         ->formatResults(function ($results) use ($options) {             return $results->map(function ($row) use ($options) {                 $row['author'] = $this->Authors->getFormatted($row['author_id']);                 unset($row['author_id']);                   return $row;             });         });

Use Action extensions to format output

In index action defined callback Action.Crud.afterFindEntities, which called after data fetched,  could be used to extend or overload results coming from the database. Callbacks are catch-in-action extensions and could be applied to multiple endpoints. For view action defined Action.Crud.afterFindEntity, which called after single record fetched.

Use Action extensions to append additional data to output

Sometimes there is some additional information needed to be presented in some group of endpoints. In this case it is possible to implement an action extension to append additional data. For example, pagination provides information about number of pages, records count, and current page number. Another example for additional data is some execution statistics about the query. Here you see main parts of appending such data from extension. class PaginateExtension extends Extension implements EventListenerInterface {     public function implementedEvents(): array     {         return [             'Action.Crud.afterFindEntities' => 'afterFind',         ];     } ...     public function afterFind(EventInterface $event): void     {         ...         $pagination = [             'page' => $this->_page($action),             'limit' => $limit,             'pages' => ceil($count / $limit),             'count' => $count,         ];         $result->appendPayload('pagination', $pagination);     }     The renderer class describes how to handle payload data. For example in JSend renderer, all payload records appended to the root of the resulting json object.

Rendering output. Renderers.

Renderers perform final mapping of response records to output format.  Such formats like xml, json, or file are provided by  The CakeDC API plugin. JSend is the json extension with some additional agreements about returning results.    

Remote Work, Actually Works!

As a fully remote company, the Cake Development Corporation team is used to working from home. We communicate with our team daily, keep on top of tasks, hold each other accountable and support one another. Heck, a lot of us even do it with kids in the household, too! I consider us extremely lucky to be able to work while juggling an at home life at the same time.  It has worked for CakeDC over the past decade, and in my opinion, can work for most companies.   As of last month, an estimated 4.7 million people were working remotely, which grew 44% over the last 5 years. This is just in the United States. Remote work is becoming the norm.  Obviously for the next few weeks, this number will be drastically increased, but perhaps this will educate companies on the advantages of a WFH culture. Advantages to employers, besides the operations cost (other than payroll, of course), which can decrease by close to 90%, includes increased productivity. Decreased overhead results in higher salaries, which results in more quality candidates and employees.  I understand the concern of the ability to micro-manage (UGH) being unavailable, but according to statistics, 85% of businesses that work remotely confirmed that productivity increased in their companies. When there is more flexibility, there will be higher employee morale.  With the current situation arising from COVID-19, a lot of businesses are forced to transition employees to WFH in order to stay afloat. This not only keeps employees and clients safe, but family members too.  I have put together some stats and resources that may help CEO’s and employees transition a little bit easier.  

Communication:

It is absolutely essential to keep open communication among a team when everyone is working remotely. Our team uses RocketChat* ( I will include some links in the resource section at the end of this blog), and it has proved to be effective. A chat allows for quicker response time, as well as allowing individuals to set their status (like busy, away, at lunch, sick, etc.). This is a good way to get quick answers, as users can be alerted when they have been messaged or tagged in a company chat. Most of our team work in different timezones, so this is a good way to “stay in the know” about everything happening day to day. We separate chats according to their department. For example: marketing, development, general, etc. We also have the option to private message with co-workers when needed.  Other ideas, if not daily chat interaction, include scheduled meetings. For most of our team meetings, we use Zoom. This tool allows for audio only, as well as video chats.  

Accountability & Time Management:

It is important that tasks are managed and followed through. We use programs like Redmine* to track hours and work, in addition to weekly, or monthly conference calls for each department.  If you or your team are new to remote work, it may be in your best interest to assign a project manager, someone who will assign work, track hours, and ensure that work needed is being completed in a timely manner. Without each person being held accountable, the ship will sink, fast. For personal accountability, there are many free apps and tools available. One example is Trello*. This is a scheduling board so that tasks are not forgotten and you can plan your work week and stay organized. Once tasks placed on your “schedule board” are completed, you can make note of it and stay focused on each one according to their priority. You can also keep track of documents and reports. The boards look like this:    

Resources:

Documents & Recording - We <3 Google Docs - we are able to share and edit internally, we couldn’t function without it.  Docusign is a good tool for contracts / documents needing signatures Invision Freehand - this is a tool where you can create presentations, and allows comments and feedback between designers. Good for freelance designers!    Organization/Tasks -  Trello - for individual time management scheduling.  Redmine - for project assigning, time recording, HR management,    Communication -  RocketChat - allows for multiple internal chats all rolled into one link (allows for individual logins) Zoom - good for meetings. Allows audio and video chats for teams or reps and clients.  Slack - also a great option for expanded chats. Each person has a “screen name” and can be personally messaged, or public groups can be created (we use this as well). Slack also allows video calls with their paid subscription.  Google Hangouts WhatsApp - if your team is diverse, like ours, WhatsApp is a must. We are able to text each other, regardless of location - no fees, no service problems (if you have wifi of course).  World Time Buddy - this is a tool that I am not familiar with, but being the designated “scheduler of meetings”, I think I would find it useful. If your team works within different timezones, this allows you to add the location of your teammates, compare times, and find ideal times for meetings.    Community - In the development world, community support sites are absolutely one of the most important tools. This allows for individuals - inside or outside of your company - to communicate and help each other out. Most developers are aware and utilize these, but if not, may I suggest: Discourse - chat support  GitHub - our favorite team collaboration tool. GitHub allows for hosting, editing and managing products. We use it for building software and allow for community interaction. It also integrates with a lot of other tools, which is a plus!  

Take Away:

These resources are just a drop in the bucket compared to what is available to remote workers. I think this is a reflection of how WFH is becoming more accepted and more normal in the corporate world. I’d love to hear some of your favorites: amanda.goff@cakedc.com.  Let’s take away some positivity to the current quarantined times, and encourage more companies to follow suit. In today’s world, flexibility goes a long way and this type of transition can be mutually beneficial for employers and employees. I mean look at us, we are PRETTY normal… right?  Speaking of being in quarantine - stay healthy, stay inside, and wash your hands!  

We Bake with CakePHP