Search the Community
Showing results for 'runtime'.
-
Processwire performance, serverload and server settings
recyclerobot replied to recyclerobot's topic in General Support
Hi Ryan, Thanks for your answer, php 5.1 was a typo, I'm using 5.3.2 I've done some tests running processwire as mod_cgi and running processwire as mod apache, both running a bare bone github install (main repo from today) and called a execution time and you're right: mod_cgi is a tiny tiny bit faster but uses alot more RAM while doing so (after 1000 refreshes, mod_cgi spiked at almost 300Mb in cycle, while mod_apache stayed at a steady 68Mb) runtimes (after 1000 calls) mod_cgi: page runtime: 0.0476528 sec mod apache: page runtime: 0.0479234 sec so I'm switching my server to mod apache, and looking into APC Love your markupCache, I've been succcessfully using it on 2 projects now (caching large header elements) Looking forward to the new Page > write to filesystem or not again, thanks for everything!- 3 replies
-
- 1
-
-
- performance
- server
- (and 4 more)
-
Thanks for the testing netcarver and stillmoving design. Looks like I can set this with the jQuery UI datepicker 'yearRange' option. Though I'm wary about getting too many configuration options with the field, unless it's something everyone will use. Good point though, this may be one to have... JS/jQuery datepicker is working with the timestamp in seconds * 1000, whereas PHP isn't. I did the conversion on the front-end (passing value in ms), but neglected to on the submitted value. So that's a bug-- thanks for finding it. But it brings up something else. Rather than adding code for this exception, I'm really wondering if there's any point in having a unix timestamp for this field. After all, the unix timestamp is always available since PW keeps it in memory as a timestamp regardless of what date format you choose... converting from timestamp to formatted date is part of runtime output formatting. And a timestamp is always acceptable as input from the API. So the whole purpose of the date/time format and date/time picker is so that you don't have to see/use a timestamp. As a result, I'm thinking perhaps I should remove the timestamp option, unless anyone can think of a reason to keep it. The question is why I put it there in the first place.
-
At what point should can I echo $error? I echoed it in the final else statement but didn't see anything. Here is whole contact page markup <?php include("./header.inc"); ?> <p class="italic_header">If you'd like to get in touch regarding tuition, please use the form below.</p> <form action="" method="post" id="contact_form"> <fieldset class="first"> <h6>About yourself: </h6> <label for="name">Your name: </label> <input type="text" name="name" autofocus> <label for="email">Your email: </label> <input type="email" name="email"> <label for="phone">Your phone number: </label> <input type="phone" name="phone"> </fieldset> <fieldset> <h6 class="mt60">Your tuition: </h6> <label for="subject">Subject: </label> <select name="subject" id="subject" /> <?php foreach ($page->subject_options as $subject) { echo "<option>$subject->subject_option</option>"; } ?> </select> <label for="level">Level: </label> <select name="level" id="level" /> <?php foreach ($page->level_options as $level) { echo "<option>$level->level_option</option>"; } ?> </select> <label for="hours">Hours per week: </label> <input type="number" min="1" max="40" value="2" name="hours"> </fieldset> <div class="clear"></div><!-- /.clear --> <fieldset class="full"> <label for="message">Additional information: </label> <textarea name="message" cols="30" rows="10"></textarea> <input type="submit" value="submit" id="submit"> </fieldset> </form> <div id="contact_side"> <h6>Or you can find me, here: </h6> <ul> <li>Skype: <?php echo $page->skype_name; ?></li> <li><a href="<?php echo $page->fb_url; ?>" target="_blank">Facebook</a></li> <?php if ($page->twitter_url) { echo "<li><a href='$page->twitter_url' target='_blank'>Twitter</a></li>"; } ?> </ul> <?php // set this to the email address you want to send to (or pull from a PW field) $emailTo = 'me@me.com'; // or if not set, we'll just email the default superuser if(empty($emailTo)) { $emailTo = $users->get($config->superUserPageID)->email; } // set and sanitize our form field values $form = array( 'name' => $input->post->name, 'email' => $input->post->email, 'phone' => $input->post->phone, 'subject' => $input->post->subject, 'level' => $input->post->level, 'hours' => $input->post->hours, 'message' => $input->post->message, ); // initialize runtime vars $sent = false; $error = ''; // check if the form was submitted if($input->post->submit) { // determine if any fields were ommitted or didn't validate foreach($form as $key => $value) { if(empty($value)) $error = "<h2 class='error'>Please check that you have completed all fields.</h2>"; } // if no errors, email the form results if(!$error) { $subject = "Contact Form"; $message = ''; foreach($form as $key => $value) $message .= "$key: $value\n"; mail($emailTo, $subject, $message, "From: $form[email]"); $sent = true; } } if($sent) { echo "<h2>Thank you, your message has been sent.</h2>"; // or pull from a PW field } else { echo "<h2>Sorry, that didn't work.</h2>"; } ?> </div> <!-- end contact side --> <?php include("./footer.inc"); ?> Thanks for the help.
-
Can't seem to get this form sending, have slightly modified Ryan's code but not working, code is below. Any one have any ideas? <?php // set this to the email address you want to send to (or pull from a PW field) $emailTo = 'me@me.com'; // or if not set, we'll just email the default superuser if(empty($emailTo)) { $emailTo = $users->get($config->superUserPageID)->email; } // set and sanitize our form field values $form = array( 'name' => $sanitizer->text($input->post->name), 'email' => $sanitizer->email($input->post->email), 'phone' => $sanitizer->text($input->post->phone), 'subject' => $sanitizer->text($input->post->subject), 'level' => $sanitizer->text($input->post->level), 'hours' => $sanitizer->text($input->post->hours), 'message' => $sanitizer->textarea($input->post->message), ); // initialize runtime vars $sent = false; $error = ''; // check if the form was submitted if($input->post->submit) { // determine if any fields were ommitted or didn't validate foreach($form as $key => $value) { if(empty($value)) $error = "<h2 class='error'>Please check that you have completed all fields.</h2>"; } // if no errors, email the form results if(!$error) { $subject = "Contact Form"; $message = ''; foreach($form as $key => $value) $message .= "$key: $value\n"; mail($emailTo, $subject, $message, "From: $form[email]"); $sent = true; } } if($sent) { echo "<h2>Thank you, your message has been sent.</h2>"; // or pull from a PW field } else { echo "<h2>Sorry, that didn't work.</h2>"; } Thanks
-
Thanks Rob, got your message and will take a closer look today. Regarding the functions you mentioned: • wakeupValue() converts a file from a basic storage type (typically an array) into it's representation in ProcessWire. Most often this is used to translate the raw value from the DB into the live value for runtime. • sleepValue() does the opposite of wakeupValue() and translates a runtime value back to it's basic type for storage. If you are just dealing with a simple type like an integer or a string that are represented in the database exactly how they are at runtime, then wakeupValue() and sleepValue() don't need to do anything at all (other than return the value they were given). So these functions really only come into play when the field's value has to be stored differently than it would be presented at runtime. This would be the case for anything that is presented as an object at runtime. Since an object can't just be "stored" and still have its components be searchable and sortable in a database, it needs to be translated to/from fields in a DB table. Likewise, if you are sending object field values to/from JSON/XML web services, you probably want that object represented as an array, so that it can be encoded by XML or JSON. • sanitizeValue() is entirely unrelated to the other two functions (though you may see it called in series with them). But it does nothing other than sanitize a value that is assigned to a $page. So lets say that you have a field called 'myfield' and this API call gets executed: $page->myfield = 'my value'; That value gets passed through the sanitizeValue() method for whatever fieldtype is used by 'myfield'. After passing through sanitizeValue() it gets set to the $page. The sanitizeValue() method is just a way to ensure that invalid data doesn't get assigned to the page. So if the fieldtype used by 'myfield' expects it to be a string, then its sanitizeValue() method should ensure that whatever it returns is a string, regardless of what it's given. Or if you want, you can have it throw an exception when it receives invalid data. But here's what a sanitizeValue() method might look like for 'myfield': public function sanitizeValue(Page $page, Field $field, $value) { if(!is_string($value)) $value = (string) $value; return $value; }
-
Default values are something we'll likely have at some point, but I'm a little conflicted about it. I like the idea that when you create a new page and assign no values to it, it doesn't place any values in the database. There's a clear distinction between set and not set. There's a nice simplicity to that. So I translate that to the way I name and use fields. If I have a checkbox that I want to enable some behavior, I'll name it toggle_behavior and if I have a checkbox that I want to disable some behavior, I'll call it toggle_no_behavior or toggle_disable_behavior. You end up with a smaller and faster database if you are naming and using fields in a manner that veers towards the empty state being the more common one, and assigning any defaults at runtime rather than storing more duplicate 'default' values in the database. But I also recognize that these benefits are more technical than functional, which is why I say we'll likely have them at some point.
-
Ryan Great to hear from the developer! Don't really follow you here, as surely the idea is to prevent users from saving bad data? So long as you provide clear error messages how is this a problem? With jQuery it's pretty easy to provide the message as soon as users tab out of the field. Don't understand much about PW yet, but doesn't doing this in the template mean that issues will only show up at runtime? I suggested the regex idea as a quick and dirty fix, but obviously it's going to restrict use of the feature to sad geeks like us. Plus, on thinking it through, a single field for an error message would hit problems with your back-end internationalisation. Years ago I developed a flexible declarative approach and it has served me well. Some of the modern PHP frameworks use a similar idea. You develop an easily extended utility library of validations, and each validation has an error string in all active languages. The string can use template-like placeholders for parameters: "Number should be between {1} and {2}." Then you develop a simple declarative syntax for setting validations and any relevant parameters. Here's a couple of examples: is_greater_than,10 is_between,1,365 is_alphanumeric;is_max_length,256 As a catchall, you can offer access to regexes: matches_pattern, ^\$(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$,"Must be a valid USD price" Another useful feature, I find, is filters that clean up input. These are run before the validations and ensure consistent presentation. For example, for a city or postal code you might use: to_uppercase For a field in which you are entering, say, architects, you can tidy up capitalisation with: to_pretty_name If input isn't entirely trusted, you can offer a range of sanitation filters to eliminate cross-site scripting etc. This would open up the possibility of using PW for, say, social content management. The actual plumbing for this is just a few lines of code, and there are plenty validation and filter libraries to plunder. You'd be getting a lot of functionality for a small investment! I guess you'd tuck this out of the way on the advanced tab. For types with limited validation options such as numeric fields you could improve usability by offering the validation options as fields on the form instead of declarations. For text fields, the declarative string would be the most flexible, I think. You could offer popup help so users could check their options without leaving the form. Personally, I would find this pretty useful. Why not help content creators achieve consistency and correctness?
-
Edit: oh hi and welcome gcplan, glad you found us! I think you'll have no problems to make a custom integer fieldtype/inputfieldtype module, that would check for a certain range and output an error when saved. It's possible to create field setting you would be able with 2 integer fields to enter a upper-lower bound. You could even implement jquery script to check on runtime before saving. Jut have a look at how the PW integer,float,text fieldtype/inputfieldtypes are done. I think you'll have no problem if you're fluent in php. PW makes it very easy to do what ever you like in that regard.
-
The existing comments module does keep the user ID already, though it doesn't use it for storing the user name. But you could make an autoload module that changes the 'cite' property of a comment to the user name. This is something that has to be done at runtime since a user's name may have changed since the comment was posted. public function init() { $this->addHookAfter('FieldtypeComments::wakeupValue', $this, 'hookWakeupValue'); } public function hookWakeupValue(HookEvent $event) { $value = $event->return; foreach($value as $comment) { if($comment->user) $comment->cite = $comment->user->name; } } To have the comment displayed instantly, that will be easier to solve, and doesn't require modifying the existing module. Just do your comments processing/output generation before you "echo" any output. When a comment is posted, do a $session->redirect('./'); I'm making a page-based comments module which will have the same sort of flexibility as the rest of ProcessWire, though it'll be a bit before I've got it finished (and some projects have to come first). But this page-based comments module should support nearly anything you could want to do with it, without having to modify its core code.
-
check_access just refers to view access, and this is assumed if you omit check_access. So the only reason to ever use check_access is if you want to include pages the user doesn't have access to view, due to access control settings. To list the pages you mentioned, you'd just use "status=unpublished". If $user->isSuperuser() then don't bother performing any checks, because they will have access. You could cycle through the templates, see which ones are defining access, and of those, which ones have editRoles that are consistent with the users roles. Then include those templates in your $pages->find() selector. But this leaves out those pages that inherit their access. That's because that access is inherited through the hierarchy at runtime, so not possible to determine without actually loading the page and following it's inheritance path. As a result, this is a complex question to which there isn't a simple answer... at least not one I can think of yet.
-
Autocomplete and Other Search Enhancements
ryan replied to Michael Murphy's topic in Getting Started
This is the case with template, but not parent. If you set a parent, then PageListSelect assumes that to be the starting point in the tree. The pages don't have to have that parent directly. They just have to have that parent as an ancestor. This is the way it's supposed to work, and the way it worked here just testing it. Are you getting a different behavior? But you are right with regard to template. PageList doesn't take template into account because PageList is designed to list hierarchy not type. It's feasible in the future that template could be combined with parent as a constraint within the hierarchy defined by parent, but that ability isn't there right now. As a result, template constraints shouldn't be used with PageListSelect inputs. It's not just a matter of an Inputfield here. The paths for pages don't actually exist anywhere that can be searched. Paths are constructed and determined at runtime, and only for pages that are loaded. There's nothing to strpos() or find(). So we'd need to find a place for them to be cached before such a solution could search them (using that 'mypath' field, for example). I'll keep thinking if there's other ways. -
Autocomplete and Other Search Enhancements
ryan replied to Michael Murphy's topic in Getting Started
It'll work with any text field (or combination of text fields). But url or path is not actually a DB field that exists anywhere in PW. Instead it's determined at runtime for each page... so it's not one that can be queried. Title is probably the best way to go in most cases. Excellent point -- this is a great way to go so that you can use the same template for regular and ajax results. -
I'm not sure why that would work when removeAll doesn't because the foreach you posted is identical to the one used by removeAll. But that's not the issue here, instead it's this: Files aren't actually removed or copied until you call $page->save(); that's what ultimately commits the change to the file system. So I think you'd solve this one by adding a $page->save(); immediately after your removeAll (before adding the other images). The reason for this is that we don't want permanent changes (like deleting files) made to pages until we're certain those changes are actually going to be saved. Otherwise temporary runtime manipulations to something like $page->images wouldn't be possible, because you'd be copying or deleting files around without ever having that committed to the database (resulting in data corruption, and lots of untracked files).
-
Pete, if I'm understanding correctly, I think you can just make the module an 'autoload' module. Then ProcessWire will include it automatically at runtime. If you want to bake in some functions or instantiate some objects, just do it outside of your module's class, but in the same file (or have your autoload module include the file that they are in, in it's init() method). If you want to add a new API variable that will be sent to all the templates, you can do this in your .module file, outside of the class: $myvar = 'string, object, or whatever you want'; Wire::setFuel('myvar', $myvar); Then all your templates will have that $myvar variable and your modules will be able to access it from $this->myvar or wire('myvar');
-
Progress on ProcessWire 2.2 and overview of multi-language support
ryan replied to ryan's topic in Multi-Language Support
We're duplicating GetText functionality here, not just a string translator. Everything about it is geared towards making it super-simple to use, and able to scale to any size. I actually think we have a solution that is significantly less complex than GetText, while duplicating its functionality. For example, take a look in the WordPress i18n documentation and read the sections for: POT files, PO files, MO files, "Choosing and loading textdomains", and "Generating POT files". Note that you don't have to deal with any of that in ProcessWire, nor do you have to install GNU Internationalization utilities, nor do you have to install and use POEdit. Yet you get all the same capability and power–ProcessWire's Language Support does it all for you. If you want to compare ProcessWire's implementation, compare it to another of the same capabilities like in WordPress or Drupal (both of which use GetText). I think you'll find ProcessWire's implementation is far simpler and just as powerful from every standpoint. The example you posted doesn't involve a parser. By that, I mean a parser like GetText that sifts through PHP files and locates the translatable phrases on it's own, outside of program execution. Without a parser, you have to predefine everything on your own in a separate PHP file (or some other file), like in your example. This is okay for small things, but we need something more powerful and scalable than that. While there's a lot of power under the hood, I think our basic translation API is about as simple as it gets: <?php echo __("text"); // outside of a class echo $this->_("text"); // inside of a class With regard to number of translation function calls on a line, there's no problem with placing multiple __() function calls on the same line from a PHP perspective–all those functions will still get called at runtime. It all has to do with the external parser (like GetText, or in our case PW's LanguageParser.php). We need to have a way to let the parser identify the translatable phrases outside of PHP while also optionally communicating additional meta data about the translation. This part happens at translation time, not at runtime, so that everything is cached and ready to go with no parsing at runtime. The 1-translation per-line requirement is to ensure that optional meta data about the translation can be communicated to the parser (and people doing translations), and that meta data is communicated via comments placed at the end of the line. Since this meta is optional, it's feasible we could just ignore it when there are multiple translations on a line (and perhaps will add that), but for now I'm trying to keep it simple with clear guidelines and best practices. It goes beyond technicalities or rules too. Keeping translations on one line helps to keep things more readable and clear (for me at least, having now made dozens of files translatable). Language designed for translation is different from regular language in that it requires more careful consideration. I've had to rethink my use of English in many cases. Due to the differences in languages, translatable phrases are by nature independent pieces of information that must always be static and carefully considered, especially when it comes to how it flows with other dynamic text. Note that GetText (WordPress/Drupal) has the same requirement when it comes to providing meta data to a translation function call. However, they also don't prevent you from putting several calls on one line (with no meta data) so we may update to do the same if there is enough demand for it. But I'd still encourage people to follow these rules even if we just make them optional guidelines. -
The item description field is actually configurable in the module settings. In the admin, go to Modules > Markup > RSS. Click on it to configure the various settings it can use. This sets the defaults for all instances of MarkupRSS. If you prefer, you can also change the settings at runtime for any individual instance like this: <?php $rss = $modules->get('MarkupRSS'); $rss->itemDescriptionField = 'body'; echo $rss->render($yourPages); Also, thanks for the great example stillmovingdesign!
-
This is something I don't know much about yet and need to do more research. You've got me curious. Looking at Drupal7, it looks like they do it with PHP, though only if one specifically enables some page_compression and cache options. I only see reference to it in their /includes/bootstrap.inc for serving pages from the cache. It looks like it involves checking a lot of $_SERVER variables to verify gzip support, delivering a "content-encoding: gzip" header and spitting out the gzipped data when appropriate. They create the gzipped data with PHP's gzencode function. It appears that they only use it for delivering data from the cache. That makes me think that the gzencode is potentially slow and they are caching and performing the gzencode after delivering a page where it can be picked up from the cache by the next request. What's interesting is that they gzip the cache data even if not supported by the client and they gzinflate it at runtime for clients that don't support it. I suppose this makes sense, and a good way to keep smaller cache sizes. This is something we'll probably want to implement in PW's core PageRender module at some point.
-
You'd probably want to make a copy of the FieldtypeComments and modify/rename it towards your needs. You'd need to change the DB schema that it uses so that you'd have a URL field, and then update the CommentForm class to accept it and save it. Basically, I'd just duplicate everything for the 'email' field to make a URL field. When it comes to sanitizing it, you'd just use the $sanitizer->url() rather than $sanitizer->email(). URLs are kind of open-ended in terms of what characters they allow, so make sure you run it through htmlentities() before outputting anywhere at runtime.
-
How to save submitted form data from a module
ryan replied to evanmcd's topic in Module/Plugin Development
Are you sure this is from FieldtypeComments? That module doesn't override the formatValue() function. Also the comments on that function refer to renderMapMarkup? This is different than how formatValue is meant to be used, but it is still okay. But there is a major component missing, and that is how the value goes from user input into your fieldtype? Fieldtypes aren't meant to handle user input (Inputfields are), so we have to come up with another way to get front-end user input into here. Before we go further, I just mention how FieldtypeComments works: It has no formatValue() function because it doesn't need one. formatValue is an optional method to convert a runtime value into one ready for presentation on the site... the best example is taking a string of text and encoding the entities in it (i.e. '&' becomes '&'). FieldtypeComments doesn't need a formatValue() function because its wakeupValue() returns an object (of type CommentArray). That CommentArray has some built in helper methods that you can use on your site to render comments or render the form for them. So here's how you render comments: echo $page->comments->render(); And the form for inputting comments is rendered like this: echo $page->comments->renderForm(); That renderForm() method actually loads up another class called CommentForm(), and that class is looking for posted comments. This is different from other Fieldtypes because it's something designed to accept input from the frontend rather than the admin. Admin input is handled with Inputfields. So in your case, you are trying to achieve the same result at FieldtypeComments. I think it may be okay to let your formatValue() function take this role. But your formatValue function will need to detect when a up/down has been submitted, in addition to outputting the form that it is now. At least for now, I would suggest making your Fieldtype a regular Fieldtype and not a FieldtypeMulti. I don't think a FieldtypeMulti isn't necessary here and might even make it more difficult to implement. Instead, I would use a schema that increments a single counter for every up vote. Probably the same schema as FieldtypeInteger. If you wanted to maintain separate up and down counters, then you would expand your Fieldtype schema to have two counters. But I would suggest just starting with one to get things going, and then expand. Likewise, if you determine you need a FieldtypeMulti, than no problem, but since that evolves from a regular Fieldtype, it's good to understand the workings of a regular Fieldtype first. Assuming the stuff in the paragraph above, your formatValue would do something like this: <?php public function formatValue(Page $page, Field $field, $value) { if($input->post->vote) { // a vote was submitted // turns off outputFormatting so we can save a raw value $page->setOutputFormatting(false); // now increment and save the value $name = $field->name; $value++; // increment the counter $page->set($name, $value); $page->save($name); // turn outputFormatting back on, so we're leaving everything as it was $page->setOutputFormatting(true); $out = "<p>Thank you for voting. Current votes: $value</p>"; } else { // no vote submitted, display the form $out = "<form action='./' method='post'>" . "<p>Current votes: $value</p>" . "<p><input type='submit' name='vote' value='Vote' /></p>" . "</form>"; } return $out; } Note that there is no security or validation to ensure the user doesn't double vote or hasn't already voted for that page, etc. So it's just for demonstration purposes, but I think gets across the part I was talking about: something to identify the vote submission and save the vote. -
The typing of "images" in a <p> was just an example of using a little template file code to automate some specific runtime output. It's not a standard or even a recommendation, just a little code snippet I found handy in a couple cases. Unless I've misunderstood, now you are asking for exactly what the built-in functionality does– Click on the photo icon in TinyMCE and add a photo. If you then want to link it to something, then click on the photo to highlight it and then click on the link icon to select what you want it to link to.
-
I agree with all this. Here are the curent module naming conventions (first word in module name): Export - any module that provides site data export capabilities, especially where there may be a related Import module. Fieldtype - any module that extends the 'Fieldtype' class. Represents a data type used by ProcessWire fields. Form - any module that deals with creating/processing web forms (some crossover potential with Markup). Inputfield - any module that extends the 'Inputfield' class. Represents an HTML input widget used to collect data in the admin. Import - any module that imports data to create new data in a PW site. Jquery - any module that adds something related to jQuery/Javascript. Language - any module that provides support for other languages Process - any module that extends the 'Process' class. Typically attached to a page for handling admin actions. If it's related to another Process module (core or 3rd party) it's name should start with that module, i.e. ProcessPageEditLink is related to ProcessPageEdit. Markup - any module designed for creating or parsing markup Page - any module designed to add capabilities to PW's Page class. Textformatter - any module that extends the 'Textformatter' class, for runtime output formatting of text fields. Some of the naming conventions are based on the root class that they extend, though not all. New additions to this list likely won't be based on extending some built-in class, since there aren't any others. Though I would suggest that when a module doesn't fit in the above, it should start with the class name of the core class or module it is hooking into (not unlike the 'Page' one above). So if you are adding hooks to the Pages class, then start your module with 'Pages'. Likewise if you are adding hooks to the Session class, then start your module with 'Session'. Beyond this, the naming conventions are open ended. I guess the first thing we have to determine is: what are the major classes of modules that aren't covered above? I can't think of any at the moment, but I know they are there.
-
This module bolts on top of the built-in access system rather than replacing it. It gets involved in runtime access control, but not low-level access control. As a result: For the same reason, the pages can appear in your PageList, like you mentioned. Perhaps we can make a future version of this module hook into PageList and other things to add a viewable() check before showing in the PageList. But for the moment, I think this particular module is more of a good starting point for further coding/customization rather than something to use as your primary access control solution. I actually think the built-in access system with templates is the best way to go most of the time, but this module is a good fit for more rare specific instances.
-
That's correct. Anything set to a $page passes through sanitizeValue, regardless of where it comes from. But I suggest that you ignore the sanitizeValue method for now, because there is no reason to implement it at this stage (unless you've extended another Fieldtype that does something with it that you don't want). I'm not sure that I understand exactly what you are saying. But your sanitizeValue shouldn't attempt to modify the value it's given unless it's of the wrong type. So in your case, I would suggest leaving sanitizeValue out of the equation for now and don't bother implementing it until you have everything else working. If things are working until you try to implement them, try doing this: leave the existing implementation in place, but put in sleepValue/wakeupValue methods just to observe what's going back and forth. That should help to clear up ambiguity about why it might be breaking when you try to provide an implementation for them. <?php public function ___wakeupValue(Page $page, Field $field, $value) { $value = parent::___wakeupValue($page, $field, $value); echo "<pre>wakeupValue: "; var_dump($value); echo "<pre>"; return $value; } public function ___sleepValue(Page $page, Field $field, $value) { $value = parent::___sleepValue($page, $field, $value); echo "<pre>sleepValue: "; var_dump($value); echo "</pre>"; return $value; } That way you can see exactly what data is getting sent back and forth without modifying it. Once you know exactly what's getting sent around, you should be able to expand upon it. If you are dealing with a multi field table, then an array is going to be used as the native storage format, and it will have an index called 'data' that contains the primary value. But it's best to observe exactly what's there rather than me tell you since I don't know the full context of your situation. You should be able to do what you are wanting to do. Lets say that you want to have your 'id' integer that's stored in the database convert to an instance of MyClass during runtime. Here is pseudocode for what you would want to do: <?php // convert an instanceof MyClass to an integer id function sleepValue($value) { return $value->id; } // convert an integer id to a MyClass function wakeupValue($value) { return new MyClass($value); } // make sure $value is a MyClass, but don't bother with this for now... function sanitizeValue($value) { if($value instanceof MyClass) return $value; else throw new WireException("value was not a MyClass"); }
-
That's correct. wakeupValue is where you take whatever value is stored in the DB, and expand that to be how you want the value represented at runtime. So in your case, it sounds like you are doing it right if you are taking that ID and then building a an object from it with other data. sleepValue does the opposite of wakeupValue. It will be given the value you created with wakeupValue, and your sleepValue needs to take that and reduce it back to its representation in the DB. In your case, it sounds like that is just the ID number.
-
Thanks Ryan. Yes I'm trying but the sort order makes it impossible. Though there subdirs that are sorted by name so they would work, but the ressort pages arent and they don't appear same position in page array with a find. No I can't use names... since they're language specific. I tried following: <?php $de = wire("pages")->get("/de-ch/halbjahresbericht-2011-2012")->find("include=all"); $en = wire("pages")->get("/en-ch/halfyearreport-2011-2012")->find("include=all"); foreach($de as $key => $p){ $e = $en[$key]->name; echo "<p>page: $p->name"; echo "<br/>page: $e</p>"; } yes I got a page reference field to reference them, but first nee to find a simple solution to not do it manually page by page. And yes the structur is 1:1. It's not for runtime on the site, but after import of these pages. --- Attached image so you see the two trees.