Symfony - rlip/java GitHub Wiki
dd($tracks);
dump($tracks);
// in twing:
{{ dump(tracks) }}
{{ dump() }}
//lista tras
symfony console debug:router
symfony console router:match /api/songs/11 --method=POST
// lista serwisów
symfony console debug:autowiring
// funkcje twig
symfony console debug:twig
// nazwy parametrów konfiguracyjnych w yml
php bin/console debug:config twig
// przykładowa konfiguracja
php bin/console config:dump twig
// maker bundle
composer require --dev symfony/maker-bundle
php bin/console list make
php bin/console make:controller --help
// konsola
composer require --dev symfony/profiler-pack
//taki helper do parametrów
composer require sensio/framework-extra-bundle
Zawsze można wejść na domena\_profiler
żeby zobaczyć profiler
symfony new licenseserv //create project
composer require symfony/twig-pack //teplates
composer require symfony/debugger
composer require symfony/asset
composer require symfony/http-client
class VinylController extends AbstractController
{
#[Route('/api/songs/{id<\d+>}', name: 'api_songs_get_one', methods: ['GET'])]
public function getSong(int $id, LoggerInterface $logger): Response
{
$song = [
'id' => $id,
'name' => 'Waterfalls',
'url' => 'https://symfonycasts.s3.amazonaws.com/sample.mp3',
];
$logger->info('Returning API response for song {song}', [
'song' => $id,
]);
return $this->json($song);
}
----------------
#[Route('/browse/{genre}', name: 'app_browse')]
public function browse($genre = null): Response
{
$genre = $genre ? u($genre)->title() : null;
return $this->render('vinyl/browse.html.twig', [
'genre' => $genre,
]); // zamiast render można użyć serwisu Environment twig i zwrócić new Response($twig->render(...))
}
///config/settings.yml
parameters: // tu dodajemy
profiles: '/uploads/profiles/'
profiles_directory: '%kernel.project_dir%/public%profiles%' // tu użymamy profiles z linijki wyżej
//// odczyt w kontolearze:
$this->getParameter('profiles_directory'),
w config/packages/twig
też można użyć paraetru z services
:
twig:
globals:
profiles: '%profiles'
#[Route('/micro-post/add', name: 'app_micro_post_add', priority: 2)]
public function add(Request $request, MicroPostRepository $posts): Response
{
// można zadeklarować formulary inline, ale zalecane jest zrobić to w osobnym pliku
// $form = $this->createFormBuilder($post)
// ->add('title')
// ->add('text')
// ->getForm();
$form = $this->createForm(
MicroPostType::class,
new MicroPost()
);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$post = $form->getData();
$post->setCreated(new \DateTime());
$posts->save($post, true);
$this->addFlash('success', 'Your micropost has been added');
return $this->redirectToRoute('app_micro_post');
}
return $this->render(
'micro_post/add.html.twig',
[
'form' => $form
]
);
}
--------- From/MicroPostType.php
class MicroPostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('text', TextareaType::class)
->add('extraPrivacy');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => MicroPost::class,
]);
}
}
composer require encore
yarn install
yarn add bootstrap --dev
yarn add @fontsource/roboto-condensed --dev
yarn add @fortawesome/fontawesome-free --dev
// do assets/styles/app.css
@import '~bootstrap';
@import '~@fortawesome/fontawesome-free/css/all.css';
@import '~@fontsource/roboto-condensed';
#[Route('/browse/{slug}', name: 'app_browse')]
--
public function browse(HttpClientInterface $httpClient, CacheInterface $cache, string $slug = null): Response
{
$mixes = $cache->get('mixes_data', function(CacheItemInterface $cacheItem) use ($httpClient) {
$cacheItem->expiresAfter(5);
$response = $httpClient->request('GET', 'https://raw.githubusercontent.com/SymfonyCasts/vinyl-mixes/main/mixes.json');
return $response->toArray();
});
php bin/console cache:pool:clear cache.app
php bin/console cache:pool:list
composer require --dev symfony/maker-bundle
php bin/console list make
php bin/console make:controller --help
composer require symfony/orm-pack
symfony console make:entity
symfony console make:migration
symfony console make:migration:status
symfony console doctrine:migration:migrate
symfony console doctrine:migration:migrate prev
symfony console doctrine:migration:migrate status
Można zrobić funkcję która zwraca queryBuildiera. Żeby dodstać sql to qb->getQuery()->getSql()
composer require --dev orm-fixtures
symfony console doctrine:fixtures:load
$micropost1 = new MicroPost();
$micropost1->setTitle("Welcome to Poland");
$micropost1->setTest("Welcome to Poland");
$micropost1->setCreated(new \DateTime());
$manager->persist($micropost1);
$manager->flush();
composer require sensio/framework-extra-bundle
Dodaje rózne mapowiania: https://symfony.com/bundles/SensioFrameworkExtraBundle/current/annotations/converters.html
#[Route('/micro-post/{id}', name: 'app_micro_post_show')]
public function show(MicroPost $microPost): Response
{
$this->addFlash('success', 'Your micropost has been added');
{% for message in app.flashes('success') %}
<div class="rounded-md p-2 border-green-300 bg-green-50 border dark:border-green-600 dark:bg-green-700 dark:text-white mb-4">{{ message }}</div>
{% endfor %}
tailindcss.com
#Validacja
composer require symfony/validator
// twig.yaml
twig:
default_path:
form_themes:
- 'form/fields.html.twig'
// framework.yaml
framework:
form:
legacy_error_messages: false
// w entity:
use Symfony\Component\Validator\Constraints as Assert;
----------
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
{% if app.user.follows is defined and not app.user.follows.contains(userToFollow) %}
<a href="{{ path('app_follow', { id: userToFollow.id }) }}"
class="rounded-md border p-2 border-gray-300 text-gray-600 hover:bg-gray-300 dark:text-gray-300 dark:hover:bg-gray-500 dark:border-gray-600">
Follow
</a>
composer require security
symfony console make:user
symfony console make:migration
symfony console doctrine:migration:migrate
//tworzymy userProfile
symfony console make:entity
//żeby zrobić relację dajemy tym pola i tam np. oneToOne
# Własne komendy
```php
symfony console make:command
//zaleca sie dodać nazwę z jakimś przedrostkiem np. app:create-user
//edycja w Command/CreateUserCommand.php
//odpalenie:
symfony console app:create-user
//można w trakcie komendy zadawać pytania, żeby nie zapisywać np. hasła w histori
Trzeba mieć user entity, login controller, ustawić w security config:
class LoginController extends AbstractController
{
#[Route('/login', name: 'app_login')]
public function index(AuthenticationUtils $utils): Response
{
$lastUserName = $utils->getLastUsername();
$error = $utils->getLastAuthenticationError();
return $this->render('login/index.html.twig', [
'lastUsername' => $lastUserName,
'error' => $error
]);
}
#[Route('/logout', name: 'app_logout')]
public function logout()
{
// Do nothing Symfony do the logout
}
}
//// security.yml
firewalls:
main:
lazy: true
provider: app_user_provider
form_login:
login_path: app_login
check_path: app_login
logout:
path: app_logout
target: app_login
//można też tam dodać hierarhię ról:
role_hierarchy:
ROLE_ADMIN: [ROLE_EDITOR] # can do everything what ROLE_EDITOR can do
ROLE_EDITOR: [ROLE_COMMENTER] # can do everything what ROLE_COMMENTER can do
ROLE_COMMENTER: [ROLE_USER]
//////
// potem można ograniczać dostęp za pomocą annotacji, albo funkcji
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function add(Request $request, MicroPostRepository $posts): Response
{
// $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
//albo w security.yml ograniczyć an raz do całej ścieżki
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
// w twig goraniczamy tak:
{% if is_granted('IS_AUTHENTICATED_FULLY') %}
symfony console make:voter
//////
class MicroPostVoter extends Voter
{
public function __construct(private Security $security)
{
}
// jeśli funkcja `supports(..)` zwróci true to wykona się `voteOnAttribute()`
protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, [MicroPost::EDIT, MicroPost::VIEW])
&& $subject instanceof MicroPost;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
/** @var User $user */
$user = $token->getUser();
$isAuth = $user instanceof UserInterface;
if ($this->security->isGranted('ROLE_ADMIN')) { //to też można używć w innych miejscach
return true;
}
return match ($attribute) {
MicroPost::EDIT => ($isAuth && $subject->getAuthor()->getId() == $user->getId())
|| ($this->security->isGranted('ROLE_EDITOR')),
MicroPost::VIEW => true,
default => false,
};
}
}
/////////////
// później w kontrolerze można zrobić
#[Route('/micro-post/{post}/edit', name: 'app_micro_post_edit', priority: 2)]
#[IsGranted(MicroPost::EDIT, 'post')] // tu nazwa paramertu
public function edit(MicroPost $post, Request $request, MicroPostRepository $posts): Response
// można też użyć wewnątrz metody:
$this->denyAccessUnlessGranted(MicroPost::EDIT, $post);
symfony console make:registration-form
composer require symfonycasts/verify-email-bundle