Jump to content

possible to detect mobile using php / latte ?


protro
 Share

Recommended Posts

Hello PW forums,

I am using PW & Rockfrontend with the Latte template engine. I see there used to be a mobile detect module but it is no longer available. Is there a way to accomplish simple mobile detection using php in Processwire 3.x.x ?

Thanks,

Link to comment
Share on other sites

Detecting mobile for what reason?

JS can always detect mobile browser, or touch devices or based on display resolution.
CSS can change due to media and/or container queries.
PHP has quite some helpers to do the same.

The module you mentioned might not be updated and compatible anymore but you could look into it to check out how it detected mobile devices.

Btw.: Latte doesn't detect anything. It just helps making templating easier.

  • Like 1
Link to comment
Share on other sites

Thanks for your response @wbmnfktr … I am aware that these things can be done with css/js … I was more interested in trying something outside my familiarity with php.

Here's a follow-up question: how can I write a custom function and access it in a template file in Processwire?

Inside of _init.php I have added a user-agent regex for mobile detection

<?php namespace ProcessWire;
// Optional initialization file, called before rendering any template file.
// This is defined by $config->appendTemplateFile in /site/config.php.
// Use this to define shared variables, functions, classes, includes, etc.

function isMobileDevice() {
// Get the user agent string
$userAgent = $_SERVER['HTTP_USER_AGENT'];

// Check if the user agent matches any common patterns for mobile devices
if (preg_match('/android|iphone|ipod|blackberry|iemobile|opera mobile|palmos|webos/i', $userAgent)) {
return true;
} else {
return false;
}

}

So why do I get: Call to undefined function isMobileDevice()
when trying to access this function with inside of a .latte template:
{if isMobileDevice()}

I might be missing something very simple. This is some new territory for me.
With thanks,

  • Like 2
Link to comment
Share on other sites

Answering my own question in case it is helpful to anyone else.

I am using Processwire and Rockfrontend. I was able to get a custom mobile detection to work using PHP by adding a custom function to _init.php (and taking care to comment out the PW namespace as per RF repo documentation).

<?php // namespace ProcessWire;

// Optional initialization file, called before rendering any template file.
// This is defined by $config->appendTemplateFile in /site/config.php.
// Use this to define shared variables, functions, classes, includes, etc.

function isMobileDevice() {
// Get the user agent string
$userAgent = $_SERVER['HTTP_USER_AGENT'];

// Check if the user agent matches any common patterns for mobile devices
if (preg_match('/android|iphone|ipod|blackberry|iemobile|opera mobile|palmos|webos/i', $userAgent)) {
	return true;
	} else {
	return false;
	}
}

Then I was able to call the function in the normal way with Latte:

{if isMobileDevice() == 'true'}

🙂

  • Like 3
Link to comment
Share on other sites

I wouldn't rely on this regex for mobile detection. There's a great library for that: https://github.com/serbanghita/Mobile-Detect

You can simply copy the MobileDetect.php to site/templates/inc/MobileDetect.php. (If you prefer, you could install it via composer)

And then include it in _init.php and use it like

include_once('./inc/MobileDetect.php');

function isMobileDevice() {
    $detect = new \Detection\MobileDetect;
    return $detect->isMobile();
}

 

  • Like 5
Link to comment
Share on other sites

Unfortunately it seems MobileSupport.php is not supported in PHP 8.x.x versions. I'm getting errors in VS Code on that MobileDetect.php file. I'll keep my eye on this though.

15 hours ago, gebeer said:

I wouldn't rely on this regex for mobile detection. There's a great library for that: https://github.com/serbanghita/Mobile-Detect

You can simply copy the MobileDetect.php to site/templates/inc/MobileDetect.php. (If you prefer, you could install it via composer)

And then include it in _init.php and use it like

include_once('./inc/MobileDetect.php');

function isMobileDevice() {
    $detect = new \Detection\MobileDetect;
    return $detect->isMobile();
}

 

 

 

Link to comment
Share on other sites

38 minutes ago, protro said:

Unfortunately it seems MobileSupport.php is not supported in PHP 8.x.x versions. I'm getting errors in VS Code on that MobileDetect.php file. I'll keep my eye on this though.

 

 

That is strange. I am using the same library for years now (http://mobiledetect.net/), on PHP 8+ i have no problems.

Depending on where you put the mobile-detect files I have this in my _init.php:

require_once '../../vendor/mobiledetect/mobiledetectlib/Mobile_Detect.php';
$deviceCheck = new Mobile_Detect;

Then I can use the following expression to check the device. For example in a PHP template file.

if (!$deviceCheck->isMobile()) {
	echo "this is not mobile";
}

 

  • Confused 1
Link to comment
Share on other sites

Hey guys could you please help me: Why would one detect mobile/desktop on the server side? Isn't that a thing for the frontend and with ProCache you can't use tools that rely on PHP. So could you please share some background? Thx 🙂 

  • Like 1
Link to comment
Share on other sites

17 minutes ago, bernhard said:

Hey guys could you please help me: Why would one detect mobile/desktop on the server side? Isn't that a thing for the frontend and with ProCache you can't use tools that rely on PHP. So could you please share some background? Thx 🙂 

I am using mobile detect to switch between different markups on mobile / desktop.  
For example on mobile I am using a different image format than on desktop devices. 
It would be much easier to make use of css media queries but in that case I do not want to load images that I do never display on a particular screen width.

$imgFormat = 'title-img';

if ($deviceCheck->isTablet()) {
    // Tablet
    $imgFormat = 'title-img-tablet';
}

---

and then:

 <img data-srcset="<?php echo $image->size($imgFormat)->srcset() ?> [...]

Another example is the usage of html data attributes that vary on mobile/desktop devices: When using an animate on scroll plugin like aos.js you put your animation properties inside these data attributes. On desktop you might want animation A with duration X while on mobile you want animation B with duration Y. 
I set those properties via the mobile detect queries.

<div class="feature-item-icon" data-aos="flip-right" data-aos-delay="<?= (!$deviceCheck->isMobile() && !$deviceCheck->isTablet()) ? $key*250 : '250'?>" data-aos-offset="200">
  <img class="img-fluid" src="<?=$icon->url?>" alt="Feature Icon"/>
</div>

The major drawback is: the detection is server side. It is not responsive like css media queries where you see new properties instantly when switching through the breakpoints. Instead you have to reload the page to get the new values. 
In most cases this is no problem though. 

  • Like 1
Link to comment
Share on other sites

2 hours ago, Stefanowitsch said:

Instead you have to reload the page to get the new values. 

I usually use this (or similar) extensions when I use Mobile Detect while developing. Switching the user agent to mobile and not having to reload manually the page every time. Then revert back when done.

  • Like 1
Link to comment
Share on other sites

13 hours ago, protro said:

Unfortunately it seems MobileSupport.php is not supported in PHP 8.x.x versions. I'm getting errors in VS Code on that MobileDetect.php file. I'll keep my eye on this though.

On 12/9/2022 at 9:19 AM, gebeer said:

I would not have expected this since the lib is actively maintained and used by many projects. But in the github issues I saw that the author seems to be working on PHP 8 support.

12 hours ago, bernhard said:

Hey guys could you please help me: Why would one detect mobile/desktop on the server side? Isn't that a thing for the frontend and with ProCache you can't use tools that rely on PHP. So could you please share some background? Thx 🙂 

Most things we can do with CSS/JS but if you want to deliver completely different content for mobile devices, doing it on the PHP level is a viable option. Caching is a problem, though and needs some extra attention.

 

12 hours ago, Stefanowitsch said:

For example on mobile I am using a different image format than on desktop devices.

Personally I would solve this through img srcset and size attributes. No need for separate code here.

  • Like 1
Link to comment
Share on other sites

19 hours ago, protro said:

Very strange @Stefanowitsch. I copied into my project MobileDetect.php and am receiving this error in my env (MAMP using PHP 8.0.8)
 

syntax error, unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST)

If the error message is pointing to the correct line, then this does not look like a PHP 8 issue. That line should be valid in PHP 7.4 or any later version.

I would double check that you're running the code on correct PHP version, and also that this is an actual error you get while running the code (not just in your code editor, where the check may potentially be performed by locally installed PHP or something along those lines).

There may, of course, be other PHP 8 incompatibilities in the library 🙂

Link to comment
Share on other sites

On 12/9/2022 at 8:21 PM, Stefanowitsch said:

I am using mobile detect to switch between different markups on mobile / desktop.  

That is very counterproductive. Google might derank your page based on this (Don't know if it is still the case, but it was). Also it is never a good thing to optimize something to specific devices or resolutions. Design for EVERY device. Use progressive enhancement instead of using the user agent string or some other detection for the browser. User agent strings can be manipulated and are not reliable! Also future browsers wouldn't be taken into account. Browser detection is a thing of the past and should be abandoned, as there is no need for it.

If you want different images for different resolutions or landscape and portrait view modes, there are media queries for this purpose.

On 12/9/2022 at 8:21 PM, Stefanowitsch said:

but in that case I do not want to load images that I do never display on a particular screen width

Thats exactly what media queries are for. You can even do art direction (display different images on different viewports) with different display modes depending on the display. 

DO NOT USE BROWSER DETECTION. PERIOD!

  • Like 1
Link to comment
Share on other sites

2 minutes ago, dotnetic said:

That is very counterproductive. Google might derank your page based on this (Don't know if it is still the case, but it was).

With dedicated sub-domains this isn't really an issue but it brings other challenges as Google expects a super highly optimized version then.
So... choose your challenge. 😄

It's also not that big of a problem on trusted high-traffic sites as reducing HTML/source load is a very good reason in those cases. Google respects that.

Here comes the big BUT... most sites can't offer a super optimized sub-domain version, neither are high-traffic, nor are they that trusted by Google.
So if you aren't maintaining a 20-25+ year old financial, automotive, insurance, Fortune 500, or media/news outlet site... I highly support the following statement:

13 minutes ago, dotnetic said:

DO NOT USE BROWSER DETECTION. PERIOD!

(all of the above excludes member areas and sites Google/Bing/... can't officially crawl or see.)

  • Like 3
Link to comment
Share on other sites

thanks for chiming in @dotnetic @teppo @gebeer I will re-consider the approach in my template.

I was hitting performance issues with video thumbnails on mobile so I wanted to cancel displaying them if the user was on mobile (via Latte template query) and display a still image instead, but I guess this was the wrong approach.

I will see if I can tackle the template logic differently and explore @media queries in CSS further.

Many thanks for the feedback.

  • Like 1
Link to comment
Share on other sites

For YouTube videos... just use:

https://orestbida.com/demo-projects/iframemanager/demo1/ or any other minimal YouTube solution with a placeholder as cover.

If you hit a performance issue just with video thumbnails... mobile detection isn't your solution.
In this case you probably have way bigger problems.

Let's start with the basics:

  • How many videos are on that (single) site/page?
  • How large (in kb) is the poster/cover in average for a video?
  • Where does that poster/cover come from?
  • Are images lazy loaded if possible?
  • How do you know there is a performance issue?
  • Do you pay more than $0,99/month/year for hosting?

Tell us more.

I ran quite busy sites on cheap shared hostings solutions (H*stgator, Dr*amh*st, H*stnun,... and similar) without almost any issues.

  • Like 2
Link to comment
Share on other sites

10 hours ago, dotnetic said:

That is very counterproductive. Google might derank your page based on this (Don't know if it is still the case, but it was). Also it is never a good thing to optimize something to specific devices or resolutions. Design for EVERY device. Use progressive enhancement instead of using the user agent string or some other detection for the browser. User agent strings can be manipulated and are not reliable! Also future browsers wouldn't be taken into account. Browser detection is a thing of the past and should be abandoned, as there is no need for it.

This is not the case. On some applications progressive enhancement is not possible (or let's say: ideal) because of the technological structure or other reasons.

I am working for one of the biggest online stores in germany and for mobile/desktop devices we absolutely use browser detection and I am pretty sure most of the industry does.

When visiting a product page there is a switch in the master template which then leads either to a mobile or desktop markup. These markup files share the same data source but code wise they are entirely different from each other. The reason behind this is that there was a completely different approach on how google ranked those mobile sites in the past AND since there are tons of elements and features (like custom written plugins) on the pages that massively differ depending on the device you're using this makes maintaining the code a bit easier. You have to load less/different assets, but it does add work when you have to make changes to both the desktop and mobile versions.

Loading speed is an important ranking factor too, that's why you want to load only scripts and assets on your mobile page that you really need. Another reason why we use this approach. It's a giant application, though. On my private (and way simpler) ProcessWire projects I am sticking to progressive enhancement if possible.

10 hours ago, dotnetic said:

If you want different images for different resolutions or landscape and portrait view modes, there are media queries for this purpose.

Thats exactly what media queries are for. You can even do art direction (display different images on different viewports) with different display modes depending on the display. 

For images this will work. But I would never advice someone use media queries to hide elements with important content (SEO stuff) with "display: none" on any application. Just because google nowadays ignores this kind of content. Render the markup and the content that google needs to see (mobile first because mobile sites have top priority to google). And as you said: Take the same element and just make it look good on any device by using media queries.

As I said I only use this browser detection for changing data-attributes or (only in one or two cases) the image format for a title image.

Even advanced plugins like aos.js or high-end frameworks like UIKit are NOT responsive in some cases (https://getuikit.com/docs/animation). What do you do when you want to alter an animation based on the device? You have to somehow detect it and change the markup.

  • Like 1
Link to comment
Share on other sites

1 hour ago, Stefanowitsch said:

What do you do when you want to alter an animation based on the device?

Why would you even do that? What you mean when you are talking about "device"? Do you mean resolution? Then use media queries. Do you mean specific features? Then use feature detection. What is the specific use case, that can't be handled via normal media queries or window.matchMedia and feature queries?

1 hour ago, Stefanowitsch said:

On some applications progressive enhancement is not possible (or let's say: ideal) because of the technological structure or other reasons.

Maybe that is the problem, because the application has grown over time and now you can not easily change it to use best practices.

1 hour ago, Stefanowitsch said:

I am working for one of the biggest online stores in germany and for mobile/desktop devices we absolutely use browser detection and I am pretty sure most of the industry does.

I work in this industry since 1999 and know that browser detection is a thing of the past and preached by webexperts (I count myself to that, not in all areas, but many) everywhere not to use it. Even if many companies should still use it (which I believe is not true, or they might have legacy websites), that doesn't make it right.

I also worked on over 100+ projects (international and national) and my company moved from using browser detection very long ago. Never had something that we couldn't do without it.

1 hour ago, Stefanowitsch said:

Loading speed is an important ranking factor too, that's why you want to load only scripts and assets on your mobile page that you really need

Exactly, thats why you would load scripts conditionally via the import() expression via JS modules (all evergreen browsers support this). Stylesheets can be loaded depending on a media query to target specific media.

I think the main problem what we talking about here is, that you have a legacy webpage/application, which could not be easily transformed to use best practices. The second one is the definition of "mobile" or "device" and what should be possible or not with that device.

1 hour ago, Stefanowitsch said:

But I would never advice someone use media queries to hide elements with important content (SEO stuff) with display: none on any application

I neither wouldn't do that, because it is a bad practice.

1 hour ago, Stefanowitsch said:

As I said I only use this browser detection for changing data-attributes or (only in one or two cases) the image format for a title image.

 

You can do this via JavaScript with the matchMedia method, if we are talking about viewport width.

If you have specific questions how you might tackle your problem, we might give you suggestions here.

  • Like 1
Link to comment
Share on other sites

26 minutes ago, dotnetic said:

Why would you even do that? What you mean when you are talking about "device"? Do you mean resolution? Then use media queries. Do you mean specific features? Then use feature detection. What is the specific use case, that can't be handled via normal media queries or window.matchMedia and feature queries?

So basically it all depends on the screen width here.

Take this for example. How do you change data-attributes or custom code inside HTML elements depending on the screen width directly inside your markup? For example when the plugin does not have responsive options.

<div class="uk-card" uk-scrollspy="cls: uk-animation-slide-left;">
  <p>Hello World</p>  
</div>

I want to change the properties of the uk-scrollspy attribute for example. A different animation on small (=mobile) screens or maybe no animation at all. UIKit does not offer such responsive options (yet).

For that I would use the detect-mobile library like this:

<div class="uk-card" uk-scrollspy="<?= (!$deviceCheck->isMobile()) ?  'cls: uk-animation-slide-left': 'cls: uk-animation-slide-bottom' ?>">
  <p>Hello World</p>  
</div>

When resizing the window this change is not applied though, I have to reload the page to make it happen.

(t might confuse some plugins that read those values on DOM ready but hat is another story)

  • Like 2
Link to comment
Share on other sites

You could achieve this if you are using your own custom CSS animation:

Take a look at my Codepen example Uikit scrollspy animation different on viewport width (codepen.io)

You can see, that I use a media query to trigger the different directions of the animation

@keyframes my-animation {
    0% {
        transform: translateX(-100%)
    }
    100% {
        transform: translateX(0)
    }
}

@media(min-width: 768px){
  @keyframes my-animation {
    0% {
        transform: translateY(100%)
    }
    100% {
        transform: translateY(0)
    }
 }
}
<div class="uk-child-width-1-3@m" id="animateMe" uk-grid uk-scrollspy="cls: uk-animation-slide-bottom; target: .uk-card; delay: 300; repeat: true">
    <div>
        <div class="uk-card uk-card-default uk-card-body" uk-scrollspy-class="my-animation">
            <h3 class="uk-card-title">Animation based on viewport width</h3>
            <p>On a small viewport I slide into your DMs from the left.</p>
          <p>On a large viewport I sneak in from the bottom.</p>
          <p>Resize the window and click on me me to trigger the animation again.
        </div>
    </div>
   
</div>

 

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...