Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This course is archived!
This tutorial uses a deprecated micro-framework called Silex. The fundamentals of REST are still ? valid, but the code we use can't be used in a real application.

Project Routing

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Project Routing

Ok, let’s get start by downloading (see the Download button for subscribers) or cloning the CodeBattles project. Now, follow the README.md file to get things working. It involves downloading Composer and installing the vendor libraries:

$ git clone https://github.com/knpuniversity/rest.git
$ cd rest
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar install

Tip

If you’re new to Composer, watch The Wonderful World of Composer.

When that’s done, start up the app by using PHP’s awesome built-in web server:

$ cd web
$ php -S localhost:8000

Note

The built-in web server requires PHP 5.4, which all of you should have! If you’re using PHP 5.3, you’ll need to configure a VirtualHost of your web server to point at the web/ directory.

If it worked, then load up the site by going to http://localhost:8000. Awesome!

About the App

CodeBattles is built in Silex, a PHP microframework. If this is your first time using Silex, take a few minutes with its Documentation to get to know it. It basically let’s us design routes, or pages and easily write the code to render those pages. Our setup will look just a little bit different than this, but the idea is the same.

But this is not a tutorial on building a REST API on only Silex! Most of what we’ll do is basically the same across any framework. You will need to do a little bit of work here and there. But trust me, these things are a pleasure to do compared with all the tough REST stuff.

First Endpoint: POST /api/programmers

Let’s pretend we’re building the API for an iPhone app. Ignoring authentication, what’s the first thing the user will do in the app? Create a programmer of course! And that’s our first API endpoint.

Separate URLs from our Web Interface?

But hold up! In the web version of our app, we’re already able to create a programmer by filling out a form and submitting it via POST to /programmers/new. This either re-renders the HTML page with errors or redirects us.

Why not just reuse the code from this URL and make it work for our API? To do this we’d need to make it accept JSON request data, become smart enough to return errors as JSON and do something other than a redirect on success. Then, /programmers could be used by a browser to get HTML or by an API client to pass JSON back and forth.

That would be sweet! And later, we’ll talk about how you could do that. But for now, things will be a lot easier to understand if we leave the web interface alone, prefix our API URLs with /api, and write separate code for it.

This does break a rule of REST, because each resource will now have 2 URLs: one for HTML and one for the JSON representation. But REST has a lot of rules, too many for our rebel Codebattles site. We’ll break this one, like many APIs. But later, I’ll show you how we could use 1 URL to return multiple representation.

Basic Routing

So let’s build the endpoint. Find the src/KnpU/CodeBattle/Controller/Api/ProgrammerController.php file and uncomment the route definition:

// src/KnpU/CodeBattle/Controller/Api/ProgrammerController.php
// ...

protected function addRoutes(ControllerCollection $controllers)
{
    $controllers->post('/api/programmers', array($this, 'newAction'));
}

Next, create a newAction inside of this class and return let's battle!:

// src/KnpU/CodeBattle/Controller/Api/ProgrammerController.php
// ...

public function newAction()
{
    return 'let\'s battle!';
}

And just like that, we’re making threats and we have a new endpoint with the URL /api/programmers. If we make a POST request here, the newAction function will be executed and these famous last words will be returned in the response. This is the core of what Silex gives us.

URLs and Resources

My choice of a POST request to create a programmer isn’t accidental. /api/programmers is a collection resource. And according to some HTTP rules I’ll show you later, when you want to create a resource, you should send a POST request to its collection.

In other words, I’m not making this all up: I’m following the rules of the web. And in the API world, if you follow the rules, you’ll have more friends.

Testing the Endpoint

Well let’s try it already! That’s actually not easy in a browser, since we need to make a POST request. Instead, open up the testing.php file at the root of the project that I’ve already prep’ed for us:

// testing.php
require __DIR__.'/vendor/autoload.php';

use Guzzle\Http\Client;

// create our http client (Guzzle)
$client = new Client('http://localhost:8000', array(
    'request.options' => array(
        'exceptions' => false,
    )
));

This is a plain PHP file that creates a Guzzle Client object. Guzzle is a simple library for making HTTP requests and receiving responses.

Let’s make a POST request to /api/programmers and print out the response:

// testing.php
// ...
$client = new Client('http://localhost:8000', array(
    'request.options' => array(
        'exceptions' => false,
    )
));

$request = $client->post('/api/programmers');
$response = $request->send();

echo $response;
echo "\n\n";

Try it out by running the file from the command line. You’ll need to open a new terminal tab and make sure you’re at the root of the project where the file is:

$ php testing.php
HTTP/1.1 200 OK
Host: localhost:8000
Connection: close
Cache-Control: no-cache
Content-Type: text/html; charset=UTF-8

let's battle!

Success!

Leave a comment!

68
Login or Register to join the conversation
Juan R. Avatar
Juan R. Avatar Juan R. | posted 1 year ago

Soryy , no working tuto : Deprecated: Return type of Pimple::offsetExists($id) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /Users/juanroussille/Documents/api_rest/rest/vendor/pimple/pimple/lib/Pimple.php on line 93

Reply

Hey @Roussille!

Yes, unfortunately while many of the concepts of this tutorial are still valid, this tutorial is VERY hold and won't work on newer php versions. We mention this on the main page, but it might be too subtle: https://symfonycasts.com/sc.... I've just archived this course to make it more obvious.

Cheers!

Reply
Gaetano S. Avatar
Gaetano S. Avatar Gaetano S. | posted 3 years ago

Hi,
I'm trying to start the project and I'm using Docker. Just 3 Services: apache, mysql, php. I configured my virtualhost conf to point at web folder. I have this error:

- Fatal error: Uncaught Symfony\Component\Filesystem\Exception\IOException: Failed to chmod file "/var/www/html/src/KnpU/CodeBattle/../../../data". in /var/www/html/vendor/symfony/filesystem/Filesystem.php on line 199

- Symfony\Component\Filesystem\Exception\IOException: Failed to chmod file "/var/www/html/src/KnpU/CodeBattle/../../../data". in /var/www/html/vendor/symfony/filesystem/Filesystem.php on line 199

I don't understand how to fix this problem because it's a weird permission problem.

Thanks for your help.

Reply

Hey Gaetano,

I suppose you downloaded the course code and start from start/ directory? If so, have you read the README.md inside that folder? In particular, the 4th step is responsible for that data/ folder you see in the error. You have to make it writable and executable, in other words set its permissions to 777. The same for logs dir. Basically, you need to execute this command:

$ chmod 777 logs data```


I hope this helps!

Cheers!
Reply
Sebastian R. Avatar
Sebastian R. Avatar Sebastian R. | posted 3 years ago | edited

I am trying execute the test in php storm:

`Testing started at 9:30 a. m. ...
C:\xampp\php\php.exe C:/Users/sebas/AppData/Local/Temp/ide-phpunit.php --configuration C:\xampp\htdocs\doki\dev2\phpunit.xml.dist Tests\AppBundle\Controller\DoctorControllerTest C:\xampp\htdocs\doki\dev2\tests\AppBundle\Controller\DoctorControllerTest.php
PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in C:\xampp\php\pear\PHPUnit\TextUI\Command.php on line 277
PHP Stack trace:
PHP 1. {main}() C:\Users\sebas\AppData\Local\Temp\ide-phpunit.php:0
PHP 2. spl_autoload_call() C:\Users\sebas\AppData\Local\Temp\ide-phpunit.php:272
PHP 3. IDE_PHPUnit_Loader::{closure:C:\xampp\php\pear\PHPUnit\Autoload.php:71-207}() C:\Users\sebas\AppData\Local\Temp\ide-phpunit.php:272
PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in C:\xampp\php\pear\PHPUnit\TextUI\Command.php on line 285
PHP Stack trace:
PHP 1. {main}() C:\Users\sebas\AppData\Local\Temp\ide-phpunit.php:0
PHP 2. spl_autoload_call() C:\Users\sebas\AppData\Local\Temp\ide-phpunit.php:272
PHP 3. IDE_PHPUnit_Loader::{closure:C:\xampp\php\pear\PHPUnit\Autoload.php:71-207}() C:\Users\sebas\AppData\Local\Temp\ide-phpunit.php:272
PHP Fatal error: Uncaught Error: Class 'PHPUnit\Framework\TestCase' not found in C:\xampp\htdocs\doki\dev2\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Test\KernelTestCase.php:24
Stack trace:
#0 C:\xampp\htdocs\doki\dev2\vendor\composer\ClassLoader.php(444): include()
#1 C:\xampp\htdocs\doki\dev2\vendor\composer\ClassLoader.php(322): Composer\Autoload\includeFile('C:\xampp\htdocs...')
#2 [internal function]: Composer\Autoload\ClassLoader->loadClass('Symfony\Bundle\...')
#3 C:\xampp\htdocs\doki\dev2\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Test\WebTestCase.php(22): spl_autoload_call('Symfony\Bundle\...')
#4 C:\xampp\htdocs\doki\dev2\vendor\composer\ClassLoader.php(444): include('C:\xampp\htdocs...')
#5 C:\xampp\htdocs\doki\dev2\vendor\composer\ClassLoader.php(322): Composer\Autoload\includeFile('C:\xampp\htdocs...')
#6 [internal function]: Composer\Autoload\ClassLoader->loadClass('Symfony\Bundle\...')
#7 C:\xampp\htdocs\doki\dev2\tests\AppBundle\Controller\BaseController.php(7): spl_au in C:\xampp\htdocs\doki\dev2\vendor\symfony\symfony\src\Symfony\Bundle\FrameworkBundle\Test\KernelTestCase.php on line 24

Process finished with exit code 25`

Reply

Hey Sebastian R.

The PHP warning "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? comes from PHP 7.3. I'll check if that's a problem with an old dependency of this course, in the meantime you can downgrade to PHP 7.2 so you can keep going.

Cheers!

Reply
Default user avatar

I already have composer in global enviroment, do i need to install it again ?

Reply

Hey wuwu,

Not really, but you may want to update it in case it's an old installation

Cheers!

Reply

Hi there. I tried to start up the project and when setting up the localhost I get this error:

Fatal error: Uncaught PDOException: could not find driver in C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOConnection.php:43 Stack trace: #0 C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOConnection.php(43): PDO->__construct('sqlite:C:\\Bitna...', 'root', NULL, Array) #1 C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\PDOSqlite\Driver.php(56): Doctrine\DBAL\Driver\PDOConnection->__construct('sqlite:C:\\Bitna...', 'root', NULL, Array) #2 C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Connection.php(360): Doctrine\DBAL\Driver\PDOSqlite\Driver->connect(Array, 'root', NULL, Array) #3 C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Connection.php(973): Doctrine\DBAL\Connection->connect() #4 C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Schema\AbstractSc in C:\Bitnami\wampstack-7.3.11-0\apache2\htdocs\rest\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\AbstractSQLiteDriver.php on line 85

I saw in the comments that someone else had this problem already but I'm not to sure how to fix it? I've only used phpstorm to write my own code. This is the first time using dependencies.

EDIT: I was able to fix the problem by going into the php.ini and putting

extension=pdo_mysql

in comments and uncommenting the following:

extension=pdo_sqlite

Maybe include this in the readme file so the setup will run smoother

Reply

Hey juantreses!

Nice job finding your fix - it was 100% correct! These things are tricky, because making sure the PDO SQLITE PHP extension is available is *totally* different on every operating system - Windows, OSX, Ubuntu - sometimes different even inside the same operating system. That's the main reason we don't include it in the README. But I think *mentioning* that you need to have the PDO SQLITE PHP extension installed might at least help a bit - I'll check into that :).

Cheers!

Reply

Hey Ryan, today I ran into the same problem on a different project. I changed it back to extension=pdo_mysql but it's still refusing to work. I'm completely out of the loop at the moment.

Reply

Hey juantreses

What error are you having? Can you double-check that the PDO extension is installed and loaded in your new project?

Cheers!

Reply
Frank G. Avatar
Frank G. Avatar Frank G. | posted 3 years ago

Hi there,

the Api-tutorials are great. A lot of details are explained easily, that really saves time.

On the other hand a general question:
I'm looking for an introduction on how to merge the Api endpoints, resources etc. into one app. For example, how do I create a functional web app based on Api documentation (endpoints/operations)? I would like to create a ShoppingCart application based on Api and have no idea how to lead the responses step by step to the checkout. A SessionId doesn't have an Api, does it?

If you have such a general description in your tutorials, that would be great. If not, I would also be very grateful for a hint to some example application on the web.

Greetings
Frank

Reply

Hey @dergraf!

Really excellent question :). Let's think about this. First, it probably makes sense at the start of a "checkout" to create some sort of Order record in your database that has an id. This is a really easy way for you to have an "id" that you can use throughout the process.

Then, I can see a checkout process in two different ways: (A) A checkout process consists of multiple different UI "steps" that each, under the hood, are making requests to update some Order resource. This... may be an over-simplification, however - as you'll probably need different validation depending on each step. So, just making a PUT request to /api/orders/1 4 different times (for the 4 different steps of information) seems weird to me. (B) Another way to look at this process is that it's a workflow... and you can do some really interesting things with API Platform and the Workflow component and we have a really nice presentation about it here on the site. It's about the ordering process of a pizza, so it may not be far off from what you're thinking about doing: https://symfonycasts.com/screencast/symfonycon2018/power-sf-components-apiplatform

This is a LONG way of saying that... I'm honestly not sure what the best way is to model all of this out. Personally, I would map out the UI first, figure out what API requests your front-end would need to make, and see if an obvious model of how the API should look comes from this. Checkout processes are delicate and complex beasts - it's definitely a post where I'd want my UI to drive things versus just exposing entities as API resources and making the UI work with that. Also, it may be that you literally decide to create custom, non-entity API Resource classes for each step - e.g. CheckoutCollectAddressInfoStep, CheckoutSetShippingInfoStep, etc. There may be better ways to handle this (this "feels" like a workflow), but ultimately, by creating custom classes and exposing as API resources (something we'll talk about in the next API Platform tutorial) gives you maximum power over what each endpoint looks like.

I hope this helps - even if I don't really have a clear answer for you :). Btw, to give you an idea about how we do it in SymfonyCasts, we don't use API Platform endpoints for checkout, but we more-or-less have the equivalent of (A) an Order entity that can be created/edited to add items to it and (B) a custom API endpoint that handles all the payment info... which technically behind the scenes is creating a Payment that's related to the Order. It's not a huge, multi-step process... but the result is very simple - it's a few operations related to Order and its related Payment.

Cheers!

Reply
Avraham M. Avatar
Avraham M. Avatar Avraham M. | posted 3 years ago

Hi, thanks great series!

I downloaded the source code, moved to start directory
composer install

Package silex/silex is abandoned, you should avoid using it. Use symfony/flex instead.
Package guzzle/guzzle is abandoned, you should avoid using it. Use guzzlehttp/guzzle instead.

Ok, I have read the The end of Silex article,
yet it seems to load and works, I will try.

Thanks!

Reply

Hey Avraham,

Yes, Silex is EOL in favor of Symfony Flex, so you should avoid using it in real projects, I'd recommend you to start with Symfony Flex instead. Also, the guzzle/guzzle version we using in this course is already outdated, and there's a new version of it, see guzzlehttp/guzzle. But anyway, concepts we're covering in this course are still relevant. So, if you just want to learn RESTful APIs and code along with us - you can continue using Silex and do exactly what we show in this screencasts- it's enough for learning purposes.

Cheers!

Reply

Hey there,
If you follow this tutorial with symfony local web server with tls, you could have this error message : PHP Fatal error: Uncaught Guzzle\Http\Exception\CurlException: [curl] 60: [url] https://localhost:8000/api/programmers

For solve this, you could disable SSL verification from Guzzle.
Add in testing.php : <br />$client->setDefaultOption('verify', false);<br />

Reply
Ray D. Avatar

When running the testing.php file, I'm getting a 404 error, any idea on what gives?

Yes, I'm in the root folder, yes the php server is running correctly.

PS E:\public_html\sites\rest> php testing.php
HTTP/1.1 404 Not Found
Host: localhost:8000
Date: Wed, 11 Jul 2018 14:56:09 +0000, Wed, 11 Jul 2018 14:56:09 GMT
Connection: close
X-Powered-By: PHP/7.2.2
Cache-Control: no-cache
Content-Type: text/html; charset=UTF-8
...

Reply

Hey there!

Hmmm. To debug this, I would try this:

A) In ProgrammerController::addRoutes, temporarily change $controllers->post to $controllers->get so that this matches a GET request.

B) In your browser, go to http://localhost:8000/api/programmers

I assume this will give you a 404. But then, it might at least make it a bit more obvious what's causing that 404 - especially if you can see if the 404 is coming from the PHP web server (it will say "The requested resource / was not found on this server.") or if it is getting into our Silex app, and the error is coming from Silex.

Let me know what you find out!

Cheers!

Reply
Tonislav A. Avatar

I'm having the same issue. There is no route configured for "/". GET request returns "The requested resource /api/programmers was not found on this server." This is from the web server: "[Tue Oct 30 16:46:48 2018] 127.0.0.1:38126 [404]: / - No such file or directory", "[Tue Oct 30 16:47:33 2018] 127.0.0.1:38182 [404]: /api/programmers - No such file or directory". I haven't done any modifications to the code. Just cloned the repo, ran composer install and started the web server.

Reply

Hey Tonislav A.!

Ah, so to be clear, you get this error:

> The requested resource /api/programmers was not found on this server.

Is that right? Did you start the built-in PHP web server from inside of the web/ directory? If you started it in the root of the project, that would cause problems like this. Or it could be something else. Let me know!

Cheers!

1 Reply
Tonislav A. Avatar
Tonislav A. Avatar Tonislav A. | weaverryan | posted 4 years ago | edited

Hey weaverryan
I just tried running the web server from the web directory. It seems to be working, because now I am getting an exception and not 404. I think it was something related to paths, because I ran composer install and then moved the contents of the start directory to the project root. Re-init the project, moved the contents of start to root and removed start and finish dirs. Ran composer install and then ran the server from within the web dir and now it's up and running! Thanks for the help!

1 Reply
Ray D. Avatar

So, to follow up (a week later) there's still an error, seems like the route is not found. :(

1/2
ResourceNotFoundException in UrlMatcher.php line 102:
No routes found for "/api/programmers".

2/2
NotFoundHttpException in RouterListener.php line 159:
No route found for "GET /api/programmers"

I thought it might be Guzzle, so I adjusted how the client was created, and eliminated the options using jsut the base uri, but still have the same issue. POST or GET gives me the same error page, so somehow along the way, the route is missing. and I don't understand why.

--EDIT--

So, I started over. reinstalled the whole project, and now it works. I'm not sure what different steps I may have taken, but it's good, so all's well that ends well.

Reply

Hmm, interesting, probably you imported the wrong Route namespace or something like that :)
I'm glad that you could fix your problem

Cheers!

Reply
Rajaona F. Avatar
Rajaona F. Avatar Rajaona F. | posted 5 years ago

Hi, i've this problem

Fatal error: Uncaught Symfony\Component\Filesystem\Exception\IOException: Failed to chmod file "/home/ywoume/www/rest/src/KnpU/CodeBattle/../../../data". i've doing chmod -R 777 logs/ and create a data directory in parent and doing 777 in data/ directory but i've this error

Reply

Hey Rajaona F.

Could you show me the full error message? I'm not sure what's going on, maybe the data folder is not being found or you don't have the right permissions

I need more info about the error so I can help you debugging :)

Cheers!

Reply
Rajaona F. Avatar

i have this error when i use my apache 127.0.0.1/rest in ls -s /home/myfolder/www/rest /var/www/html when i use in localhost:8000 it was working . this is the full error

Fatal error: Uncaught UnexpectedValueException: The stream or file "/home/ywoume/www/rest/src/KnpU/CodeBattle/../../../logs/development.log" could not be opened: failed to open stream: Permission denied in /home/ywoume/www/rest/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php on line 70
( ! ) UnexpectedValueException: The stream or file "/home/ywoume/www/rest/src/KnpU/CodeBattle/../../../logs/development.log" could not be opened: failed to open stream: Permission denied in /home/ywoume/www/rest/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php on line 70

Reply

Oh, so you have a permissions problem, try this:


$ chmod www-data:www-data var/*

(you may need to run it with "sudo")

Cheers

Reply
Default user avatar

Hello, i am getting this error: RuntimeException in NativeSessionStorage.php line 144:
Failed to start the session because headers have already been sent by "/Users/user/rest/vendor/monolog/monolog/src/Monolog/Logger.php" at line 214.
PHP version is 5.527. Thank you!

Reply
Default user avatar

I have installed php 5.4.45 and is working now, but i still have one warning:

Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/user/rest/vendor/monolog/monolog/src/Monolog/Logger.php on line 214

Reply

Hi Florin!

Ah, I know this problem :). This is a classic problem when you first install php - you need to set the date.timezone setting in php.ini. First, you need to find your php.ini file. If you're using the built-in php web server, you can find it by running this from the command line:

php --ini

Look for "Loaded Configuration File". That's your php.ini path. Open that file in an editor (you'll probably need sudo), and find the date.timezone line. Make sure it is not commented out (remove the ; at the beginning of the line) and set it to your timezone (from this list http://php.net/manual/en/ti.... Mine looks like this:

date.timezone = America/Detroit

Then, kill your build-in web server (ctrl+c) and run it again. All should be well :)

Cheers!

Reply
Default user avatar
Default user avatar agape801 | posted 5 years ago

Hello I am getting this error Fatal error: Uncaught exception 'Guzzle\Http\Exception\CurlException' with message '[curl] 7: Failed to connect to localhost port 8000: Connection refused [url] http://localhost:8000/api/programmers' in C:\Users\Agape\rest\vendor\guzzle\guzzle\src\Guzzle\Http\Curl\CurlMulti.php:359 ... I've tried 127.0.0.1 as well and it didnt work

Reply

Hey there!

Hmm, it just looks like your local web server isn't running. When you get this error, are you able to go to `http://localhost:8000/api/programmers` in your browser? I expect that you will also see a connection refused error when you do this. If so, check that you started your built-in web server correctly - the commands are near the top of the script on this page :).

Cheers!

Reply
Default user avatar

After cloning the Git repo, which branch do we switch to? The "master" branch already contains the finished code, and none of the other existing remote branches seems to start from the point where this video starts from.

Reply

Hey Marin

Master branch should contain the starting files for this tutorial (From chapter 1), if for some reason you are getting the finished files (which is weird) you can download the project from this page, in the right upper corner we have a "Download" button. I hope it helps you :)

Have a nice day!

Reply
Default user avatar
Default user avatar Marin | MolloKhan | posted 5 years ago | edited

My bad MolloKhan, I was looking at "KnpU\CodeBattle\Controller\ProgrammerController", while the tutorial works on "KnpU\CodeBattle\Controller\Api\ProgrammerController", which indeed starts as a blank file when cloning the repo.

Reply

No problem man :) I'm glad I could help you.

Cheers!

Reply
Default user avatar
Default user avatar 3amprogrammer | posted 5 years ago | edited

I am using laravel/homestead box and when I try to access code-battles.dev my browser downloads the file, but when I type code-battles.dev/index.php everything works just fine. I have tried to do some googling, but yet without any success.

This is my conf file. Can you please give me some hint as I dont know nginx much.


server {
    listen 80;
    listen 443 ssl http2;
    server_name code-battles.dev;
    root "/home/vagrant/Code/code-battles/web";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/code-battles.dev-error.log error;

    sendfile off;

    client_max_body_size 100m;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
    }

    location ~ /\.ht {
        deny all;
    }

    ssl_certificate     /etc/nginx/ssl/code-battles.dev.crt;
    ssl_certificate_key /etc/nginx/ssl/code-battles.dev.key;
}
Reply

Hey 3amprogrammer!

Yea, Homestead is awesome! We have some docs about specifically using it with Symfony, in case you haven't seen it already :) http://symfony.com/doc/curr...

But specifically, the issue is that Symfony doesn't have an "index.php" file - it has "app.php" and "app_dev.php". The best way to solve this is either to:

A) Look back at your homestead setup - it has configuration for symfony, which should take care of this for you
B) Look at the Nginx documentation for Symfony - http://symfony.com/doc/curr... - and tweak your setup to match this.

In both cases, what you basically need to change is to tell Nginx to execute either app.php or app_dev.php, instead of index.php.

Let me know if this helps! Cheers!

Reply
Default user avatar
Default user avatar 3amprogrammer | weaverryan | posted 5 years ago

Thanks for the replay. I have no idea what the heck was wrong, but when I removed the files and pasted it again everything magically worked - probably it was some issue with permissions, I have no idea.

And by the way, I think you misunderstood me. Homestead works well with Symfony all it needs is to add type: Symfony to Homestead.yaml.
I had a problem of running regular app from REST course using index.php as a root, not app.php or app_dev.php.

Nevertheless, everything is working fine now. I really appreciate I can count on you when any questions pop out :)

Reply

Ah, thanks for the clarification - I looked too quickly and didn't notice which tutorial you were asking about! I'm glad you got it working - despite my not-so-perfect help :).

And yep, we're here if you have any comments or questions - both help everyone.

Cheers!

Reply
Default user avatar
Default user avatar Lim Ken | posted 5 years ago

Hi, I tried to clone and launch the app. However, I am getting the following when I go to localhost:8000

Warning: date_default_timezone_get(): It is not safe to rely on
the system's timezone settings. You are *required* to use the
date.timezone setting or the date_default_timezone_set() function. In
case you used any of those methods and you are still getting this
warning, you most likely misspelled the timezone identifier. We selected
the timezone 'UTC' for now, but please set date.timezone to select your
timezone. in /Users/rayner/learning/restapi/rest/vendor/monolog/monolog/src/Monolog/Logger.php on line 214

Whoops, looks like something went wrong.

1/1
RuntimeException in NativeSessionStorage.php line 144:
Failed to
start the session because headers have already been sent by
"/Users/rayner/learning/restapi/rest/vendor/monolog/monolog/src/Monolog/Logger.php"
at line 214.

in NativeSessionStorage.php line 144
at NativeSessionStorage->start() in NativeSessionStorage.php line 268
at NativeSessionStorage->getBag('attributes') in Session.php line 97
at Session->set('_security.main.target_path', 'http://localhost:8000/') in ExceptionListener.php line 213
at ExceptionListener->setTargetPath(object(Request)) in ExceptionListener.php line 191
at ExceptionListener->startAuthentication(object(Request), object(InsufficientAuthenticationException)) in ExceptionListener.php line 131
at ExceptionListener->handleAccessDeniedException(object(GetResponseForExceptionEvent), object(AccessDeniedException)) in ExceptionListener.php line 97
at ExceptionListener->onKernelException(object(GetResponseForExceptionEvent), 'kernel.exception', object(EventDispatcher))
at call_user_func(array(object(ExceptionListener), 'onKernelException'), object(GetResponseForExceptionEvent), 'kernel.exception', object(EventDispatcher)) in EventDispatcher.php line 164
at EventDispatcher->doDispatch(array(array(object(ExceptionListener), 'onKernelException'), array(object(LogListener), 'onKernelException'), array(object(ExceptionHandler), 'onSilexError')), 'kernel.exception', object(GetResponseForExceptionEvent)) in EventDispatcher.php line 53
at EventDispatcher->dispatch('kernel.exception', object(GetResponseForExceptionEvent)) in HttpKernel.php line 224
at HttpKernel->handleException(object(AccessDeniedException), object(Request), '1') in HttpKernel.php line 76
at HttpKernel->handle(object(Request), '1', true) in Application.php line 581
at Application->handle(object(Request)) in Application.php line 558
at Application->run(object(Request)) in index.php line 27

Reply

Hey Lim,

This error means you don't configure your PHP environment, you need to set up timezone in your php.ini. Open the php.ini file, find "date.timezone", uncomment this line and set it to your timezone or to UTC. To see supported timezones: http://php.net/manual/en/ti...

Cheers!

1 Reply
Default user avatar
Default user avatar curious | posted 5 years ago

Do course1 has different repo ?

Reply

Hey @curious!

Both of the REST courses (this one and part 2) are built on the same project and same repository (https://github.com/knpunive.... Does that help? If you download the course code for episode 2, we actually give you the correct starting code for that course (which is the same finish code as this course - course 1).

I'm not sure if I answered your question correctly - but if not - let me know and we'll be happy to help.

Cheers!

Reply
Default user avatar
Default user avatar ciudadano82 | posted 5 years ago

Hi guys! i'm having a problem with the testing file. It throws me a 403 error. However, when i run it from the browser, it throws me the right response (i've changed the post() call to a get() call to prove it there, and also changed the guzzle request to a get call). Any help?

Reply

Wow, that *is* weird! But, I like your debugging techniques :). At this point, we haven't added any security, so it seems like the 403 is probably not coming from our Silex app (but, I could be missing something). Does the 403 (if you print out the response content in the test file) "look" like it's coming from your web server? Are you using the built-in web server? What happens if you try to curl the URL directly - e.g. curl http://localhost:8000/...

I'm sure we can figure this out :)

Reply
Default user avatar
Default user avatar Emberous | posted 5 years ago

Hello, i am getting this error: Fatal error: Uncaught exception 'PDOException' with message 'could not find driver' in /usr/share/nginx/html/test/rest/rest/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:40 Stack trace: #0

Reply

Hey!

The project uses SQLITE, so this sounds to me like pdo-sqlite driver isn't installed/enabled in your PHP install. If you run "php -i | grep sqlite", you should see some output related to pdo_sqlite (or if you're on windows, you can just run "php -i" and look in the output for pdo_sqlite stuff). Anyways, I think you *won't* find anything there. In that case, check how you installed PHP to see how to get this enabled.

Cheers!

Reply
Richard Avatar
Richard Avatar Richard | posted 5 years ago

Is composer missing something?

Fatal error: Uncaught PDOException: could not find driver in /home/rgr/development/gitprojects/rest/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php on line 85
( ! ) Doctrine\DBAL\Exception\DriverException: An exception occured in driver: could not find driver in /home/rgr/development/gitprojects/rest/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php on line 85
Call Stack
# Time Memory Function Location
1 0.0001 358600 {main}( ) .../index.php:0
2 0.0001 358920 require_once( '/home/rgr/development/gitprojects/rest/app/bootstrap.php' ) .../index.php:6
3 0.0028 582008 KnpU\CodeBattle\DataFixtures\FixturesManager->resetDatabase( ) .../bootstrap.php:31
4 0.0047 814616 Doctrine\DBAL\Schema\AbstractSchemaManager->dropAndCreateTable( ) .../FixturesManager.php:48
5 0.0057 840360 Doctrine\DBAL\Schema\AbstractSchemaManager->createTable( ) .../AbstractSchemaManager.php:583
6 0.0068 963808 Doctrine\DBAL\Schema\AbstractSchemaManager->_execSql( ) .../AbstractSchemaManager.php:443
7 0.0068 963808 Doctrine\DBAL\Connection->executeUpdate( ) .../AbstractSchemaManager.php:1017
8 0.0068 963808 Doctrine\DBAL\Connection->connect( ) .../Connection.php:973
9 0.0068 963808 Doctrine\DBAL\Driver\PDOSqlite\Driver->connect( ) .../Connection.php:360

rgr (192.168.2.111)@[web] master$ php -i | grep sqlite
/etc/php/7.0/cli/conf.d/20-pdo_sqlite.ini,
/etc/php/7.0/cli/conf.d/20-sqlite3.ini,
PDO drivers => mysql, sqlite
pdo_sqlite
sqlite3
sqlite3.extension_dir => no value => no value

Reply
Cat in space

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

This tutorial uses a deprecated micro-framework called Silex. The fundamentals of REST are still ? valid, but the code we use can't be used in a real application.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "silex/silex": "~1.0", // v1.3.2
        "symfony/twig-bridge": "~2.1", // v2.7.3
        "symfony/security": "~2.4", // v2.7.3
        "doctrine/dbal": "^2.5.4", // v2.5.4
        "monolog/monolog": "~1.7.0", // 1.7.0
        "symfony/validator": "~2.4", // v2.7.3
        "symfony/expression-language": "~2.4" // v2.7.3
    },
    "require-dev": {
        "behat/mink": "~1.5", // v1.5.0
        "behat/mink-goutte-driver": "~1.0.9", // v1.0.9
        "behat/mink-selenium2-driver": "~1.1.1", // v1.1.1
        "behat/behat": "~2.5", // v2.5.5
        "behat/mink-extension": "~1.2.0", // v1.2.0
        "phpunit/phpunit": "~5.7.0", // 5.7.27
        "guzzle/guzzle": "~3.7" // v3.9.3
    }
}
userVoice