getting an array into a block database

Permalink
Hello there, I'm a complete newbie to Concrete5. I'm trying to create a block with a dynamic form, something like this...

http://www.concrete5.org/documentation/how-tos/developers/sort-a-li...

I've named each filed something like this "name[]"

I would like to receive a php array in view.php (name[])


Thanks in advance

 
jordanlev replied on at Permalink Reply
jordanlev
Can you please provide more details? I don't understand what it is you're asking exactly.
osnoz replied on at Permalink Reply
Sorry, I'll explain myself a bit better.

I have created a dynamic form, I.E. a form where the user can press a button to add new fields to the form.

So I have a form which simplified looks like this...

<select name="list[]"> ... </select>
<select name="list[]"> ... </select>
<select name="list[]"> ... </select>


The user can add as many of these fields as they like. What I want to know is how to handle the data from this form and save it in the database. I've named the fields something[], like an array after guidance from this page...

http://www.concrete5.org/documentation/how-tos/developers/sort-a-li...

...however, I don't know how to make it work.


Hope thats a bit clearer.
jordanlev replied on at Permalink Reply
jordanlev
If the name of the field is "list[]", then the values will be in $_POST['list']. For example:
$items = $_POST['list'];
foreach ($items as $item) {
  echo $item;
}


But you are also going to need to know where to put the code that handles the POST and saves data -- which could be in one of several different places depending on what you're doing exactly. Are you building a block? A single_page? Something else?
osnoz replied on at Permalink Reply
I'm building a block, do I need to do something with the controler.php ?
jordanlev replied on at Permalink Reply
jordanlev
Okay, so I'm assuming this is a form in the add or edit dialog of the block. There are two issues here. One is the code that processes the post, and the other is how you're storing this data.

STORING THE DATA: Every c5 block must have a "primary" table defined in its db.xml file, which must have an integer primary key field called "bID", and at least one other field of any type (if you don't need another field here, just make one called "dummy" or something) -- you will get C5 errors if there's not at least two fields in this main table. C5 will know about this table because your controller has a property up top called "$btTable" which should be the table name of this "primary" table. Now, since you have multiple values associated with each block, you probably need to also create an additional table. Generally, this table will have a "bID" field as well which is a foreign key pointing to the primary block table, and it will generally ahve a many-to-one relationship with the primary table (because there's multiple records for each block). For the sake of example, let's say this secondary table has two fields -- "bID" and "item".

SAVING THE DATA: Create a "save" method in your block controller, which C5 will automatically call when someone clicks the "Save" button in the block add or edit dialog. For example:
public function save($args) {
  $db = Loader::db();
  $items = $args['list'];
  foreach ($items as $item) {
    $sql = "INSERT INTO btMyBlockSecondaryTable (item) VALUES (?)";
    $vals = array($item);
    $db->Execute($sql, $vals);
  }
  parent::save($args); //<--You MUST call this at the end otherwise the save won't go through completely
}


The foreach loop saves every "secondary" record, and then the call to parent::save() saves the primary block record (C5 handles that one for you).

Good luck!
cecil4 replied on at Permalink Reply
cecil4
How would you save data to the DB if your aren't in the add/edit dialog?
jordanlev replied on at Permalink Reply
jordanlev
It depends. Where are you trying to save from? What is the data? Where did the data come from? What table do you want to save it to?
incredikill replied on at Permalink Reply
But with this solution the values in the second database arent linked to the first because there is no bID set, because this will be created when
parent::save
is called.... and that is after you add the items. How to solve that?
jordanlev replied on at Permalink Reply
jordanlev
Good point. You can get the bID in the save function like this:
$this->bID

... even though the parent save() function hasn't been called yet, the block object itself knows what its bID is.

Although note that recently I've started doing these differently and instead of having separate tables of data, I just create a TEXT field in the primary table and use PHP's serialize() function to store all of the array elements in that one field (like @nerdess mentions in another reply in this thread). To do that, you need to call serialize() in the save function, unserialize in the add, edit, and delete functions. Also If you have a getSearchableContent function you'll want to unserialize there as well.

All that being said, I also have another option available if you need a custom block with repeating items: Designer Content Pro is a new addon I've developed that creates the data schema and editing interface for you automatically (you just configure it via a dashboard page and it handles the rest -- no php programming necessary). Then it makes that data available to you in an empty block view.php file which you can customize however you need to (for any kind of front-end -- lists, slideshows, galleries, etc.). It's not free, but it saves a lot of development time and is totally worth it if you're building custom blocks for paying clients:
http://www.concrete5.org/marketplace/addons/designer-content-pro...

Best,
Jordan
JohntheFish replied on at Permalink Reply
JohntheFish
A few weeks ago I posted a howto on the other strategies Jordan mentions:

http://www.concrete5.org/documentation/how-tos/developers/save-and-...
nerdess replied on at Permalink Reply
nerdess
I think what you need is serialize()/unserialize() ?!?!

With serialize() you can "flatten" an array into a string. This string can then be saved in the database and turned back into an array with unserialize().

Keep in mind though that serialising violates the paradigm to keep your database "normalised". It is a quick and dirty solution but not the best practise ;-)