Posts Tagged ‘web development’

SASS course

Sunday, November 22nd, 2020 | News

SASS is a preprocessor that turns CSS into a programming language. You can use includes, variables, reuse bits of code, add logic and functions, and much more.

Using SASS allows you to develop cleaner, well-organised code that is easy to update and maintain.

In this course, you will learn how to use SASS. We’ll start with a tour of the functionality before moving onto a project to put those skills into action. You can code along to pick up some real-world experience.

Preview the course on Udemy or watch the trailer below.

Upgrading LAC to Slim 4

Wednesday, October 28th, 2020 | Programming

Last month, I published an upgrade guide to Slim 4 covering the changes that most people will need to make.

I recently upgraded the Leeds Anxiety Clinic and this project has some further complexities, so this post will elaborate on all of the changes I made, in case my original blog post did not cover some of the issues that you are also running into.

Things to do in advance

The old service layer calls no longer work:

$db = $this->ci->db;

And need to be updated to:

$db = $this->ci->get('db');

However, Slim 3’s service container already supports this syntax, so you can go ahead and update your code in advance.

If you are passing the container into controller functions, you need to typecast it.

use Psr\Container\ContainerInterface;

class Controller {
    __construct(ContainerInterface $ci) {}
}

If you pull the request out from the service container, you cannot do that in Slim 4. For example, if you have a render helper that relies on the request being in the container, you will have to start manually passing that into your render help from the page route closure.

Dependencies

You will want all of these:

"slim/slim": "4.*",
"slim/psr7": "1.*",
"slim/http": "1.*",
"php-di/php-di": "^6.1",

I did wonder if I could remove my other PSR-7 library that I use for Mailgun, nyholm/psr7, but the answer is no.

Instanciating the app

We now create the container and then the app, and you can recursively pass in the container.

$container = new \DI\Container;

$container->set('serviceA', function() use ($container) {
    return new ServiceA($container->get('serviceB'));
});

\Slim\Factory\AppFactory::setContainer($container);
$app = \Slim\Factory\AppFactory::create();

Throwing not found exceptions

If you manually throw not found exceptions or other HTTP exceptions, Slim 3 has them located here:

Slim\Exception\NotFoundException

Slim 4 moves it to here:

Slim\Exception\HttpNotFoundException

Error handling

If you want Slim 4’s default error handling, you need:

$errorMiddleware = $app->addErrorMiddleware(true, true, true);

And if you want to handle HTTP errors (such as not found), you can use:

$errorMiddleware->setErrorHandler(
    Slim\Exception\HttpNotFoundException::class,
    function (Psr\Http\Message\ServerRequestInterface $request) use ($container) {
        $controller = new App\Controller\ExceptionController($container);
        return $controller->notFound($request);
    });

You can also set your own error handling:

$errorMiddleware->setDefaultErrorHandler(
        function (Psr\Http\Message\ServerRequestInterface $request,
        Throwable $exception) use ($container) {
            $controller = new App\Controller\ExceptionController($container);
            return $controller->error($request, $exception);
        });

This means you will need to create your own response object in any exception controller you use.

public function notFound(Request $request)
{
    $response = new \Slim\Psr7\Response;
    return $this->render($response, 'not-found.html');
}

Custom middleware

The way we pass through middleware has changed. The old way:

public function __invoke($request, $response, $next)
{
    $response = $next($request, $response);
    return $response;
}

The new way:

public function __invoke($request, $handler)
{
    return $handler->handle($request);
}

That change alone probably won’t do what you want it to do out-of-the-box, so you might need to do some reading up and adapt it to your specific middleware depending on function.

Custom middleware wants to go towards the bottom after you define your routes, but before the error middleware.

Surviving the JavaScript ecosystem updates of 2018

Tuesday, December 18th, 2018 | Programming

When I first launched the WAM website it was built using a reasonably straightforward stack of React + Babel + Webpack. That was a year or two ago and a lot has happened since then. Notably, there have also been some JS security issues, too, so we’re going to start upgrading the stack on a regular basis.

As anyone who has worked with JavaScript knows, though, that is a massive pain in the ass. Here are some notes on the upgrade process.

Upgrading Gulp

Gulp has now moved to version 4. First off, you need to uninstall any previous versions of Gulp. You then install the Guli CLI globally, and the latest version of Gulp locally.

npm install -g gulp-cli

This was a massive hassle. The uninstalls did not work and I had to manually go through the file system to get rid of the thing.

There were also some changes to the config itself. Any paths such as dest('') had to be changed to dest('.'), and all of the functions that defined the Gulp tasks had to now return, rather than just being called.

return gulp.task('name', () => { });

The way tasks were run within them has also changed. So, anywhere that used tp be ['sass'], for example, now needs to be:

gulp.series('sass')

Ugrading Node

You’ll want to upgrade Node to the latest LTS version. This includes editing the engine in your package.json file, especially if you are using Heroku.

Upgrading React

This was as simple as updating the versions in package.json and running an update. However, I did run into a problem with the React CSS Transition group, where I had to update to a drop in replacement.

npm install --save react-transition-group@1.x
npm remove react-addons-css-transition-group

And then change the import statement to import from:

react-transition-group/CSSTransitionGroup

Upgrading Babel

This was mostly a case of bumping the version numbers, but I also had to update my .babelrc file. I think the spread operator was previously a different package, and I had to change the name.

{
    "presets": ["@babel/react", "@babel/preset-env"],
    "plugins": ["@babel/plugin-proposal-object-rest-spread"]
}

Upgrading Webpack

Again, this started with bumping all of the versions. There were also some config changes. Most notably, Webpack now has an environment property.

config.mode = 'production';

It has also changed the way that UglifyJS is brought in if you’re using that to minify your code. You’ll need to install the new package.

npm install uglifyjs-webpack-plugin webpack-cli --save-dev

And then update your Webpack config, too.

config.optimization = {
  minimizer: [
    new UglifyJsPlugin({
      uglifyOptions: {
        output: {
          comments: false
        }
      }
    })
  ]
}

Hopefully this will come in handy if you are upgrading a similar stack and wondering why everything has exploded.

PHPNW13

Sunday, October 13th, 2013 | Programming, Tech

phpnw13

Last weekend I headed over to Manchester for PHPNW13.

I really enjoyed last year’s event and came away having learned a lot from it. This year was also quite interesting, though on returning home and reviewing my notes, there is only really one new thing that I want to look into.

Drupal basics in under five minutes

Tuesday, May 29th, 2012 | Limited, Programming, Tech

Drupal is probably the best PHP-based CMS (content management system) on the market today. However, because it has a somewhat steeper learning curve than other systems, where you can just install and start creating content, it is easy to get frustrated with it and give up.

However, a short amount of time getting your head round the basics should be enough to show you that Drupal has some really powerful features which make it a far better CMS than those that simply allow you to drop text into pages.

We used Drupal to build Know Leeds and it allowed us to quickly and easily put together a functional site that allowed the non-technical contributors to get to grips with the system.

Content types
Because most people are familiar with WordPress, I’m going to use that as a comparison throughout this article. If you’re not familiar with WordPress, don’t worry, because most, if not all of the terms used are generic concepts that you will be able to understand anyway.

In WordPress, you have two types of content – posts and pages. Posts are the bread and butter of what was traditionally a blogging only system. Pages, are similar, but are static and don’t go into the date-based archives.

In Drupal, you get to define your own content types. It comes pre-configured with an article (similar to a post) and static page content types, but where you go from there is up to you. There are two good examples of where we used this in Know Leeds.

Firstly, we added a content type for “Restaurant Review”. This is similar to the Article content type, but we wanted to add some additional fields to Restaurant Review that didn’t want to be in Article – a star rating and a categorisation of what type of food the restaurant served.

Secondly, we added a content type for “Place”. We offer listings of local bars, clubs and restaurants on the website and if you think about it, an entry for one of these is basically just a piece of content. But with different needs than an article – we need address, phone number, email address, etc. So we created a custom content type for that too.

Fields
As I discussed with our custom content types, we wanted to customise the field types on our content types. In WordPress there are a number of fields – title, body, published date, categories, etc. In Drupal, you have the same thing, but you can create your own fields and match them to each content type.

So for the Restaurant Review content type we added a star rating field. This allows the editor to enter a numeric value between one and five. We also added a Cuisine content type which allows them to pick what kind of food it is. This works just like the WordPress categories system, except we can have multiple types of categories and we can pick which content types they apply to!

Taxonomy
In WordPress, there are two types of taxonomy – categories and tags. In Drupal, surprisingly enough, you can define your own. As I’ve already discussed, we created a Cuisine taxonomy and added a list of different terms (or categories if you will) such as French, Italian and Steak House.

Drupal allows you to create as many different categorisation systems as you wish and apply them to the content types as appropriate. We only wanted Cuisine to apply to the Restaurant Review content type for example, but Category might apply to both Article and Restaurant Review.

Blocks
Units of content which can be placed somewhere in your layout are called Blocks. The nearest equivalent to this in WordPress is the “widgets” system where you can drop widgets in and out of the sidebar.

Drupal comes with some standard blocks such as user login and search form, and many of the modules you can add into Drupal will add some blocks too – adding the forum module will add an “active forum topics” block for example. Of course, you can create your own custom blocks too.

You can then define where these appear – first sidebar, second sidebar, footer, navigation menu, etc, by selecting their position from the blocks menu. You can even do this on a theme by theme basis – on one theme you may want the search form to go in a sidebar for example, in another theme you may want it to go at the top or bottom of the page.

Unlike the widgets system in WordPress though, everything is a block in Drupal! Even the main page content so for some reason if you wanted to make your footer text display in the centre of the page and your main content display in your sidebar – you’re just a couple of clicks away from that!

Menus
Menus probably need the least explaining of all – it allows you to create menus which people can navigate around the site with. It is worth noting though, that items don’t appear in the menu automatically – you have to request that a piece of content (usually a static page) is given a menu link when creating or editing that piece of content.

Of course, you can create as many different menus as you want, assign different content (or any other links you want to add!) to different menus, and have the menus display in different places around your layout using the blocks system.

Conclusion
I hope this has presented you with a quick introduction to the fundamental concepts of Drupal. It is far more customisable that most other popular content management systems and as such has a steeper learning curve, but far more flexibility once understood.

Gluttons for punishment

Sunday, June 27th, 2010 | Tech

There was a really interesting poll on SitePoint today asking whether freelance web developers were working this weekend. The results were as follows:

  • 43% said they always worked weekends
  • 34% said they sometimes worked weekends
  • 20% said they worked weekends if necessary
  • Only 3% said they never worked weekends

What we can probably assume from this is that on any given weekend, more than half of people who do freelance web development are working. Crazy people. Anyway, I would love to chat more about this but I have code to write…

Calling the Brain Trust

Monday, May 31st, 2010 | Tech

Ok, here is the situation. I have a website which has two virtual hostnames pointed at it – domaim.com and sub.domain.com. They both point to the exact same location in the file system and serve the same content. However I need one of them to invoke a http authentication and the other not to.

The obvious solutions I see are…

Set up a rule in the .htaccess so it only requires a valid user when accessing the sub domain. This is the simplest solution but I don’t think such a rule exists.

Dynamically serve different .htaccess files based on the host being accessed. This ticks neither box of being simple or actually something you can actually make the computer do. But maybe it is if you start layering your .htaccess files.

Invoke the http authentication from the PHP script itself, detecting the server name and serving if appropriate. This is doable and straight forward to implement but requires quite a bit of coding.

Also maybe I can do the original solution, but only inside the vhosts.conf file? I haven’t really looked into that so that’s just speculation. Question is, which is the easiest solution to implement?