
<?php echo 'Hello, world!';
, . , . . , 2017 . , , hello-world , , , .
→ «hello,world» .
, . "
echo 'hello, world'
", ( ?). - , , Symfony.
, , . ? «hello, world» !
2017 postgresql. , :
sudo apt-get install postgresql
postgres, psql .
sudo -u postgres psql
( - ).
CREATE ROLE helloworlduser WITH PASSWORD '12345' LOGIN;
:
CREATE DATABASE helloworld OWNER helloworlduser;
, pg_hba.conf localhost (127.0.0.1). - :
host all all 127.0.0.1/32 md5
:
psql -h localhost -U helloworlduser helloworld
. :
CREATE TABLE greetings ( id int, greeting text, primary key(id) ); INSERT INTO greetings (id, greeting) VALUES (1, 'Hello, world!');
, , .
php-
, 2017 composer .
composer create-project symfony/framework-standard-edition helloworldphp
:
host: 127.0.0.1 database_name: helloworld database_user: helloworlduser database_password: 12345
/ .
config.yml
driver: pdo_pgsql
. ( php- pdo_pgsql ?)
, ,
cd helloworldphp bin/console server:start
, 8000 .
http://localhost:8000/
- « , ».
! , , , , !
… . , 2017-. SPA (single page application).
Php- 2017 js , full stack, helloworld .
, , php--,
JavaScript
( app/Resources/view/default/index.html.twig) , :
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="root"></div> <script src="js/bundle.js"></script> </body> </html>
.. bundle.js: javascript , .
? webpack .
Webpack ( ) , javascript 2017-, typescript . typescript - js-. , webpack.
, typescript . - . — react + redux. , , bootstrap ( sass, ).
js-. nodejs npm? , npm :
npm init
( package.json) :
"dependencies": { "@types/react": "^15.0.11", "@types/react-dom": "^0.14.23", "babel-core": "^6.23.1", "babel-loader": "^6.3.2", "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.23.0", "bootstrap-sass": "^3.3.7", "css-loader": "^0.26.1", "node-sass": "^4.5.0", "react": "^15.4.2", "react-dom": "^15.4.2", "react-redux": "^5.0.2", "redux": "^3.6.0", "resolve-url-loader": "^2.0.0", "sass-loader": "^6.0.1", "style-loader": "^0.13.1", "ts-loader": "^2.0.0", "typescript": "^2.1.6", "url-loader": "^0.5.7", "webpack": "^2.2.1", "@types/node": "^7.0.5" }
npm install
:
npm install webpack -g
webpack.
, . typescript, tsconfig.json, :
tsconfig.json
{ "compilerOptions": { "module": "es6", "moduleResolution": "node", "sourceMap": false, "target": "esnext", "outDir": "web/ts", "lib": [ "dom", "scripthost", "es5", "es6", "es7" ], "jsx": "react" }, "include": [ "frontend/**/*.ts", "frontend/**/*.tsx" ] }
, typescript.
:
// frontend/components/Greetings.tsx import * as React from 'react'; export interface GreetingsProps { text: string; isReady: boolean; onMount(); } class Greetings extends React.Component<GreetingsProps, undefined> { componentDidMount() { this.props.onMount(); } render() { return ( <h1>{this.props.text}</h1> ); } } export default Greetings;
SPA Rest API. React — view-, .
redux, redux react (react-redux). , Greetings properties, (store) , ( ).
Disclaimer: redux, « ».
, , :
// frontend/components/App.tsx import * as React from 'react'; import {connect} from 'react-redux' import Greetings from './Greetings'; const mapStateToProps = (state) => { return state; } const mapDispatchToProps = (dispatch) => { return { onMount: () => { fetch("/greetings/1").then((response) => { return response.json(); }).then((json) => { dispatch({type: 'FETCH_GREETING', text: json.greeting}) }); } } } export default connect(mapStateToProps, mapDispatchToProps)(Greetings);
, redux-, .. -, , :
// bootstrap import 'bootstrap-sass/assets/stylesheets/_bootstrap.scss'; import * as React from 'react'; import * as ReactDOM from "react-dom"; import {Provider} from 'react-redux'; import App from './components/App'; import {createStore} from 'redux'; const app = (state = {isReady: false, text: ''}, action) => { switch (action.type) { case 'FETCH_GREETING': return Object.assign({}, state, {isReady: true, text: action.text}); } return state; } const store = createStore(app); ReactDOM.render( <Provider store={store}> <App/> </Provider>, document.getElementById("root") );
:
- —
{isReady: false, text: ''}
. - reducer app, FETCH_GREETING .
- store .
- ,
<div id="root"></div>
, . :
webpack.config.js
const webpack = require('webpack'); const path = require('path'); const ENVIRONMENT = process.env.NODE_ENV || 'development'; let config = { context: path.resolve(__dirname, "frontend"), entry: './index.tsx', output: { filename: 'bundle.js', path: path.resolve(__dirname, "web/js") }, resolve: { extensions: [ ".js", ".jsx", '.ts', '.tsx'] }, module: { rules: [ { test: /\.tsx?$/, use: [{ loader: 'babel-loader', query: { presets: ['es2015', 'react'] } }, { loader: 'ts-loader' }] }, { test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/, loader: 'url-loader' }, { test: /\.scss$/, use: [ { loader: "style-loader" }, { loader: "css-loader" }, { loader: "resolve-url-loader" }, { loader: "sass-loader" } ] } ] }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(ENVIRONMENT) }) ], node: { process: false } }; if (ENVIRONMENT == 'production') { config.plugins.push( new webpack.optimize.UglifyJsPlugin({ compress: { drop_console: false, warnings: false } }) ); } module.exports = config;
webpack NODE_ENV=production webpack ( bundle.js)
Pomodoro
, hello, world. 2017 , , ( Pomodoro ..). , , .
[ - ]
. /greetings/1 javascript, php- .
Doctrine
, php- . :
<?php // src/AppBundle/Entity/Greeting.php namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="greetings") */ class Greeting { /** * @ORM\Column(type="integer") * @ORM\Id */ private $id; /** * @ORM\Column(type="string", length=100) */ private $greeting; public function getId() { return $this->id; } public function getGreeting() { return $this->greeting; } }
. -.
REST
- REST API, json GET /greetings/1
( src/AppBundle/Controller/DefaultController.php) :
/** * @Route("/greetings/{id}") */ public function greetings($id) { $greeting = $this->getDoctrine()->getRepository("AppBundle:Greeting")->find($id); return new JsonResponse(['greeting' => $greeting->getGreeting()]); }
, . «Hello, world!». , , <?php echo «hello, world» ?> ( ), . , , ( , ), :)
« php, java». , , , — . php — . , , . 100500 : ( java), , linux, javascript , , http-, - . SPA.
Upd. , . :
1) SPA , , .
2) .