Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

DataModel not accessible


Reply


6 Posts   552 Views

Avatar
FriedBuffalo

Community Member, 5 Posts

9 October 2013 at 4:09am

Edited: 09/10/2013 4:18am

I've just picked up SilverStripe not long ago and have been pleasantly surprised with it so far. I seem to have hit a wall though when handling data returned from a pretty basic data model though.

I know there are addons already suited for this, such as Blocks and Widgets but I was curious as to how one would go about doing it through a more MVC-style. The below doesn't render getInfo as I thought?

../code/Student.php

class Student extends DataObject {
   private static $db = array(
      'Name' => 'Varchar',
      'University' => 'Varchar'
   );

   function getInfo()
   {
      return $this->renderWith('StudentInfo');
   }
};

../templates/Layout/StudentInfo.ss

$Name ($University)

../templates/Includes/IncludedSection.ss

$Info

Avatar
martimiz

Forum Moderator, 1107 Posts

9 October 2013 at 8:04am

Have you made sure that $Info (in IncludedSection) is within the scope of Student? (looping Student objects)?

Avatar
FriedBuffalo

Community Member, 5 Posts

9 October 2013 at 11:28am

Edited: 09/10/2013 11:31am

Yessir, tried loop and with ($)Student(s) and still no display.

I've worked around it by moving that function into Page_Controller (feels kludge-y moving business logic into the base Controller) and voilà, other pages used the function without a problem. It's not a good solution though, because I wanted a self-contained module without modifying the base Page and Page_Controller of the project.

Since I only have one function that's available on every page, I've been trying to embed it into the Model itself with no success. (The Model in question only handles creating an ArrayList, the view handles formatting it. Maybe I'm mis-interpreting how renderWith() works in this case.)

I guess I have 3 smaller questions that would help my understanding and set me on the right track:
* Is it possible to have a Model and View without the Controller using Sapphire's include/with/loop control-structures?
* Is it possible to create a globally-available Model method without a Controller?
* If not, how can a self-contained controller provide global (Page-wise) access to the Model?

Avatar
martimiz

Forum Moderator, 1107 Posts

10 October 2013 at 2:21am

Edited: 10/10/2013 2:21am

First: which version of SilverStripe are you using? You are referring to Sapphire which is version 2.x, but if you're new to SilverStripe I'd suggest you start with 3.1, that uses Framework

You can create DataObjects (Models) independently, use ModelAdmin in the CMS to fill them, and load them from within any DataObject or Controller with SomeModel::get(). In that sense they are globally accessible. But you cannot just include them in your template (View) directly.
Even if you travel down a series of nested loop/with structures in you template, the first set of data always has to come from the current controller some way.

But instead of adding your, say, getAllStudents() function to the Page_Controller, you could create a (Data)Extension (decorator) for it in your Module and move the functionality there. Read here: http://doc.silverstripe.org/framework/en/reference/dataextension.

By the way: the Page and Page_Controller classes are not considered core. They live in mysite and are meant to be a 'starting platform' for the construction of your site. But of course you'd want a module to be as seperate as possible, which can sometimes be a bit of a hassle :)

I hope this answers your question :)

Avatar
FriedBuffalo

Community Member, 5 Posts

10 October 2013 at 7:56am

Edited: 10/10/2013 8:00am

I'm using 3.1, I should clarify I meant the templating-engine.

I currently have the module working as intended by heeding your advice and sticking to using an outside controller (simple delegate function in Page_Controller for now). Here's how I got it to work so far.

(Slightly different model (pseudo)code, demonstrating what I'm trying to accomplish)
code/Student.php

<?php
class Student extends DataObject
{
   /* ... */
   public function getInfo()
   {
      $output = new ArrayList();
      $records = $this->get();
      foreach($records as $name => $university) {
         // modify data here
         $output->push(new ArrayData(array('Name' => $modifiedName, 'University' => $modifiedUniversity, 'ExtraData' => $extraData)));
      }

      return $output;
   }
}

templates/includes/IncludedSection.ss

<% if Info %>
   <% loop Info %>
      $Name ($University)
      $ExtraData
   <% end_loop %>
<% end_if %>

(This part is where I got lost, I think)
mysite/code/Page.php

class Page_Controller extends ContentController {
   /* ... */
   
   function getInfo()
   {
      $widget = new Student;
      return $widget->getInfo();
   }
}

I'm pretty familiar with decorators, so I should find some fun with DataExtensions to see if I can refactor a bit and see where that takes me. If it's any help to others starting out, there's a related piece of documentation in [url="http://doc.silverstripe.org/framework/en/reference/member"]member role extension[/url] that was also helpful.

Although Page and its Controller aren't core, it seems like the best way to register global methods and configuring data models (not to mention another layer of indirection). I wanted to keep it minimalist.

Thanks for the nudge in the right direction :)

Avatar
martimiz

Forum Moderator, 1107 Posts

10 October 2013 at 10:21pm

Yes, there's always that balance between perfect OO and complexity, resources and speed, especially when dealing with PHP. SilverStripe lets you get a looong way and that's what I like about it, amongst other things :)