PHP - cut string up into smaller string

Associate
Joined
8 Mar 2007
Posts
2,176
Location
between here and there
hey guys,

long story short I have this string
Code:
[[ Pooh , 2009 , 12 , 12 ],[ Mavis , 2010 , 10 , 31 ],[ Mk1 , 2010 , 6 , 1 ],[ Pooh , 2009 , 12 , 31 ],[ MK1 , 2010 , 2 , 29 ]]

It's a mutli array that i have flattened. This will get bigger in time so the below needs to be automated on any scale.

I'd like to loop though it creating a variable for each instance inbetween [..].

This is what i have so far..

Code:
//Setting counter and book variable for bookings name
$x = 1;
$book = "book";

//Setting first starting point
$start = strpos($bookings, "[", 0);

//while x is less than num_of_bookings create a varaible for each booking with all details inside from string (bookings)
while ($x <= $num_of_bookings){							 
	$end = strpos($bookings, "]", $start);
	echo ("<br>---" . $x . "--- start =" . $start . " end =" . $end);
	${$book . $x} = substr($bookings, $start, $end);
	$start = $end;	
	$x++;
}

//echoing for testing
echo ("<br>" . $x);


//echoing for testing
echo "<br><br>";
echo "-----";
echo "<br>";
echo $book1;
echo "<br>";
echo $book2;
echo "<br>";
echo $book3;
echo "<br>";
echo $book4;
echo "<br>";
echo $book5;
echo "<br>";
echo $book6;
echo "<br>";
echo "-----";

it returns the following;

Code:
-----
[[ Pooh , 2009 , 12 , 12
],[ Mavis , 2010 , 10 , 3
],[ Mavis , 2010 , 10 , 3
],[ Mavis , 2010 , 10 , 3
],[ Mavis , 2010 , 10 , 3
],[ Mavis , 2010 , 10 , 3
-----

Can anyone see where I have gone wrong??

I'm quite new to php and any help will be greatly received!

Thanks all

Blastman :)
 
Associate
OP
Joined
8 Mar 2007
Posts
2,176
Location
between here and there
Out of interest why have you flattened an array - I'm guessing it's coming from outside PHP?


yeah from mysql.

tbh, I know that I'm doing this the long way round, but the way i figger it I'm learning loads in both php and javascript and in the next project i do I'll be doing it the 'correct' way.

Any ideas for the problem I've got listed above??
 

Pho

Pho

Soldato
Joined
18 Oct 2002
Posts
9,324
Location
Derbyshire
Ah ok. As really MySQL should have a column for each of these in a bookings table, as I'm sure you're aware.

And sure, give me a few minutes (I may have to break for tea mind :p).
 

Pho

Pho

Soldato
Joined
18 Oct 2002
Posts
9,324
Location
Derbyshire
PHP:
<?php
// You should make these private and use functions to access them instead of allowing direct access
class CBooking {
	public $name;
	public $date;
	public $some_other_var;		// 3rd offset in the data
	public $some_other_var2;	// 4th offset in the data
}

$bookings = "[[ Pooh , 2009 , 12 , 12 ],[ Mavis , 2010 , 10 , 31 ],[ Mk1 , 2010 , 6 , 1 ],[ Pooh , 2009 , 12 , 31 ],[ MK1 , 2010 , 2 , 29 ]]";

// To store the split up $bookings data
$arrBooking_Input = Array();
// To store results
$arrBookings = Array();

// Find everything between [ and ] and save into $arrBookings array
// it also splits each comma up into its own array index
//
// everything between ( and ) pairs gets saved in the array, there are four below
// \ has to be used to escape the [ character, like escaping quotes in a string
// (.*?) is basically a wildcard for "everything" between one comma and the next
//
// this should read each [ ] pair into the following values:
// [ (array[1]),(array[2]),(array[3]),(array[4])
//
// Try echo "<pre>"; print_r($arrBookings); echo "</pre>"; to test the output
if (!preg_match_all("/\[\[?(.*?),(.*?),(.*?),(.*?)]/i", $bookings, $arrBooking_Input, PREG_SET_ORDER))
	throw new Exception('Invalid input found');
else {
	// There's probably a better way to do this, but it works for now
	
	// For each array in $arrBooking_Input (it's multidimensional)
	foreach ( $arrBooking_Input as $data )
	{
		// Create a new booking object
		$booking = new CBooking();
		
		// Copy values from $data into it
		$booking->name = $data[1];
		$booking->date = $data[2];
		$booking->some_other_var = $data[3];
		$booking->some_other_var2 = $data[4];
		
		// Add the booking object to our $arrBookings array
		array_push($arrBookings, $booking);
	}
	
	// We don't need this any more
	unset($arrBooking_input);
	
	// Now we have your input as a class which you can access with array notation :)
	echo "<pre>";
	print_r ( $arrBookings );
	echo "</pre>";
}
?>


Going to eat, I'll answer questions later.

I know that regex is awful, but I'm still learning.
 

Sic

Sic

Soldato
Joined
9 Nov 2004
Posts
15,365
Location
SO16
You should probably look into json_encode, json_decode, serialize and unserialize. Personally I prefer JSON.
 
Associate
OP
Joined
8 Mar 2007
Posts
2,176
Location
between here and there
You should probably look into json_encode, json_decode, serialize and unserialize. Personally I prefer JSON.

thats how i flattened the array.

I used jon_encode to create a string from the array.

I now want to create a loop to cut out all the data inbetween the [] and assign them a varaible as I've tried above.

any suggestions?
 

Pho

Pho

Soldato
Joined
18 Oct 2002
Posts
9,324
Location
Derbyshire
arh!!

you'll have to explain this a bit to me.

What is the above code doing?? Is it taking my string and creating a array with it??


preg_match_all takes your string and splits it into an array ($arrBooking_Input) whose structure is basically:

// First booking
$arrBooking_Input[0][1] = booking 1 name
$arrBooking_Input[0][2] = booking 1 date
$arrBooking_Input[0][3] = booking 1 third val (I don't know what it is)
$arrBooking_Input[0][4] = booking 1 fourth val (I don't know what it is)

// Second booking
$arrBooking_Input[1][1] = booking 2 name
$arrBooking_Input[1][2] = booking 2 date
$arrBooking_Input[1][3] = booking 2 third val (I don't know what it is)
$arrBooking_Input[1][4] = booking 2 fourth val (I don't know what it is)

etc.

It then just loops through this array using the foreach and converts that array into objects of type CBooking ($arrBookings) which is a class you could extend and do whatever with - you don't need this part, you could stop after the preg_match_all function if you wanted.

You can then reference say the name of the first booking using this:
echo $arrBookings[0]->name;
Or the second bookings date:
echo $arrBookings[1]->date;
 
Last edited:
Associate
OP
Joined
8 Mar 2007
Posts
2,176
Location
between here and there
cool thanks.

Thing is i really need one variable for each booking, so...

$book1 = [ Mavis , 2009 , 12 , 10 ]
$book2 = .......

and so on...


I could use your code to get that data by calling each part of the booking and cat'em together in to one varaible, but isn't there a simpler way??

If I run in trouble later on I need to be to understand and adjust the code.

I was thinking something along the lines of a for or while loop to get find the first instance of [ and ] and then assign the data in the middle to a varaible (${$book . $x} - where $book = book and $x = 1), then create a new variable in the same way but add 1 to $x and get the next bit of data.

I'm nearly there with what i have above it just gets misalined and pulls the wrong bit.

Please dont take this as me not being greatfull, as I am.

Many thanks

Blastman
 

Pho

Pho

Soldato
Joined
18 Oct 2002
Posts
9,324
Location
Derbyshire
This is why classes are beneficial.

Here's a function which merges the values back into what you want ([ Pooh , 2009 , 12 , 12 ]) when you run:
echo $arrBookings[0] or echo $arrBookings[1] etc.

PHP:
public function __tostring() {
	return '['.$this->name.','.$this->date.','.$this->some_other_var.','.$this->some_other_var2.']';
}


Full code with demo at the end:
PHP:
<?php

// You should make these private and use functions to access them instead of allowing direct access
class CBooking {
	public $name;
	public $date;
	public $some_other_var;		// 3rd offset in the data
	public $some_other_var2;	// 4th offset in the data
	
public function __tostring() {
	return '['.$this->name.','.$this->date.','.$this->some_other_var.','.$this->some_other_var2.']';
}
}

$bookings = "[[ Pooh , 2009 , 12 , 12 ],[ Mavis , 2010 , 10 , 31 ],[ Mk1 , 2010 , 6 , 1 ],[ Pooh , 2009 , 12 , 31 ],[ MK1 , 2010 , 2 , 29 ]]";

// To store the split up $bookings data
$arrBooking_Input = Array();
// To store results
$arrBookings = Array();

// Find everything between [ and ] and save into $arrBookings array
// it also splits each comma up into its own array index
//
// everything between ( and ) pairs gets saved in the array, there are four below
// \ has to be used to escape the [ character, like escaping quotes in a string
// (.*?) is basically a wildcard for "everything" between one comma and the next
//
// this should read each [ ] pair into the following values:
// [ (array[1]),(array[2]),(array[3]),(array[4])
//
// Try echo "<pre>"; print_r($arrBookings); echo "</pre>"; to test the output
if (!preg_match_all("/\[\[?(.*?),(.*?),(.*?),(.*?)]/i", $bookings, $arrBooking_Input, PREG_SET_ORDER))
	throw new Exception('Invalid input found');
else {
	// There's probably a better way to do this, but it works for now
	
	// For each array in $arrBooking_Input (it's multidimensional)
	foreach ( $arrBooking_Input as $data )
	{
		// Create a new booking object
		$booking = new CBooking();
		
		// Copy values from $data into it
		$booking->name = $data[1];
		$booking->date = $data[2];
		$booking->some_other_var = $data[3];
		$booking->some_other_var2 = $data[4];
		
		// Add the booking object to our $arrBookings array
		array_push($arrBookings, $booking);
	}
	
	// We don't need this any more
	unset($arrBooking_input);

	// Here's your book variables
	$book1 = $arrBookings[0];
	$book2 = $arrBookings[1];
	$book3 = $arrBookings[2];
	$book4 = $arrBookings[3];
	
	echo $book1 . "<br/>";
	echo $book2 . "<br/>";
	echo $book3 . "<br/>";
	echo $book4 . "<br/>";
}
?>
 
Last edited:

Sic

Sic

Soldato
Joined
9 Nov 2004
Posts
15,365
Location
SO16
Have you already created your input data? If you're using JSON to encode it, why not do it as named key => value pairs? If you json_decode the data you've already got there, you get nice arrays anyway:

PHP:
Array
(
    [0] => Array
        (
            [0] => pooh
            [1] => 2006
            [2] => 1
            [3] => 4
        )

    [1] => Array
        (
            [0] => mavis
            [1] => 2009
            [2] => 1
            [3] => 8
        )

    [2] => Array
        (
            [0] => mk1
            [1] => 2010
            [2] => 1
            [3] => 9
        )

)

Surely using that data has got to be easier than what you're attempting to do here?
 
Last edited:
Associate
OP
Joined
8 Mar 2007
Posts
2,176
Location
between here and there
the end result is i want all the data in a database to be pushed over to javascript.

I planned on get my data from the database then on the server split the enties up into thier own variables and then pass them over to javascript for comparason in a calendar that I've written.

The other thing is that as more bookings are placed, the string will get longer so having an array wont work as i can't code infinate amount of if array[x][0] is null as x keeps getting bigger.

The way i though it would work would simply create as many varaibles as needed and put the correct data in.

I can then count the rows in the array at the very begining and then get javascript to loop creating varaibles and passing data accross untill the array is empty.

I hope I'm making sense!?

So I really do need a little help with a for or while loop.

any suggestions?
 

Sic

Sic

Soldato
Joined
9 Nov 2004
Posts
15,365
Location
SO16
JSON stands for javascript object notation. If you push JSON to javascript (just echo it), then it can become a javascript array/object that can be used natively. Little example:

PHP: call this js.php

PHP:
$array = array('1','2','3','4');
echo json_encode($array);

JavaScript
PHP:
// all your ajaxy stuff, basically you want to have
// ajax loading js.php
// see http://mootools.net/docs/core/Request/Request.JSON
// the text that has been echoed in js.php can be transferred as 
// a javascript array
var r = new Request.JSON({
    'url' : '/js.php',
    'onSuccess' : function(json,text){
        alert(json[0]); // 1
    }
}).send();
 
Last edited:

Pho

Pho

Soldato
Joined
18 Oct 2002
Posts
9,324
Location
Derbyshire
Yeah your JSON approach was the best, I didn't even notice it looked like it :o.

Half my code was converting it into objects though which could be stripped out.
 

Sic

Sic

Soldato
Joined
9 Nov 2004
Posts
15,365
Location
SO16
hehe, to be honest, you could've probably got most of the battle using explode. I can appreciate blastman's wanting to become more familiar with PHP before doing things the "right" way, but that seems counterproductive to me. If you want to become familiar with the language, set yourself little tests like this, but don't use it in production as you'll come back to it in 6 months and be like "wtf was I thinking?!". I know this because I've done it before.
 
Back
Top Bottom