Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Saving Pets

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $4.00

Saving Pets

Ok, let’s talk about saving pets. No, not like rescuing them, though that’s really cool too. I’m talking about being able to submit our new pet form and saving that pet information somewhere so that it shows up on our site. I want to make our pet list truly dynamic!

We haven’t talked about databases yet, and we’re not using one. But actually, the pet data our site needs is being stored in a simple pets.json file. And this file is something we can read from and even update. And hey, that’s basically all a database really does. So if we can figure out how to update the pets.json file each time we submit this form, we’re in business!

First, we can re-use our get_pets function to get an array of all of the existing pets from the file. Let’s add this right at the bottom of our form processing code:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {

    // ...

    $pets = get_pets();
    var_dump($name, $breed, $weight, $bio);die;
}

Next, create an associative array that represents the new pet that’s being added. Make sure the keys you’re using match the existing pets from the file. We don’t have age or image fields yet, so just set those to be blank:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {

    // ...

    $pets = get_pets();

    $newPet = array(
        'name' => $name,
        'breed' => $breed,
        'weight' => $weight,
        'bio' => $bio,
        'image' => '',
        'age' => '',
    );

    var_dump($name, $breed, $weight, $bio);die;
}

Ok! Now just add that new pet to the $pets array:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {

    // ...

    $pets = get_pets();

    $newPet = array(
        'name' => $name,
        'breed' => $breed,
        'weight' => $weight,
        'bio' => $bio,
        'image' => '',
        'age' => '',
    );

    $pets[] = $newPet;

    var_dump($name, $breed, $weight, $bio);die;
}

Remember that the empty square brackets tells PHP we want to add something to the $pets array, but we don’t care what the items key is. It’ll choose a unique number for us.

Saving the Pets to pets.json

Now, $pets has all the existing little fur balls, and our new one. It basically represents what we want to save to pets.json.

Let’s do it! First, turn $pets back into JSON with PHP’s json_encode function. To actually save the file, use another PHP function: file_put_contents:

// ...
$pets[] = $newPet;

$json = json_encode($pets);
file_put_contents('data/pets.json', $json);

This is basically what the get_pets function does, only in reverse! json_encode turns the array into a string, and then we save it back to the file.

Let’s try it! Fill out the form and submit. An error!

Call to undefined function get_pets()

Ah, woops! That function lives in the functions.php file. If we want to use it, we need to require that file:

<?php
require 'lib/functions.php';

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    // ...
}

Ok, refresh and re-post the form. Hmm, it looks like it did nothing. But that’s not true! We submitted the form, our code detected this was a POST request, we saved the new stuff to pets.json, and then the page continued rendering the blank form. There weren’t any fireworks, but I think this worked!

Go to the homepage to find out for sure! We didn’t give it an image, but there’s our pet. We don’t even have a database, and we already have a dynamic app.

Readable JSON!

If you look at pets.json, it got flattened onto one line. That’s ok! Spaces and new lines aren’t important in JSON, and PHP saved without any extra whitespace. Again, that’s fine really.

But since I did like my file better when it was readable, give json_encode a second argument of JSON_PRETTY_PRINT:

$json = json_encode($pets, JSON_PRETTY_PRINT);

Fill out our form again. Hey, now pets.json looks awesome again. We are really good at training this digital pet :) JSON_PRETTY_PRINT is called a constant, which is kind of like a variable, exept that it’s magically available everywhere, doesn’t have a $, and its value can’t change. You won’t use them often, so don’t worry about them too much.

Leave a comment!

23
Login or Register to join the conversation

Hi there!
I can't seem to progress the challenge, even if I copy paste the provided solution. I assume it's broken, can you fix this?

Reply

Hey @Deniz

Can you point me to the challenge you're having troubles? I just tried out the challenges of this episode and I was able to solve them (The only gotcha is to fullfil the form in the Browser tab, and click on "Add toy")

Cheers!

Reply

Hey MolloKhan !
It just works now for some reason- thanks for checking!

Reply

Good to know! It may have been a short outage :)

Reply
Michał Ł. Avatar
Michał Ł. Avatar Michał Ł. | posted 3 years ago

Hello,
Copy all from "Show answer" and paste in the my 'new_toy.php' but all the time i have error
"Bummer! Not quite right, try again!
I don't see Bacon Bone in toys.json - double-check that you're keeping the original pets, not replacing them entirely."

Reply
Michał Ł. Avatar

Ok nevermind, I add __DIR__ . '/../toys.json' click check and then change it to toys.json and its work.

1 Reply
Daniel R. Avatar
Daniel R. Avatar Daniel R. | posted 4 years ago

I've been following along with Chapter 4 by loading the project in codeanywhere and editing the pets_new.php. Everything has worked fine up until this point until I try to submit the form and I get this warning "Warning: file_put_contents(data/pets.json): failed to open stream: Permission denied in /home/cabox/workspace/pets_new.php on line 44" at the top of the page. Any assistance in getting this to work would be much appreciated!

Reply

Hey Daniel R.

You have to give at least read permissions to such user/group on that folder/file so your code can access to it

Cheers!

1 Reply

Hello!
First of all, thank you for the quality of this course! :)
I discovered a bug on the first challenge, when I filled out the form and send it, I had an error but I still validated the challenge :p
I think you check only a var_dump message on the content of the web page even if it does not match with the expected answer.
My error : i forgot the quotation marks on the first parameter of the file_get_contents php function.
Hope this helps you!

Reply

Hey Yassin,

First of all, thank you for your kind words and reporting this issue. I just double checked it and, unfortunately, I wasn't able to reproduce it. If I missed quotes for the 1st argument of file_get_contents(), i.e. call "file_put_contents(toys.json, $json);" - I would have an error and the system does not consider my answer as correct. But there's some tricky part - if you answered the challenge correctly before - then the "Fluffy Pig Stuffed Animal" IS already in the list because we store it into the file, and on the 2nd go when you send form with "file_put_contents(toys.json, $json);" it will show an error in the browser but consider the answer as correct. Anyway, I think it's OK because we handle it right on the first go and just because we don't want to complicate our grading system. Yes, sometimes you can bypass the grading system and mark challenges as correct but you need to know how the grading works for current challenge, so it's up to you :) We don't want to give you a super secure system where you 100% could not cheat, we just want to help you to catch stupid misprints and push you to the right direction ;)

But sometimes our challenges may have some bugs, so if you find a weird behavior - please, leave a comment again!

Cheers!

Reply
Tariq I. Avatar
Tariq I. Avatar Tariq I. | Victor | posted 3 years ago | edited

<?phpphp tag
require DIR.'/lib/functions.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {

$name =$_POST['name'];
$description = $_POST['description'];
$toys = get_great_pet_toys();
$new_toy = ['name'=>$_POST['name'], 'description'=>$_POST['description']];
$toys[] = $new_toy;
file_put_contents(__DIR__.'/../toys.json',json_encode($toys));
$json = json_decode(file_get_contents(__DIR__.'/../toys.json'),true);
var_dump($json);

}
$json = json_decode(file_get_contents(DIR.'/../toys.json'),true);
var_dump($json);
?>

<form action="/new_toy.php" method="POST">

<input type="text" name="name" />
<textarea name="description"></textarea>

<button type="submit">Add toy</button>

</form>

Reply
Tariq I. Avatar
Tariq I. Avatar Tariq I. | Tariq I. | posted 3 years ago | edited

This code produces error like this:I don't see a new toy with name Fluffy Pig Stuffed Animal in toys.json. Are you adding it to the toys array before calling json_encode() and saving the file?

But on the browser window var_dump output shows the presence of 'Fluffy Pig Stuffed Animal' in the $json array decoded from the 'toys.json' file.

What could be the reason?
(On top of my code I've written php tag but it is not getting printed on the comment.)

Reply

Hey Tariq,

Are you talking about a challenge? If so, what challenge exactly? Could you link to it? Also, did you compare your code with the challenge answer? Also, I'd recommend you to try to execute your answer again on the new fresh challenge instance so that our system boots it from scratch.

Cheers!

Reply
Tariq I. Avatar

Challenge 4.1(new_toy.php)

Reply

Hey Tariq,

Now I see... We're sorry to confuse you, but the problem is that you store the file in the parent directory, i.e. "__DIR__.'/../toys.json'", but we're expecting the file in the *current* directory instead, so basically "file_get_contents(__DIR__.'/toys.json')" or just "file_get_contents('toys.json')" should both work.

That's because of some limitation on our side to make think not too complex. And it looks like you're the first who tried a different from the current path :)

Cheers!

Reply
Tariq I. Avatar

Thanks a lot...it worked !!! :-)

Reply

Hey Tariq,

Great! Thank you for replying back and confirming this works for you now!

Cheers!

Reply
Default user avatar

Hello
Copy all from "Show answer" and paste in the my 'new_toy.php' but take mistake
Bummer! Not quite right, try again!
You should send a POST request: use the form in Browser to add a new toy with specific name.
What wong?

Reply

Hey Nina,

This challenge is pretty tricky ;) Pressing "Check" button sin't enough here, you need to send a really POST request, it means you need to fill in input fields with proper values on the "Browser" tab and press "Add toy" - this way a real POST request will be sent :)

Cheers!

Reply
Default user avatar
Default user avatar Christoph Potzinger | posted 5 years ago

Hi, even when I post use the code from the Answer section, it does not work. I keep getting "Fatal error: Call to undefined function get_great_pet_toys() in /var/www/code/new_toy.php on line 8. Looks like there is some problem with the path to the file with the function. Please help.

Reply

Hey Christoph Potzinger!

Oh no! Hmm. So I just tried the first challenge myself on this chapter (this one - just to make sure we're talking about the right one! https://knpuniversity.com/s... and I did *not* get the undefined function error. Do you have the "require" line on top? You mentioned you used the Answer code, so you should - but that require line should bring in lib/functions.php... which should bring in that function. Do you see any other errors? For example, if you *do* have the require line, do you see any error about "lib/functions.php" not existing?

Cheers!

Reply
Default user avatar
Default user avatar Christoph Potzinger | weaverryan | posted 5 years ago

Hi, thanks for your fast reply. I fixed it by completely reloading the page and pasting in the answer code. My problem might have been caused by the fact that I had a few errors before trying the answer code. It looks that my errors messed up the challenge validation. I could now pass the challenge. So all fixed! Thanks for your quick reaction - this is a Sunday, wow!

Reply

Awesome! And you might be right - the challenges are the wild west - we really let you do whatever you want in your code :). You could even delete (via PHP) the functions.php file... and yep, then you'd really be in trouble. Whatever the reason, happy it worked out for you!

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

userVoice