Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/26/2014 in all areas

  1. Today I've created a really simple little module that is configurable and attaches to hooks. So it has more or less everything of a real world module in it. I thought processwire beginners would be interested in reading how to create such a module so I added some comments to the source code in a way the module should explain itself... Here it is: /** * BackgroundChanger module for demonstration purposes * * Demonstrates the Module interface and how to add hooks in a more real world manner... * * ProcessWire 2.x * Copyright (C) 2014 by Domenic Helfenstein * */ class BackgroundChanger extends WireData implements Module, ConfigurableModule { public static function getModuleInfo() { return array( /* * the __("text") methods are used for multilanguage support * see: https://processwire.com/api/multi-language-support/code-i18n/ */ 'title' => __('BackgroundChanger'), 'summary' => __('This is a simple real world module that can change the background color.'), 'version' => 105, /* * autoload must be true if the module depends on hooks * see: http://wiki.processwire.com/index.php/Module_Creation#Details_of_what_the_.22autoload.22_property_means */ 'autoload' => true, /* * it is wise to run modules in singular mode when using hooks * see: http://wiki.processwire.com/index.php/Module_Creation#Details_of_what_the_.22singular.22_property_means */ 'singular' => true, ); } public function __construct() { //set default values $this->backgroundColor = 'yellow'; /* * !!! the value in the db will be automatically injected into this var * because it is named equal to the value of $field->name in * getModuleConfigInputfields !!! */ } public function init() { // add a hook after each page is rendered and modify the output $this->addHookAfter('Page::render', $this, 'changeBackground'); } public function changeBackground($event) { $page = $event->object; //do only modify non-admin pages if($page->template == 'admin') return; $extension = <<< _OUT <style> body {background-color:{$this->backgroundColor};} </style> _OUT; $event->return = str_replace("</head>", $extension."</head>", $event->return); } public static function getModuleConfigInputfields(array $data) { //create a fieldset $inputfields = new InputfieldWrapper(); //create field for background color $field = wire('modules')->get('InputfieldText'); $field->name = 'backgroundColor'; $field->label = __("Enter the hex-code or name of the desired background color. (visit colorpicker.com)"); //if there is already a value stored, set this value to the field if(isset($data['backgroundColor'])) $field->value = $data['backgroundColor']; //add the field to the fieldset $inputfields->add($field); //return the fieldset to display return $inputfields; } } I hope this helps others creating their own modules! BackgroundChanger.module
    12 points
  2. My second website launched with Processwire ( Haven't posted the first one because we're planning to launch the multi language version soon ) This one is german as well, but as there is no planned english version I'm posting it anyways. It's a pretty simple page except the time tables. My head went crazy a couple of time, because I'm in my early PHP stages ^^ Actually it's a relaunch of a Joomla page which was from 1960 or something They created the time tables with a wysiwyg desktop editor and uploaded them separately My personal goal was to simplify this process so I decided to customize FieldtypeEvents module to have easy creation of course schedules and nice automation of the browser and pdf output. PDF creation is already described here How To Create Pdfs With Pw And Mpdf Now they only need their PW type in some course facts hit save and good to go hehe Uhm, my head is still working on the other website, so I stop writing now. Questions, feedback, bugs and anything else are appreciated Oh, the link^^ here you go www.Yoga-Lounge-Berlin.de Update: Got a screenshot from the one. As you can see, we only made some little color adjustments. Update 2: the search engine works like I described here https://processwire.com/talk/topic/6016-capture-user-search-queries/?p=63882 So it spits out results for yoga and joga.
    6 points
  3. What about this: $np = $pages->clone($page); $np->of(false); $np->title = 'New Page'; $np->name = 'newpage'; $np->save();
    3 points
  4. I have not found any topic to report issues on the processwire site and forum and/or make suggestions about them, so I made this one. If such a topic or branch already exists, it should be there. On PW site there is now Docs menu item instead of the API (as it used to be). But on the forum it is still API. They even lead to different pages. I guess this should be fixed.
    2 points
  5. Hi All, I am experienced PHP developer and I have made number of my own CMS systems, so that I think I should be OK with learning Process Wire. I found the Process Wire being the best fit for my projects as I can see it is very mature CMS and it has great flexibility and I have chosen it for number of new projects I am developing myself. However I have trouble starting up as my projects are not standard websites, but they are websites, and what I want to do is always very hard to do anyway, which is basically allowing certain users to fill forms and submit them, and then preview the list of submitted forms. I would like to achieve the following: 1. That I have a page were I list current jobs and their statuses, e.g. list of Tasks. 2. That the page has restricted access, e.g. user needs to logon to view the page, however granunar permissions wont be required (eventually added later) 3. The user would be able to submit new job via form by simply filling it up 4. I would like to create several such "modules", where there are various task lists and forms and restrict permissions to various users. I went thru all the code and documentation however I am bit confused because I am totally new to Process Wire. Previously I was trying to make it into the admin page but now I can see the front page should be better fit. I am going now thru the Wiki Regarding the job execution, this part is already working, I am using Gearman to process tasks and update statuses as well send notifications. This is handled by external database, and it's not required for Process Wire to handle this part for the moment. In essence, I would like to ask you what would be the high-level steps to create the list and the form (search would be also good) and then make it restricted for certain users. I am working on this myself so no hurry with answer, if I figure it out I will post as soon as I have it. In my own CMS, I used to do it in the following way: 1. To create a form: $form = new Form('newTask'); $form->addField('Task Name'); $form->setAction('submitTask'); ... $page->add($form); $page->render(); 2. To list the tasks $table = new Table(); $table->label = 'Tasks List'; $data = $tasks->getTasks('somefilter'); foreach($data as $task) { $table->addRow($data->id, $data->text, array('edit', 'delete')); } ... $page->add($table); $page->render(); With the above I can submit new form, list objects, and I could also make group edit and so on. The whole code would be in single module, and that module would be restricted per role e.g. only edit, only delete, only view. The tasks were stored in single table, and the fields were defined in the xml file, so that when xml file was updated, the MySQL schema was as well. In the XML file there were the field types used to rendrer correct fields, e.g. textarea, text, checkbox etc. many thanks for your help, Bryslon
    2 points
  6. Anything that adds to the learning process is appreciated. Thanks for the effort.
    2 points
  7. The selector for counting would look like this: images.count>11
    2 points
  8. I have to show another ProcessWire while about 10 000 guest are entering the festival area. We've made this site exactly 125 days ago and while it's not our best page, it has some kind of interesting background story. URL: http://www.openbeatz.de/ This is a website for a german two-day electro festival. Some better-known DJs will be playing there and thousands of guest are expected (They hope to sell the ticket no 10000 this evening). The website features basic information pages, a DJ voting contest with FB integration and a overview of all ticket stores. It's build with ProcessWire 2.4 using FormBuilder and the AIOM module. How we got started Our existing client asked for a "small countdown page". They bought the "rights" of the festival and needed something quick to start the promotion. The problem? We didn't even had access to the domain but they printed the first batch of ads and flyers with the URL on it. The first mail came on Wednesday and the site should go online on friday. Don't we all love those kind of challenges... As expected, the site requirements started to grow. We didn't had time for proper project management or any kind of planing. The whole site was build quick and dirty in under a week. We hired another coder to help us. The site is far from perfect, we know. It's hard to get the best results without proper communication and the lack of time. Anyway, the site was online and features were added quickly. The festival last year had about 2000 attendees. We saw the line up after we build the site and that was the point we realized, that our client had something bigger in mind... The Domain The domain was already printed on thousands of flyers when we first heard of the project. At that time, the old agency deleted the domains without a notice to us. We could get the open-beatz.de one but a domain shark got the name without the - . This stuff can get really expensive so we had to negotiate withe the new, unwanted domain holder. After some mails we got down from 5000€ to a smaller three-digit price. Lesson learned (and paid). The DJ Voting DJs could apply with a sample soundcloud set. The DJ with the most Votes (in form of FB likes) will play at the festival. The whole contest was embedded within a facebook application tab. The page had 406 DJs listed with a sum of around 11k likes. A DJ was represented with a PW pages were we counted the likes on that URI using the FB API. The contest is now hidden but you can see an example page here: www.openbeatz.de/dj-contest/wildchild/ The TV ad and numbers You open Facebook and then you see the status "OpenBeatz TV ad in 5 minutes on RTL". Great, why did nobody tell us? The site was featured in multiple ads on the german RTL and RTL2 (larger) tv stations with the URL at the end. There were even ads at prime times like 19:00 and 20:00. Traffic peaked between 2000-4000 additional unique visitors after each clip. ProcessWire took it like a champ even without ProCache. For the stat nerds: 72% of those visitors in the time after the TV ads were on mobile. In total we had an average of 1700 unique visitors every day with a peak of 11k visitors. The site was also shared on the artists facebook pages which brought another 1000 visitors within a 30 minute time frame. What did we learn? Plan ahead and communication. Make double tripple sure that your client tells you all the details and the size of the project. We started to small. If there is no time don't rush. If I could travel back in time, I would just delay that stupid countdown page for a week and plan a better version of the PW site. Planning for the next OpenBeatz festival website will start in two weeks. Next time we will be prepared and launch a better site with lots of useful and cool features. Again, using ProcessWire Ideas are welcome. One more thing: The whole site isn't a site on its own. It's just part of the Rocking High website using the Multisite module. But I thought a new thread in the showroom was appropriate. Have a nice week end!
    2 points
  9. I found (after 2-3 Projects using PW) that it's a good technique to use templates in a way I think hasn't been thought of yet really by some. (Although the CMS we use at work for year, works this way.) I'm sure I'm maybe wrong and someone else is already doing something similar. But I wanted to share this for everybody, just to show alternative way of using the brillant system that PW is. Delegate Template approach I tend to do a setup like this: - I create a main.php with the main html markup, no includes. So the whole html structure is there. - I then create page templates in PW without a file associated. I just name them let's say: basic-page, blog-entry, news-entry... but there's no basic-page.php actually. - Then after creating the template I make it use the "main" as alternative under "Advanced" settings tab. So it's using the main.php as the template file. - This allows to use all templates having the same php master template "main.php" - Then I create a folder and call it something like "/site/templates/view/", in which I create the inc files for the different template types. So there would be a basic-page.inc, blog-entry.inc ... - Then in the main.php template file I use following code to delegate what .inc should be included depending on the name of the template the page requested has. Using the TemplateFile functions you can use the render method, and assign variables to give to the inc explicitly, or you could also use just regular php include() technic. <?php /* * template views depending on template name * using TemplateFile method of PW */ // delegate render view template file // all page templates use "main.php" as alternative template file if( $page->template ) { $t = new TemplateFile($config->paths->templates . "view/{$page->template}.inc"); //$t->set("arr1", $somevar); echo $t->render(); } <?php /* * template views depending on template name * using regular php include */ if( $page->template ) { include($config->paths->templates . "view/{$page->template}.inc"); } I chosen this approach mainly because I hate splitting up the "main" template with head.inc and foot.inc etc. although I was also using this quite a lot, I like the delegate approach better. Having only one main.php which contains the complete html structure makes it easier for me to see/control whats going on. Hope this will be useful to someone. Cheers
    1 point
  10. Well allow_url_fopen can only be set in the php.ini file (or your apache conf file). Take a look at this list which can come in very handy: http://docs.php.net/manual/en/ini.list.php While there is some risk in having this enabled, I'd say that it is a pretty common requirement to have this available, so I wouldn't worry too much about it. If you're really concerned, it is possible to enable it via your apache conf / htaccess file instead and that way you can limit it to specific directories, eg: <Directory /var/www/wire> php_admin_flag allow_url_fopen on </Directory> You could even limit it to a specific file if you wanted, but I wouldn't get too carried away. I'd be curious to know whether your host also blocks curl and file_get_contents and whether Ryan could implement (if it isn't already in there) an alternative using these. Maybe others will chime in with their opinions too.
    1 point
  11. Great - let me know how it goes for you. Thanks for the inspiration for putting it together!
    1 point
  12. From, yes, but not living there anymore. I'm in spain currently. And heading more tropical next month By the way, I really like your avatar hehe
    1 point
  13. This is an Error regarding "ProcessCropImage" = Thumbnails You should look there, I think it can belong to this: https://processwire.com/talk/topic/643-release-thumbnails/page-17#entry66437
    1 point
  14. CHMOD 777 (on shared hosting at least) could be very bad pwired. If the server is configured badly, like a lot of cheap ones out there probably are, 777 gives everyone on the server the ability to affect your files. There are plenty of posts about this on the internet if you do a quick search - here's one: http://stackoverflow.com/questions/11271596/how-will-a-server-become-vulnerable-with-chmod-777 If you're not on shared hosting then you're safer, but 777 is about the most open permission you can apply to a file or folder. You would need to read up on CHMOD really (I think I need to as well as it's been a while) as what permission you can realistically tighten it up to depends on how PHP is installed (mod_php etc) and I honestly don't know enough about the subject. Your recommendation of 777 just rang alarm bells with me because that's basically "anyone can read, write or execute this file" whereas something like 755 means "owner" can read, write and execute, but "group" and "others" (others being everyone else I believe) can only read and execute the file. Other folks here might be able to tell us if it's even an issue nowadays, but I just remember a lot of scripts a few years back that told you to set certain permissions on certain folders.
    1 point
  15. This is one thing that Zend Framework nailed perfectly; in typical setup your entire application lives one level beyond what's directly accessible from the web. I liked it, and it's also something that the security chapter of Programming PHP and the OWASP PHP Security Cheat Sheet suggest.
    1 point
  16. Prerequisites: Basic knowledge of git and git submodules A git hosting solution (e.g. GitHub) No aversion against bash commands Once you've built a couple of websites with it, a set of your own personal must-have modules emerges. For me, such a module and always the first install of the day is Soma's MarkupSimpleNavigation. But there's also MarkupSitemapXML. And so on. Depending on your usage of ProcessWire, the type of pages you build with PW or your customers, your set of modules may differ. Installing modules and functionalities that you'll need in most instances should be an automated and easy process. ProcessWire itself offers a range of possibilities to do so. First, there is installation via ClassNames: In Backend, chose "Modules", then "New" and paste or type in the class name the desired module established in the PW ecosystem, for example `LoginPersist`. From that point on, the particular module gets downloaded and installed within two clicks and just a matter of seconds. Rinse and repeat until your starter module set is complete, but be sure to memorize or note the correct class names. Secondly, you can create an own starter site profile with your modules in it. This not only gives you the means to bootstrap in a module related way but also many possibilities for template and field groundwork. But a disadvantage (on the module site) remains: Unless you control and update all the modules in your site profile, only certain, possibly outdated versions will be installed - and you have to manually update them afterwards. For my last few projects I found a third way: Bundling all starter/must-have modules together in a git repo, using the modules as git submodules. After ProcessWire installation on my local machine, I just clone this bundle and recursively pull every module's master to its latest commit. An example (with my set of starter modules): cd site/modules && git clone --recursive git@github.com:marcus-herrmann/ProcessWire-BootstrapModuleSet.git && cd ProcessWire-BootstrapModuleSet && git pull --recurse-submodules What does this code do? At first, let's assume you've navigated via the terminal to you ProcessWire's installation root folder. Afterwards, these steps follow: 1. Change directory to module folder 2. Clone your bundle repo 3. Change directory to the folder created by aforementioned bundle repo clone 4. Pull all submodules to their latest commit That's all. After you've created your own module bundle repo, you can even create a bash alias for this and accellerate the process even more: alias getpwstartmodules='cd site/modules && git clone --recursive git@github.com:marcus-herrmann/ProcessWire-BootstrapModuleSet.git && cd ProcessWire-BootstrapModuleSet && git pull --recurse-submodules' I possibly may have reinvented the wheel. But at least I haven't yet found such a way for "PW kickstarting" before (apart from maybe pure bred package managers such as npm and composer). But if a better solution exists, please do not hesitate to drop a comment here Disclaimer: This is also a blog post
    1 point
  17. Now available in the modules directory: http://modules.processwire.com/modules/password-force-change/ For anyone who might have downloaded early on, please grab the latest version. There was an important fix two days ago that now prevents users from simply navigating away from their profile page to another page in the admin. Now they can't do anything in the admin until their password has been changed.
    1 point
  18. How about this? Starter - $page Newbie - $page->name Jr Member - $pages-get("postCount > 10") Full Member - $config->urls->root sr Member - $config->urls->core Hero Members - $page->created <= 1292025599
    1 point
  19. @sins7ven - thanks for sharing the script! I agree with horst on this. I think this version should be much safer, although it might need some more thought. $fn = wire('input')->get->file; $pid = (int) wire('input')->get->pageid; $p = wire('pages')->get($pid); $filename = $p->logo_file->get("name=$fn")->filename; Firstly, it makes sure that pageid is an integer (so that no-one can try entering a path instead) and then gets the page object from that integer. Then it finds the file in the logo_file field that matches the name in $fn. This ensures that the file path in $filename can only be a file from the logo_file field and that it is a valid file in the PW database. You might also want to consider sanitizing the filename that is passed via get->file using something from the cleanBasename core function: https://github.com/ryancramerdesign/ProcessWire/blob/03387f8283d518e9cc405eff8f05cd6a5bf77c4c/wire/core/Pagefiles.php#L296 You could also do some checks to make sure that both pageid and file are not blank and throw an exception if they are, or if the pageid is not provided as an integer, or get->file does not match it's sanitized version - both of which might indicate attempted hacks. An even better, more secure approach might be to use child pages instead of repeaters (or the new PageTable field) and just pass the id of the page to the download script, so with one image per page, the page id is all that you would need to identify the path to the file and start the download.
    1 point
  20. Just wanted to note here in this post that I've built a configurable module for this and also included optional support for automatically generating the password for the new user. You can read more about it here: https://processwire.com/talk/topic/7051-email-new-user/ Also, there was some discussion above about how to get the entered password in plain text, but I don't think anyone actually came up with a working solution. I found that you can hook on InputfieldPassword::processInput and then you can get the plain text password with $event->object->value
    1 point
  21. Sorry to dive in late. Diogo's code would be equalent to: if($page->url == $page->url) throw .... Just looks cooler, but however I would simply not create the php template for those pages and create a separate template file. If your template would be "subpage", create a partial-subpage.php And render the subpages on home with echo $subpage->render("partial-subpage.php"); And since you don't have a subpage.php those won't be viewable anyway. Redirect: What you also could do is have the subpage.php redirect to the home with a hash /#yoo appended, so you could scroll to the panel and also use that url for indexing. $session->redirect("/#" . $page->name);
    1 point
  22. @landitus: you're right in that using the code I posted earlier message would get sent every time user is saved, which probably isn't correct behavior. One way to achieve what you're describing here would be by simply adding a check for changed status (published). You might want to take a look at Process Changelog for some sample code. "@" character was missing by purpose; in PHP adding @ before function such as mail() suppresses errors. If you're relying on these emails getting sent, this makes very little sense, as it just tells PHP that "if this fails, no worries, just keep going as if nothing happened!"
    1 point
  23. I'm planning on using PW for an upcoming project. Normally I plan out the key database tables I need, but now that I've been reading about PW and how it works, I had the usual epiphany. If all of PW is custom fields, and I create a Template to represent a group of fields, then PW "is the database". Is it true that rather than creating a "location" table, I'd create a location template and set it up with the address fields, for example? If so... How far should one take this methodology? Can you go to deep with this and live to regret it? How easy/efficient is it to query custom fields from other backend tools that aren't part of the site? Do you just bootstrap PW and work with the "pages" that represent the "table rows"? How about querying with straight SQL? I guess what I'm trying to ask is, should I go "ALL IN", leveraging PW to the max this way, or build on custom tables in the "usual way" you'd do with other CMS's? Thanks in advance for any advice on this, I'm blown away by how PW works, but a little concerned about going "all in", so to speak.
    1 point
  24. I think this should do what you are looking for: $pages->find('created_users_id=n'); where n equals the id of the user you are looking for. If you are searching for the currently logged in user, you could replace this with $user->id PS, Welcome to PW!
    1 point
  25. this is what i was missing... thanks! Edit: Got it working with CSRF token, but I think the redirect approach fits better here. Easy to achieve with the flashdata function of PW (this should be added to the cheat sheet, I could imagine many users of PW would use this if they knew about it).
    1 point
  26. Thanks for posting Soma, this is an interesting approach and not one I've seen before, but it looks great. The underlying concept and result is similar to the approach I usually use. Since you posted a good description, I'll try to do the same for mine. The only reason you see head/foot files in the default PW profile is because it seems to be simpler for new users to grasp. But I almost never use that approach in my own sites. Like your system, I have a main.php file which is my main markup file. But unlike your system, main.php is included from all the other template files (rather than main.php including them). The other template files focus on populating the key content areas of the site, specific to the needs of the template. Examples of key content areas might include "main" (for center column/bodycopy) and "side" (for sidebar/related info), though often includes several other identified areas. But I'll keep it simple in this case. Here's how it works: basic-page.php <?php $outMain = "<h2>{$page->subtitle}</h2>" . $page->body; if($page->numChildren) $outMain .= $page->children->render(); // list the children $outSide = $page->sidebar; include("./main.php"); main.php <html> <head> <title><?php echo $page->title; ?></title> </head> <body> <h1><?php echo $page->title; ?></h1> <div id='main'><?php echo $outMain; ?></div> <div id='side'><?php echo $outSide; ?></div> </body> </html> The benefit of this approach is that basic-page.php can setup whatever it wants in the key content areas ($main or $side) whether simple like in this example, or something much more complex. I actually prefer for the variables representing the key content areas to be optional. In the scenario above, $outMain and $outSide would have to be defined by every template or they would end up as uninitialized variables in main.php. As a result, I actually use $page as an anonymous placeholder for these variables (making sure they don't conflict with any existing field names) and then let main.php assign defaults if the calling template didn't specify one of them. For example: basic-page.php <?php $page->outMain = "<h2>{$page->subtitle}</h2>" . $page->body; if($page->numChildren) $page->outMain .= $page->children->render(); // list the children // note: no $outSide specified include("./main.php"); main.php <?php // setup defaults when none specified if(empty($page->outMain)) $page->outMain = $page->body; if(empty($page->outSide)) $page->outSide = $page->sidebar; ?> <html> <head> <title><?php echo $page->title; ?></title> </head> <body> <h1><?php echo $page->title; ?></h1> <div id='main'><?php echo $page->outMain; ?></div> <div id='side'><?php echo $page->outSide; ?></div> </body> </html> Final thing to point out here is that main.php is the only template actually outputting anything. Because basic-page.php (or any other template) is determining what's going to go in that output before it is actually sent, your template has the opportunity to modify stuff that you might not be able to with other methods. For instance, the <title> tag, what scripts and stylesheets are loaded, etc. Here's the example above carried further to demonstrate it: basic-page.php <?php // make a custom <title> tag $page->browserTitle = $page->rootParent->title . ": " . $page->title; $page->outMain = "<h2>{$page->subtitle}</h2>" . $page->body; if(count($page->images)) { // display a clickable lightbox gallery if this page has images on it $config->scripts->add($config->urls->templates . "scripts/lightbox.js"); $config->styles->add($config->urls->templates . "styles/gallery.css"); $page->outMain .= "<ul id='gallery'>"; foreach($page->images as $i) { $t = $i->size(100,100); $page->outMain .= "<li><a href='{$i->url}'><img src='{$t->url}' alt='{$t->description}' /></a></li>"; } $page->outMain .= "</ul>"; // add a note to $page->title to say how many photos are in the gallery $page->title .= " (with " . count($page->images) . " photos!)"; } if($page->numChildren) $page->outMain .= $page->children->render(); // list the children include("./main.php"); main.php <?php // if current template has it's own custom CSS file, then include it $file = "styles/{$page->template}.css"; if(is_file($config->paths->templates . $file)) $config->styles->add($config->urls->templates . $file); // if current template has it's own custom JS file, then include it $file = "scripts/{$page->template}.js"; if(is_file($config->paths->templates . $file)) $config->scripts->add($config->urls->templates . $file); ?> <html> <head> <title><?php echo $page->get('browserTitle|title'); // use browserTitle if there, otherwise title ?></title> <?php foreach($config->styles as $url) echo "<link rel='stylesheet' type='text/css' href='$url' />"; foreach($config->scripts as $url) echo "<script type='text/javascript' src='$url'></script>"; ?> </head> <body> <h1><?php echo $page->title; ?></h1> <div id='main'><?php echo $page->get('outMain|body'); // use outMain if there, or body otherwise ?></div> <div id='side'><?php echo $page->get('outSide|sidebar'); // use outSide if there, or sidebar otherwise ?></div> </body> </html> More than half the time, I'll actually just re-use page variables like $page->body and $page->sidebar rather than $page->outMain and $page->outSide. That way there's no need to consider defaults, since $page->body and $page->sidebar untouched technically are defaults. <?php $page->body = "<h2>{$page->subtitle}</h2>" . $page->body . $page->children->render(); But technically you've got a little more flexibility using your own self-assign anonymous variables like outMain and outSide, so figured I'd use that in the examples above. outMain and outSide are just example names I came up with for this example and you could of course name them whatever you want.
    1 point
×
×
  • Create New...