Joomla 4 API development

566 views
Skip to first unread message

Peter Tuson

unread,
Apr 20, 2022, 2:32:50 PM4/20/22
to Joomla! General Development

I have been trying to develop an interface with the Joomla 4 API without much progress.

My request is Get http://baseaddress/api/index.php/mycomponent/controller/controllerfunction including  Bearer my key as part of the header.

The response is:
< HTTP/1.1 404 Not Found
< Date: Wed, 20 Apr 2022 18:22:05 GMT
< Server: Apache/2.4.53 (Debian)
< X-Content-Type-Options: nosniff
< X-Powered-By: JoomlaAPI/1.0
< Expires: Wed, 17 Aug 2005 00:00:00 GMT
< Last-Modified: Wed, 20 Apr 2022 18:22:05 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Access-Control-Allow-Origin: *
< Content-Length: 51
< Content-Type: application/vnd.api+json; charset=utf-8
* Connection #0 to host localhost left intact
Array
(
    [errors] => Array
        (
            [0] => Array
                (
                    [title] => Resource not found
                    [code] => 404
                )
        )
)
Firstly why am I getting this message. What is wrong with what I am doing? By the way Resource should say Route as it actually an error in the route.

Secondly, how am I supposed to debug this? I tried enqueueMessage and nothing appeared.

I am using Joomla 4.1.2 and my component has API components.

Regards,

Peter.

MarkRS

unread,
May 9, 2022, 7:53:30 AM5/9/22
to Joomla! General Development
Sorry if this is an "egg-sucking" answer (I'm just starting with the J4 API i/f too).
Have you got a plugin for your API and have you defined the path in the onBeforeApiRoute method?

Peter Tuson

unread,
May 12, 2022, 1:16:07 PM5/12/22
to Joomla! General Development
Thanks.

No, I didn't realise that I had to have such a thing given that the API section should be quite easy to parse.

Regards,

Peter.

MarkRS

unread,
May 13, 2022, 12:23:06 PM5/13/22
to Joomla! General Development
It's not about the parsing of it (as far as I can work out), it's simply that the plugin is what gets triggered by the endpoint getting hit and it then knows how to set up the call to the api area that you already have set up.

Thinking about it, I'm not sure why it's like this.  It was similar (in a quite different way, I suppose) in J3.  Plugins got triggered and we went from there.  J4 integrates the process into a more J-like structure.  I think that's probably ("perhaps"?) a good thing from our pov.

I'm still trying to work out how it all hangs together, particularly as for me, and I expect for you too, the default way it works gives me some unhelpful bits of output.

Mark

GhiaMar

unread,
Jul 1, 2022, 8:25:03 AM7/1/22
to Joomla! General Development
For the record, here in the wiki exists a step by step tutorial for adding webservices to a component https://docs.joomla.org/J4.x:Adding_an_API_to_a_Joomla_Component

MarkRS

unread,
Jul 1, 2022, 11:05:13 AM7/1/22
to Joomla! General Development
@peter, I'd be interested to know if @GhiaMar's link helps you, since I wrote most of it, after it was posted initially at least.

Peter Tuson

unread,
Jul 4, 2022, 8:59:16 AM7/4/22
to Joomla! General Development

I cannot do Joomla 4 development any more on my computer. I am using localhost on a linux laptop with apache2. I am on Joomla 4.1.5.

If I log into administrator and try and save an article or module then it goes into Loading... mode and doesn't come out. If I close the web browser and start again I have to check the object in. Also if I then try to restart or shudown the computer it goes into a wait state so that I have to manually turn off the computer. I have checked apache2 logs and syslog but there is no evidence there of anything going wrong. I have also tried other web browsers without improvement.

It used to go into this mode on a previous version but after some hours of work. Now it goes into this mode straight away. It looks as though it is a Joomla 4 issue. So frustrating!!!

Any ideas?

Regards,

Peter.

Hannes Papenberg

unread,
Jul 4, 2022, 10:42:13 AM7/4/22
to joomla-de...@googlegroups.com
Sounds like your database has an issue. A shot in the dark would be
corrupted database files.
> --
> You received this message because you are subscribed to the Google
> Groups "Joomla! General Development" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to joomla-dev-gene...@googlegroups.com
> <mailto:joomla-dev-gene...@googlegroups.com>.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/joomla-dev-general/9b2abceb-6321-48f4-8466-60a24641211an%40googlegroups.com
> <https://groups.google.com/d/msgid/joomla-dev-general/9b2abceb-6321-48f4-8466-60a24641211an%40googlegroups.com?utm_medium=email&utm_source=footer>.

Peter Tuson

unread,
Jul 5, 2022, 4:30:48 AM7/5/22
to Joomla! General Development
Hello Hannes,

Thanks, you were spot on. The mariadb server had been updated but the database hadn't for some reason.

When systemd starts its up it should check but it was expecting no password for root so the check was failing.

I figured out how to set the actual password for root as part of the start up procedure and it updated the database.

Now Joomla is back to normal.

Regards,

Peter.

Peter Tuson

unread,
Aug 4, 2022, 9:20:21 AM8/4/22
to Joomla! General Development
I have just started back on the API development to see if I can get it going. The documentation has been very useful but I am still getting errors. I have fixed a few but the latest is "detail":"BadMethodCallException: Argument 'fields' of event onApiGetFields must be be an array and not empty" I haven't the foggiest idea why this is being called, what the error is referring to and how to fix it.

Any help would be appreciated.

Peter

MarkRS

unread,
Aug 4, 2022, 11:14:44 AM8/4/22
to Joomla! General Development
My first guess would be that you're missing the protected variables $fieldsToRenderitem and/or $fieldsToRenderList which should be in your class JsonapiView.

These are the fields that need to be output in the relevant situation.

Peter Tuson

unread,
Aug 4, 2022, 11:40:47 AM8/4/22
to Joomla! General Development
Thank Mark, you are correct. I initially had them defined with empty arrays hoping I could get it going and then work out how to improve it.

It is now producing some results.

Regards,

Peter.

Peter Tuson

unread,
Aug 17, 2022, 7:16:22 AM8/17/22
to Joomla! General Development
I have got the curl GET functions working well as they access the database and are best used with administrator models, although I did have to customise some of the basic code.

However I am now having problems with PUSH, where the database is not used. PUSH come with user data, which is used to add the user to a MailChimp database and then an email is returned  to report success.

I have a test.php function to test is, and this is responding with:

*   Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> POST /eluceo/api/index.php/v1/newsletter/resourcenews HTTP/1.1
Host: localhost
Accept: */*
Content-Length: 170
Content-Type: application/x-www-form-urlencoded

* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 17 Aug 2022 11:02:16 GMT
< Server: Apache/2.4.54 (Debian)
< X-Content-Type-Options: nosniff
< X-Powered-By: PHP/8.1.5
< Access-Control-Allow-Origin: *
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8

<
* Connection #0 to host localhost left intact
Response:

I would like to be able to add code to the response so I can track what is going on. In Joomla 3 I could do this with $app->enqueueMessage with a Restful API using the JsonResponse function. How do we do this in Joomla 4?

MarkRS

unread,
Aug 17, 2022, 12:08:59 PM8/17/22
to Joomla! General Development
Wow, there's a lot in there.  I sort of understand the first paragraph, but what customisation of the basic code did you have to do?

After that... errr, what?
Are you saying that when someone signs up to your newsletter on your website, you want to send a request to MailChimp to add them to your list of recipients?

If that's right, what code do you want to add to the response? Where's it going to be seen, on MailChimp?

Peter Tuson

unread,
Aug 17, 2022, 1:23:03 PM8/17/22
to Joomla! General Development

If the user wishes to sign up for newsletters they fill in a form a click submit. This calls a function which submits the request to MailChimp and then responds with a email to the user to confirm the sign up. We have two sites so on the other site the request is sent by a PUSH Rest API to the first site to submit and confirm. It is that PUSH API I am trying to get to work. I test it by running php code in a terminal.

As I said, on Joomla 3 enqueueMessages appeared in the json response so I could track what was going on and correct any problems quite easily.

On Joomla 4, enqueueMessages do not appear in the json response so I do not know how to track. I was hoping someone knew of an alternative.  The MailChimp works correctly on the first site but nothing happens when using the API. I went through a debug process so I know the the API functionality is being used. The eventual response is either pass or fail but I need to track it to find out why it isn't working.

MarkRS

unread,
Aug 17, 2022, 4:33:50 PM8/17/22
to Joomla! General Development
Did you look at the tutorial that GhiaMar referred to?  It helps a bit.

The API "out of the box" returns what would be the content of a page, but in a JSON format.  I'm surprised enqueMessage doesn't give you output, but only slightly.

My answer, as (almost) always is use a visual debugger to run the code and watch what happens.  This is a bit of a problem with curl (iirc), but use a web browser plugin (for example RESTED for FireFox) and you'll be able to catch the call and watch the code run.

As a wild guess from almost nothing to go on, have you set up the necessary path in your plug?

Peter Tuson

unread,
Aug 18, 2022, 4:25:55 AM8/18/22
to Joomla! General Development
I did use the tutorial. It is very useful but doesn't cover everything. I have also put the path in the plugin like:

        $routes = [
            new Route(['POST'], 'v1/newsletter/resourcenews', 'newsletter.newsletter', [], $getDefaults),
        ];
       
        $router->addRoutes($routes);

One of the biggest problems is that there is the same prepareItem function for the display of both lists and item.

I tried RESTED but it doesn't add anything to what I already do.

If I introduce an error it shows that it is following the path, hence I need to track the code.

Regards,

Peter.

MarkRS

unread,
Aug 18, 2022, 6:07:18 AM8/18/22
to Joomla! General Development
RESTED adds the possibility of using a visual debugger when testing API calls. Can you do that with curl?  It doesn't sound like you are already doing that.

Why is there the same "prepareItem" function for both list and item?  You can specify different ones provided the API calls for a list and an item are different. Surely you haven't got them as the same?

Peter Tuson

unread,
Aug 18, 2022, 6:23:19 AM8/18/22
to Joomla! General Development
I can do that with curl within php. The results I got with RESTED were identical with what I get.

I made different prepareItem functions by rewriting the display list and item codes for my cases. By default there is only one function.

I have fixed the problem with my POST. The fundamental problem was that errors in getting supporting models was not reported so I moved the model to a helper.

I also replaced $this->displayItem() with:

echo new JsonResponse($result, 'Newsletter Registration', false);
jexit();

I now get what I expected:

Response: {"success":true,"message":"Newsletter Registration","messages":{"info":["Newsletter","Mail sent, please check your inbox."]},"data":true}

The messages text are enqueueMessages.

I am now going to try and figure out how to include enqueueMessage within the displayItem() response. In the normal web view it is a popup so will not appear on the document by default.

Regards,

Peter.

MarkRS

unread,
Aug 18, 2022, 6:48:15 AM8/18/22
to Joomla! General Development
That's great that you got it working.

How do you get the debugger to work with curl? That sounds great too, I haven't been able to.

My suspicion about why you can't get the enqued messages is that the J! API has created a different JSON output than the one that "JsonResponse" creates.
They have extensive (documented) reasons for this that make sense in the context of a text article based environment,

What I've done, since my requirement is also the JsonResponse format is to write my own JsonDocument class and ApiController.  My API controllers all inherit from my own ApiController, and it uses my JsonDocument class, which is what defines the output format.

Whilst this requires more initial work than just hacking out bits of the system I don't like, it gives me much more functionality, by using the system rather than ignoring it.

Peter Tuson

unread,
Aug 18, 2022, 8:34:33 AM8/18/22
to Joomla! General Development
Hell Mark.
This is an example of the PHP code I use for curl testing:

function newsletter() {
    $url  = 'http://localhost/eluceo/api/index.php/v1/newsletter/resourcenews';
    $today = 'xxxxx';
    $data = array('contact' => array('name' => 'nnnnn', 'email' => 'eeee', 'type' => 'iShine'));
    $data['newtext']    = 'Welcome to Eluceo!';
    $data['captcha']    = $today;
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    $response = curl_exec($ch);
    $error    = curl_error($ch);

    curl_close($ch);

    if ($error) {
        echo "cURL Error #: " . $error;
    } else {
        echo "Response: " . $response;
    }
    echo "\n";
}

I then put the JsonResponse code in the actual code and moved it up the page until it produced some text. That gave me an idea of what was going wrong.

What they have done is all right when using articles etc from the site. But when you have to do alot of processing, for example for mobile phone apps, then it is not very appropriate and I have just made the way I did it on Joomla 3 work for Joomla 4. The work I am doing here is the exchange of information between sites, so only one site has to hold it.

I very much like you idea of having your own library. I will be thinking of that now.

Regards,

Peter

MarkRS

unread,
Aug 18, 2022, 9:12:44 AM8/18/22
to Joomla! General Development
Is this the bit that gives you visual debugging?

Peter Tuson

unread,
Aug 22, 2022, 3:30:52 AM8/22/22
to Joomla! General Development
Mark,

Yes, the verbose option gets curl to tell us what it is doing.

The curl_error identifies any curl errors during the transaction and prints those.

If there is no curl error then it prints the response from the server.

Regards,

Peter.

MarkRS

unread,
Aug 22, 2022, 6:49:41 AM8/22/22
to Joomla! General Development
Right, but that's not visual debugging.

With a local webserver and dbg and a browser you can step through the php code as it runs, see the state of everything at every stage and nail down the errors.

Much easier than trying to guess what might have happened from an error message.

MarkRS

unread,
Aug 22, 2022, 6:50:28 AM8/22/22
to Joomla! General Development
(and a suitable IDE)

Peter Tuson

unread,
Aug 22, 2022, 11:55:10 AM8/22/22
to Joomla! General Development
Mark,

I have got the messages working now. Here is a simple example:

Array
(
    [messages] => Array
        (
            [info] => Array
                (
                    [0] => Document:
                )

        )

    [links] => Array
        (
            [self] => http://localhost/eluceo/api/index.php/v1/university/839
        )

    [data] => Array
        (
            [type] => university
            [id] => 839
            [attributes] => Array
                (
etc

I just use the command  $this->document->setMessages($lists); within the JsonApiView.

I have created a Library folder within my api/src folder with the four child documents ApiController, Document, JsonapiDocument and JsonApiView.

Within the ApiController, I added a construct function with the actions:
        parent::__construct($config, $factory, $app, $input);
        $app->loadDocument(new JsonapiDocument());

Where JsonapiDocument is the child one in the Library.

I copied a prepareMessage function from the JsonResponse class.

Regards,

Peter.

MarkRS

unread,
Aug 22, 2022, 4:59:40 PM8/22/22
to Joomla! General Development

Well done!
Reply all
Reply to author
Forward
0 new messages