I’m refactoring my code and i’m trying to setup shared controllers and moving some common logic into them. I think I have set it up right, according to this post by @jenstornell but I get a whoops when try to use it. It DOES however work, if I put the code into the controller that belongs to the template, without trying to share code (which is the way nature intended).
So for instance i have a newsarticle.php
in the controllers folder containing this:
<?php
require_once kirby()->roots()->controllers() . '/shared/global.php';
My global.php
looks like this:
<?php
return function($site, $pages, $page) {
// Article Image
$articleimgsrc = $page->articleimage()->toFile();
if($articleimgsrc) {
$articleimage = brick('img');
$articleimage->attr('src', $articleimgsrc->url());
$articleimage->attr('alt', $articleimgsrc->alt());
$articleimage->attr('style', 'max-width:'.$articleimgsrc->width().'px');
$articleimage->addClass('articleimage');
} else {
echo 'Article image is missing';
}
// pass these off to the template
return compact('articleimage');
};
And my template tries to use it like this:
<?= $articleimage ?>
However, i get a whoops. If i put the contents of the global.php
into the controller for newsarticle.php
it works
What am i doing wrong?
texnixe
November 23, 2017, 4:20pm
2
$articleimage
is not defined in the else
-case.
I think you mean change it to this:
<?php
return function($site, $pages, $page) {
// Article Image
$articleimgsrc = $page->articleimage()->toFile();
if($articleimgsrc) {
$articleimage = brick('img');
$articleimage->attr('src', $articleimgsrc->url());
$articleimage->attr('alt', $articleimgsrc->alt());
$articleimage->attr('style', 'max-width:'.$articleimgsrc->width().'px');
$articleimage->addClass('articleimage');
} else {
$articleimage = 'Article image is missing';
}
// pass these off to the template
return compact('articleimage');
};
I still get a whoops though, $articleimage
undefined. It should not be getting that far anyway, because the image field does have a value. It only works if i put it directly into the controller belonging to the corresponding template.
texnixe
November 23, 2017, 4:54pm
4
I don’t get a variable notice but an headers already sent. If I change it to this:
template specific controller:
<?php
return function($site, $pages, $page) {
require_once kirby()->roots()->controllers() . '/shared/global.php';
return [
'articles' => $articles,
'pagination' => $articles->pagination()
];
};
global.php
<?php
$perpage = $page->perpage()->int();
$articles = $page->children()
->visible()
->flip();
->paginate(($perpage >= 1)? $perpage : 5);
}
$articles = $articles->paginate(1);
it works.
Awesome. That did the trick! Thanks @texnixe
Actually, is there a way to pass options? I want to be able to crop or resize the image so can I do something like:
<?= $articleimage(600, 300) ?> // 600 width, 300 height
I cant see anything in the docs for doing something like that, is it possible?
I know i can do <?= $articleimage->resize(600, 300) ?>
but i was looking to shorten the typing
texnixe
November 23, 2017, 5:55pm
7
A variable is not a function. But you can, of course, create a function that you can pass your parameters to.
Right… this is driving me nuts.
So ive turned it into a function like this:
function imagetag($mode, $width, $height){
$articleimgsrc = $page->articleimage()->toFile();
if($articleimgsrc) {
if ($mode == 'resize') {
$articleimage = brick('img');
$articleimgsrc = $articleimgsrc->resize($width, $height);
}
if ($mode == 'crop') {
$articleimage = brick('img');
$articleimgsrc = $articleimgsrc->focuscrop($width, $height);
}
$articleimage->attr('src', $articleimgsrc);
$articleimage->attr('alt', $articleimgsrc->alt());
$articleimage->attr('style', 'max-width:'.$articleimgsrc->width().'px');
$articleimage->addClass('articleimage');
} else {
$articleimage = brick('p', 'Article Image Not Set');
}
}
Which im using im my template like:
<?= imagetag('resize', 300, 200) ?>
But i get whoops because it cant see $page
if i change that to page()
i get an empty result… sigh … how can it work out side of a function and not side? Im guess i need to tell the function about $page
but there i am lost…
texnixe
November 23, 2017, 9:51pm
9
Two things (if I haven’t overlooked anything, am a bit tired):
you need to pass the page to the function as a parameter
your function does not return anything, so it is quite useless;) It has to return $articleimage
function imagetag($page, $mode, $width, $height){
// bla bla bla
return $articleimage;
}
Call
<?= imagetag($page, 'resize', 300, 200) ?>
Ahh of course.
texnixe:
so it is quite useless;)
yup… sums me up. Tired to… hot chocolate time…
So it goes further now i have done that… but i get a whoops lower down, when it hits $articleimage->attr('alt', $articleimgsrc->alt());
Call to undefined method Asset::alt()
texnixe
November 23, 2017, 10:01pm
12
Now let’s clean this up a bit to keep your code DRY:
function imagetag($page, $mode, $width, $height){
if($articleimgsrc = $page->articleimage()->toFile()) {
if ($mode == 'resize') {
$articleimgsrc = $articleimgsrc->resize($width, $height);
}
if ($mode == 'crop') {
$articleimgsrc = $articleimgsrc->focuscrop($width, $height);
}
$articleimage = brick('img');
$articleimage->attr('src', $articleimgsrc);
$articleimage->attr('alt', $articleimgsrc->alt());
$articleimage->attr('style', 'max-width:'.$articleimgsrc->width().'px');
$articleimage->addClass('articleimage');
} else {
$articleimage = brick('p', 'Article Image Not Set');
}
return $articleimage;
}
texnixe
November 23, 2017, 10:05pm
13
You can’t call alt on the resized image.
function imagetag($page, $mode, $width, $height){
if($articleimgsrc = $page->articleimage()->toFile()) {
if ($mode == 'resize') {
$thumb = $articleimgsrc->resize($width, $height);
}
if ($mode == 'crop') {
$thumb = $articleimgsrc->focuscrop($width, $height);
}
$articleimage = brick('img');
$articleimage->attr('src', $thumb);
$articleimage->attr('alt', $articleimgsrc->alt());
$articleimage->attr('style', 'max-width:'.$thumb->width().'px');
$articleimage->addClass('articleimage');
} else {
$articleimage = brick('p', 'Article Image Not Set');
}
return $articleimage;
}
Well thanks, very much … still get the error above though.
Oh man…finally… no more whoops… thanks very much @texnixe
lol… i’m so tired i’ve been starring at this for hours, and didn’t even notice i haven’t added a width and height attribute…
… and so to bed.
Just noticed its building a malformed tag, but I’ll sort that tommorrow…
<img src="<img src="//localhost:3002/thumbs/news/news-article-one/shareimagehome-300x158.png" alt="">" width="300" height="200" alt="" style="max-width:1200px" class="articleimage">
texnixe
November 23, 2017, 10:31pm
18
I just found another error. This line:
$articleimage->attr('src', $thumb);
should be
$articleimage->attr('src', $thumb->url());
This is working a treat now.
My only niggle is having to put $page
in the tag every time:
<?= imagetag($page, 'crop', 1140, 400) ?>
Is there a way to put that somewhere else, since its always $page
.?
texnixe
November 24, 2017, 10:00am
20
You could use a page model, a custom page method or a custom file method instead, depending on where you want to use this function. If it is just related to one template, I’d opt for a page model.