Customizing and extending PHP’s SoapClient

The last time I had to work with Soap was when I was in college. Fortunately most webservices are RESTful these days, which are a lot easier to use in my opinion. I recently however, had to connect to two different webservices using SOAP which forced me to polish up my skills in this area. The first webservice was quite simple, but the second one was aweful. It required the XML to have all kinds of different attributes and namespaces, which I discovered to my surprise, is close to impossible to implement using PHP’s core SoapClient class. There simpy isn’t something like a method ‘addAttribute’.

I finally managed to crack it after days using PHP’s DOMDocument. I found a vague example of someone using it, but the problem was that they were using an override of __doRequest to return the result, which is XML. While SoapClient returns objects and handles exceptions. And that is exactly what I wanted it to do. This is how to do it:

This, of course, is a basic example. Let me explain what’s going on; some understanding of PHP’s SoapClient and Soap is required. Soap enables you to call webservices by sending data in XML format. WSDL describes the methods you can call on the webservice. Soap-xml should contain a reference to the WSDL file so that it can execute and process the calls. Let’s say you have a webservice with a method ‘doSomething’ you want to call. You initialize a SoapClient with the proper endpoint for the webservice and call ‘doSomething’ on that SoapClient instance. Of course SoapClient doesn’t have this method and will attempt to call this method on the webservice. It will validate the XML and deWDSL in the process and throw an exception if it contains errors. If it succeeds, it will return an object which it creates from the XML response it gets from the webservice.

In my example above, I gave my SoapClient a method ‘doSomething’. I did that because I want to call ‘doSomething’ on the webservice but I need to customize the XML first. Because SoapClient doesn’t offer me the methods to do this properly, I created the custom SoapClient and the method ‘doSomething’ in it. I now call this method with all the parameters I need to build up the XML. In this method I use DOMDocument to create the XML. DOMDocument is a powerful XML building tool which I can use to create exactly the XML I need. When I’m done I assign the XML to property $requestXml. Then I call SoapClient’s __soapCall() – method and pass the name of the remote method I want to call as string (‘doSomething’). Normally SoapClient does this for us when the method ‘doSomething’ doesn’t exist using PHP’s magic methods.

I created an override for method __doRequest which is also used by SoapClient to make the requests. __soapCall somewhere triggers a call to __doRequest, for which I created an override. As you can see, I replaced the first two parameters with my data and call __doRequest on the parent. These two parameters are built by SoapClient when a none-existing method is evoked on SoapClient : in this case I called parent::doSomething, which doesn’t exist on the parent. The $request param will just contain some empty XML because I called ‘doSomething’ on the parent without any parameters. I now replace it with my XML and call __doRequest on the parent. SoapClient now handles the rest of the work for me as it usually would do. My method ‘doSomething’ will now return an object or throw a SoapFault just as SoapClient would normally do.

I hope this made some sense, it’s kind of complicated to make this a simple story. Just let me know if you have any questions.

HTML2PDF : undefined offset

While this blog is mainly about code-examples, I’d like to post an occasional bugfix when it’s a nasty one. This is one of them.

The HTML2PDF library for PHP is a great library for converting HTML to PDF. I ran into a problem in an application where an exception was thrown by this library with the vague message ‘Undefined offset 5‘.

At first I thought it was my code, but as I wasn’t using any arrays I started inspecting the HTML closer and finally noticed a table-element was causing the problem. Because of a miscalculation with the rowspan-attribute of one of the table-cells, not all the table-rows contained an equal amount of columns. This explains the undefined offset issue; the library has to convert to table to pdf and uses arrays in the background to convert the table data. A mismatch in columns will break this code. The library does not account for invalid html in this case and continues on the assumption the table-markup is correct. This explains the vague error message.

I Hope this solves your issue. If this is not the case, start leaving out parts of your HTML untill the error dissapears to discover what element might be causing it.

Laravel 5 : SSL routes behind a load balancer

I just recently ran into an interesting problem when working on a Laravel website tucked away behing a loadbalancer on an Apache webserver. Though the website was using ssl, every url generated by Laravel had http:// as protocol instead of https://. Apparently the $_SERVER variables indicate it’s not ssl, except for $_SERVER[‘HTTP_X_FORWARDED_PROTO’] which is not used by Laravel to detect wether ssl is on or not.

I was looking for a proper way to solve this issue because multiple classes and functions generate urls, like for example the helper functions ‘route’ and ‘url_to’ but als the Form-class with Form::open(). So overriding all these classes and functions was not a very smooth nor adequate solution.

I did some digging to figure out how to solve this problem and this is what I came up with :

Continue reading Laravel 5 : SSL routes behind a load balancer

Laravel 5 : Creating Console Commands

Anytime something causes me a great deal of time to figure out, I usually decide it’s worth posting. In this case it’s console commands in Laravel 5. Laravel 5 has just been released with some great improvements. Somewhat confusing is the usage of commands. Commands now appear to be some kind of event driven delegates. It is all well documented but not so well documented is wat happened to console commands, something we still need for our cronjobs and serious development work like running imports.

Here’s how to walk the walk in Laravel 5:
Generate the command
Console commands are now created with the following Artisan command :

In this case ‘GetMeABeerCommand’ is the class name of my command. You replace this with your own class name unless you need a beer too. The generated command will now be available in your App/Console/Commands folder.

Provide a console name and description
Now open this class and fill out a name for your command and a description :

The name your filled out will be the name you use to run the command from the console. Use alphanumeric characters, no spaces or funny stuff (I haven’t experimented with what characters are allowed but just stick to simple). This can be what ever you choose, but it’s logical to have it reflect what the command class does. So having a console command class ‘GetMeASodaCommand’ with a $name ‘command:get-beer’ doesn’t make much sense.

Register the console command
As with Laravel 4 you still have to register the command with a ServiceProvider. Laravel 5 installs with an AppServiceProvider (/App/Providers/) which you can use for this occassion, or you can create your own service provider. Just don’t forget to add it to the list/array of service providers in app.php if you decide to create your own.

You register the console command in the boot-method:

The ‘ABCD’ namespace here is my namespace I made up. In Laravel 5 you set your namespace with the Artisan command as you might now. The AppServiceProvider is generated at install and will already have the proper namespace. The only thing you have to to is add the lines in the boot-method. Notice how ‘get-beer’ is the name I provided above in the console command class.

Run the command

Go to your console (root of the website) and type :

You will now see a list of available options, your command will be listed under ‘commands’. You can run the command like this:

your-command-name in this case is the name you provided in the $name property of your console command class. In my case that’s ‘get-beer’. So I would run :

That’s all! I’m getting a beer. Happy coding!

Concrete 5.7 : Overriding a core single page controller

Overriding a single page controller in Concrete 5.7 is still possible. In some situations you might need to do so. A lot of things have changed in Concrete 5.7 compared to prior versions and one of those things is where to put your overrides.

Let’s say you want to override the page controller for the registration page. The controller for this page (\ Concrete\Controller\SinglePage\Register) is located in the folder /concrete/controllers/single_page/. You will be looking for register.php. So the full filename is : /concrete/controllers/single_page/register.php.

Creating the override
Create a class ‘Register’ in the folder /application/controllers/single_page (you will have to create the subfolder ‘single_page’, it doesn’t exist by default). Now set the namespace of this class to ‘Application\Controller\SinglePage’ and let the controller extend ‘\Concrete\Controller\SinglePage\Register’.

This is what your class will look like:

You can now override or add methods to this class.  In this case I created an override for the on_start method and added the method ‘doSomethingAwesome’.

That’s it, you are all set!

Concrete 5.7 : creating a PageTheme class for a package’s Theme

Concrete 5.7 is completely different compared to 5.6. One of the many new features is the usage of a PageTheme class in themes. Previously themes didn’t have such as class. A PageTheme class is kind of what a controller is for a package.

A PageTheme class is optional for themes, which means a theme will install without it. But having a PageTheme class gives you more control over your theme. You can define custom css classes for your blocks here for example as well as load Javascript and CSS assets you need in your theme.

Documentation is still in the early stages when it comes to Concrete 5.7. Creating a PageTheme class is easy but getting it to work can be tricky if you don’t know how. I could find documentation on creating one in the application/themes folder but not for creating one in a theme contained in a package.

So here’s how to install a PageTheme class for your custom package.

Let’s say your package’s name is ‘MyAwesomePackage’ and you have a theme in this package called ‘MyAwesomeTheme’ . Your package’s handle will then be ‘my_awesome_package’ and the handle for this theme will be ‘my_awesome_theme’. In that theme you will have a class called ‘PageTheme’ and the filename will be ‘page_theme.php’.

This is wat your directory structure will look like so far :

– /packages/my_awesome_package
    – /themes/my_awesome_theme
        – /page_theme.php

Then you will need to namespace your theme; in this case the namespace will be : Concrete\Package\MyAwesomePackage\Theme\MyAwesomeTheme

In code :

Another important thing : If you add this after you installed your theme you will have to trigger detection for this class as Concrete will otherwise ignore it if it wasn’t present when the theme was installed. There are two ways to do this:

1.) Activate another theme, then reactive your theme.
2.) Alter the record in the table ‘PageThemes’ of your database and set the value of column ‘pThemeHasCustomClass’ to ‘1’ in the record belonging to your theme.

The last one is easier and safer to do I think because switching themes might break things but that’s just a guess.

That’s all folks! Happy coding!

Ember JS : Creating nested urls for relationships REST-style

I’ve been working on a project in Ember JS with the Ember-client extension for a while now. Ember is very frustrating to work with because of the lack of documentation.

I was recently looking for a way to have Ember use urls for loading and saving resources from a REST-api using the same conventions used by api’s like the ones Facebook and Twitter use.

For example, requesting the comments for a post would have an endpoint like this:

/posts/{ID}/comments

Unfortunately Ember will just post the user id to this endpoint:

/comments

There is a way to have Ember use /posts/{ID}/comments as endpoint but that requires the payload from the api for a post to contain the property ‘links’, containing the desired endpoint. To me this seems undesirable; endpoints should be derived from conventions. Besides, if you have no control over the api then you have no control over this ‘links’ property

You could add the ‘links’ property to the payload by overriding Ember’s RESTAdapter or RESTSerializer but that is a difficult place to do that.

I analysed what Ember does in the background when it finds the ‘links’ property on a payload : it creates relationships in the corresponding model. I managed to create an override that changes the ‘link’ property of the corresponding relationship.

This is my code:

I’m not really happy with this solution because manually changing the ‘link’ property after ember created the relationship is far from ideal. But in the mean time, untill I find a better approach I’m sticking to this in order to get my application to work.

 

Concrete5.7 : Javascript validation for a block’s form

If you are developing a block for Concrete 5.7 you might be looking for the Javascript function ‘ccmValidateBlockForm’ that handles the clientside validation of your block’s form. It seems to have dissappeared in Concrete 5.7 which leaves you with no way to prevent the form from being submitted if it contains validation errors.

I ran into this problem recently as I was developing my own block. The wrong approach is to listen to a form submit event. I tried this but discovered it submitted anyway as Concrete was triggering a submit with Javascript. The trick is to prevent that script from being triggered. Concrete listens to a click on the form’s submit button which is in fact not a submit button but an anchor using Javascript to trigger the click event on the real submit button which is hidden from sight.

This is how to solve it:

 

Replace ‘myFormValidationFunction’ with the name of your function that validates the form. Return false to prevent the form from submitting or true to allow it to submit.

Concrete 5.7 : Creating a single page for the frontend

In this post I would like to show you how to create a single page in your package for the frontend of a Concrete 5.7 website. In this tutorial we will call that package ‘YourPackage’ but of course that should be whatever your package is called.

Let’s say you want to create a single page where visitors can sign up for a newsletter. A single page is composed of a template and a controller (The controller is optional).

We will call our controller ‘SubscribeTo’. Following C5’s naming conventions this implies that :

    • The filename of the template will be called ‘subscribe_to.php’.
    • The filename of the controller will be called ‘subscribe_to.php’.

Your directory structure will look like this:

For the controller :

/packages/your_package/controllers/single_pages/subscribe_to.php

For the template :

/packages/your_package/single_pages/subscribe_to.php

And this is what your controller file will look like:

Now let’s say you want to install the single page when your package get’s installed. We will add a method to the package controller in order to do so. (The package controller is  :  /packages/your_package/controller.php).

Now the single page gets installed when you install your package. In this example I added the method ‘addSinglePage’ to the package controller but if you want to follow programming conventions it is better to create a separate class with this method (like a service/util). This way you delegate the logic. That makes it easier to refactor and you can call the method from other packages or code you create.

 

Code Examples

I’ve just started off recently (jan 10th, 2015) so there’s not much to see here yet. I’ve set up this blog mainly to post interesting examples and tutorials on code cause unfortunately there’s never enough documentation out there.

I develop a lot of websites and applications in PHP and Javascript and I would like to share some cool stuff with you guys in the years to come.

Stay tuned!