DataFixture aren't saved using nelmio/alice ( sf 3.3 with flex) - php

Hello I'm using flex to work with Symfony for learning purpose. After I installed a few recipes and I want to add the nelmio/alice for generating fake data for doctrine fixtures but after I load the fixtures no data is saved into mysql. Any ideas what did i do wrong?
<?php
namespace App\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Nelmio\Alice\Loader\NativeLoader;
class LoadFixtures extends Fixture
{
/**
* Load data fixtures with the passed EntityManager
*
* #param ObjectManager $manager
*/
public function load(ObjectManager $manager)
{
$loader = new NativeLoader();
$obj = $loader->loadFile(__DIR__ . 'fixtures.yml');
}
fixtures.yml:
App\Entity\BaseUser:
user{1..10}:
email: <email()>
BaseUser entity
<?php
namespace App\Entity;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Class BaseUser
* #package App\Entity
* #ORM\Entity
* #ORM\Table()
*/
class BaseUser implements AdvancedUserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", unique=true)
*/
private $email;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
* #return BaseUser
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* #return mixed
*/
public function getEmail()
{
return $this->email;
}
/**
* #param mixed $email
* #return BaseUser
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Checks whether the user's account has expired.
*
* Internally, if this method returns false, the authentication system
* will throw an AccountExpiredException and prevent login.
*
* #return bool true if the user's account is non expired, false otherwise
*
* #see AccountExpiredException
*/
public function isAccountNonExpired()
{
// TODO: Implement isAccountNonExpired() method.
}
/**
* Checks whether the user is locked.
*
* Internally, if this method returns false, the authentication system
* will throw a LockedException and prevent login.
*
* #return bool true if the user is not locked, false otherwise
*
* #see LockedException
*/
public function isAccountNonLocked()
{
// TODO: Implement isAccountNonLocked() method.
}
/**
* Checks whether the user's credentials (password) has expired.
*
* Internally, if this method returns false, the authentication system
* will throw a CredentialsExpiredException and prevent login.
*
* #return bool true if the user's credentials are non expired, false otherwise
*
* #see CredentialsExpiredException
*/
public function isCredentialsNonExpired()
{
// TODO: Implement isCredentialsNonExpired() method.
}
/**
* Checks whether the user is enabled.
*
* Internally, if this method returns false, the authentication system
* will throw a DisabledException and prevent login.
*
* #return bool true if the user is enabled, false otherwise
*
* #see DisabledException
*/
public function isEnabled()
{
// TODO: Implement isEnabled() method.
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return (Role|string)[] The user roles
*/
public function getRoles()
{
return ['ROLE_USER'];
}
/**
* Returns the password used to authenticate the user.
*
* This should be the encoded password. On authentication, a plain-text
* password will be salted, encoded, and then compared to this value.
*
* #return string The password
*/
public function getPassword()
{
// TODO: Implement getPassword() method.
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
// TODO: Implement getSalt() method.
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername()
{
return $this->email;
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
}
bundles.php
<?php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['all' => true],
];
and in frameworky.yml i added this
nelmio_alice:
locale: 'en_US' # Default locale for the Faker Generator
seed: 6399 # Value used make sure Faker generates data consistently across
# runs, set to null to disable.
functions_blacklist: # Some Faker formatter may have the same name as PHP
- 'current' # native functions. PHP functions have the priority,
# so if you want to use a Faker formatter instead,
# blacklist this function here
loading_limit: 5 # Alice may do some recursion to resolve certain values.
# This parameter defines a limit which will stop the
# resolution once reached.
max_unique_values_retry: 150 # Maximum number of time Alice can try to
# generate a unique value before stopping and
# failing.
composer.yml
{
"type": "project",
"license": "proprietary",
"require": {
"php": "^7.0.8",
"doctrine/doctrine-fixtures-bundle": "^2.4",
"doctrine/doctrine-migrations-bundle": "^1.2",
"sensio/framework-extra-bundle": "^5.0",
"sensiolabs/security-checker": "^4.1",
"symfony/console": "^3.3",
"symfony/framework-bundle": "^3.3",
"symfony/orm-pack": "^1.0",
"symfony/security-core": "^3.3",
"symfony/yaml": "^3.3"
},
"require-dev": {
"nelmio/alice": "^3.1",
"symfony/dotenv": "^3.3",
"symfony/flex": "^1.0"
},
"config": {
"preferred-install": {
"*": "dist"
},
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd",
"security-checker security:check": "script"
},
"post-install-cmd": [
"#auto-scripts"
],
"post-update-cmd": [
"#auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*",
"symfony/twig-bundle": "<3.3",
"symfony/debug": "<3.3"
},
"extra": {
"symfony": {
"id": "01BX9RZX7RBK5CNHP741EVCXB5",
"allow-contrib": false
}
}
}

I was trying to follow the KNP Symfony video tutorial and got lost on Nelmio/Alice repo. Bogdan's answer worked for me.
You need to add Alice Data Fixtures repo.
After adding
Here's a quick guide for all of you who's also lost:
namespace AppBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DataFixtures extends Controller implements FixtureInterface
{
public function load(ObjectManager $manager)
{
//File Path/s needs to be in array
$dummyFilePath =[__DIR__.'/DataFixtures.yml'];
//get fidry loader
$loader = $this->get('fidry_alice_data_fixtures.doctrine.loader');
//execute
$loader->load($dummyFilePath);
}
}

I solved the problem by installing theofidry/alice-data-fixtures since it seems nelmio/alice 3.x doesn't work the same as the older version. ( It doesn't takes care of the database query anymore ) .
LE:
Maybe it's my fault or not but since the official release of the sf 4 i had some problems with the loading part.
Here's a fix for anyone looking into
You need a service like this to load the fixtures
App\DataFixtures\ORM\DataFixtures:
arguments: ['#fidry_alice_data_fixtures.doctrine.purger_loader']
calls:
- [load, ['#doctrine.orm.entity_manager']]
tags: [doctrine.fixture.orm]
And in the method
$files = [
__DIR__ . '/fixtures.yml',
];
$this->loader->load($files);

Related

FOSRestBundle integration with BazingaHateoasBundle but links are still missing from response

I'm trying to integrate FOSRestBundle with BazingaHateoasBundle but the links (that I expected to be automatically generated) are still missing from the response. What is wrong with my set-up?
Here are my configs:
composer.json [excerpt]:
"require": {
"php": "^7.1.3",
"friendsofsymfony/rest-bundle": "^2.5",
"jms/serializer-bundle": "^2.4",
"lexik/jwt-authentication-bundle": "^2.6",
"sensio/framework-extra-bundle": "^5.2",
"stof/doctrine-extensions-bundle": "^1.3",
"symfony/flex": "^1.1",
"symfony/framework-bundle": "4.2.*",
"willdurand/hateoas-bundle": "^1.4"
},
jms_serializer.yaml:
jms_serializer:
visitors:
xml:
format_output: '%kernel.debug%'
fos_rest.yaml:
fos_rest:
zone:
- { path: ^/api/* }
view:
view_response_listener: true
format_listener:
rules:
- { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json ] }
routing_loader:
default_format: json
body_listener:
array_normalizer: fos_rest.normalizer.camel_keys
serializer:
serialize_null: true
body_converter:
enabled: true
validate: true
And here are my classes:
PersonsController.php:
/**
* #Rest\Route("/persons")
*/
class PersonsController extends AbstractFOSRestController
{
/**
* #Rest\Get("")
* #return View
*/
public function getList()
{
$repository = $this->getDoctrine()->getRepository(Person::class);
$view = $this->view(
$repository->findAll()
);
$view->getContext()->setGroups(['default']);
return $view;
}
}
Person.php
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity(repositoryClass="App\Repository\PersonRepository")
* #UniqueEntity("slug")
* #Serializer\ExclusionPolicy("all")
* #Hateoas\Relation("self", href = "expr('/api/persons/' ~ object.getSlug())")
*/
class Person
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Serializer\Expose
* #Serializer\Groups({"default"})
*/
private $name;
/**
* #ORM\Column(type="string", length=255, unique=true)
* #Gedmo\Slug(fields={"name"})
* #Serializer\Expose
* #Serializer\Groups({"default"})
* #Serializer\XmlAttribute
*/
private $slug;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSlug()
{
return $this->slug;
}
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
}
Testing:
GET http://localhost:8000/api/groups response:
[
{
"name": "person1",
"slug": "person1"
},
{
"name": "person2",
"slug": "person2"
}
]
Expected:
[
{
"name": "person1",
"slug": "person1",
"_links": {
"self": { "href": "http://example.com/api/persons/person1" }
}
},
{
"name": "person2",
"slug": "person2",
"_links": {
"self": { "href": "http://example.com/api/persons/person2" }
}
}
]
Researched:
https://github.com/willdurand/BazingaHateoasBundle/blob/master/Resources/doc/index.md#serializing-objects - doesn't show integration with the FOS bundle. It just constructs the Response manually.
https://github.com/willdurand/Hateoas/issues/238 - suggested removing serializedGroups, but I need groups to properly hide/expose fields to be displayed
Symfony and Wildurand/Hateoas Bundle - no links on JSON reposnse - the OP just manually constructed the response object, thus did not actually use the features of FOSRestBundle
https://symfony.com/doc/master/bundles/FOSRestBundle/1-setting_up_the_bundle.html#b-enable-a-serializer - Because the JMSSerializerBundle is the only serializer that I installed, I assume that it is the one used by the FOSRestBundle to automatically serialize the data. Thus I should not manually serialize the data and construct the response, contrary to the solutions I found.
I just needed to add the exclusion property to the Relation annotation, and specify the group where it should appear.
/**
* #ORM\Entity(repositoryClass="App\Repository\PersonRepository")
* #UniqueEntity("slug")
* #Serializer\ExclusionPolicy("all")
* #Hateoas\Relation(
* "self",
* href = "expr('/api/persons/' ~ object.getSlug())",
* exclusion = #Hateoas\Exclusion(groups={"default"})
* )
*/
class Person
{ ...

How to expose a property which depends on a serialization group from API-Platform to react-admin?

I use Changing the Serialization Context Dynamically in my application to apply the admin:write group when the user is an admin. So that an user on the admin will be able to update this property.
The context builder has this configuration:
<?php
namespace App\Serializer;
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
final class AdminContextBuilder implements SerializerContextBuilderInterface
{
private $decorated;
private $authorizationChecker;
public function __construct(SerializerContextBuilderInterface $decorated, AuthorizationCheckerInterface $authorizationChecker)
{
$this->decorated = $decorated;
$this->authorizationChecker = $authorizationChecker;
}
public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array
{
$context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);
if (isset($context['groups']) && $this->authorizationChecker->isGranted('ROLE_ADMIN') && false === $normalization) {
$context['groups'][] = 'admin:write';
}
if (isset($context['groups']) && $this->authorizationChecker->isGranted('ROLE_ADMIN') && true === $normalization) {
$context['groups'][] = 'admin:read';
}
return $context;
}
}
I want to show this property to the admin:
abstract class User implements UserInterface
{
/**
* #ORM\Column(name="account_status", type="string", length=8)
* #Groups({"read", "admin:write"})
*/
protected $accountStatus;
}
The data is returned successfully and I can see the string on table view or item view in the admin.
But the documentation generated by API-Platform on …/api/docs.jsonld does not expose this property: the property is not writable:
{
"#type": "hydra:SupportedProperty",
"hydra:property": {
"#id": "#User/accountStatus",
"#type": "rdf:Property",
"rdfs:label": "accountStatus",
"domain": "#User",
"range": "xmls:string"
},
"hydra:title": "accountStatus",
"hydra:required": false,
"hydra:readable": true,
"hydra:writable": false
},
I think that it prevents showing the field in the administration.
How can I add this property to the documentation and ultimately to react-admin?
I tried any configuration I could think of:
abstract class User implements UserInterface
{
/**
* #ORM\Column(name="account_status", type="string", length=8)
* #Groups({"read", "admin:write"})
* #ApiProperty(writable=true)
*/
protected $accountStatus;
}
For me the docs are shown as expected when I do this entirely with annotations.
/**
* "admin_edit"={
* "method"="PUT", "path"="/api/users/{id}",
* "normalization_context"={"groups"={"admin:write"}},
* "access_control"="is_granted('ROLE_ADMIN')"
* }
*/
Essentially, you are adding a new route for the admin, but it's simpler than using the serialisation mechanism.

Upgrade to Laravel 5.6 from 5.5 [duplicate]

I am trying to upgrade my Laravel 5.5 to 5.6. I have followed the instructions from the laravel website, yet I got this error:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- The requested package laravel/framework 5.6.* is satisfiable by laravel/framework[5.6.x-dev] but these conflict with your requirements or minimum-stability.
So, I changed my composer.json file and added 2 lines: **"minimum-stability": "dev", "prefer-stable": true,** based on the first answer on this laracast discussion.
Everything seemed to be working just fine until I got another error:
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 6 updates, 0 removals
- Updating sebastian/diff (2.0.1 => 3.0.0): Downloading (100%)
- Updating phpunit/phpunit-mock-objects (5.0.6 => 6.0.0): Downloading (100%) - Updating phpunit/php-timer (1.0.9 => 2.0.0): Downloading (100%)
- Updating phpunit/php-token-stream (2.0.2 => 3.0.0): Downloading (100%) - Updating phpunit/php-code-coverage (5.3.0 => 6.0.1): Downloading (100%) - Updating phpunit/phpunit (6.5.6 => 7.0.0): Downloading (100%)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> #php artisan package:discover
In trustedproxy.php line 66:
Undefined class constant 'HEADER_CLIENT_IP'
Script #php artisan package:discover handling the post-autoload-dump event returned with error code 1
The problem on line 66 is Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR',.
I have searched other posts on stackoverflow but still no luck. The last thing I tried was composer selfupdate and composer global update which was mentioned on the post composer dump-autoload not recognized command
Also, I cannot remove "minimum-stability": "dev","prefer-stable": true because if I do, then I will get the following error:
- Installation request for laravel/framework 5.6.* -> satisfiable by laravel/framework[5.6.x-dev].
- Removal request for laravel/framework == 5.6.9999999.9999999-dev
I have attached my composer.json file and trustedproxy.php respectively. Any help will be highly appreciated.
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"minimum-stability": "dev",
"prefer-stable": true,
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.1.3",
"fideloper/proxy": "~3.3",
"laravel/framework": "5.6.*",
"laravel/tinker": "~1.0"
},
"require-dev": {
"filp/whoops": "~2.0",
"fzaninotto/faker": "~1.4",
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~7.0",
"symfony/thanks": "^1.0"
},
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"dont-discover": [
]
}
},
"scripts": {
"post-root-package-install": [
"#php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"#php artisan key:generate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"#php artisan package:discover"
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
}
}
trustedproxy.php (error in line 66--> Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR',)
<?php
return [
/*
* Set trusted proxy IP addresses.
*
* Both IPv4 and IPv6 addresses are
* supported, along with CIDR notation.
*
* The "*" character is syntactic sugar
* within TrustedProxy to trust any proxy
* that connects directly to your server,
* a requirement when you cannot know the address
* of your proxy (e.g. if using Rackspace balancers).
*
* The "**" character is syntactic sugar within
* TrustedProxy to trust not just any proxy that
* connects directly to your server, but also
* proxies that connect to those proxies, and all
* the way back until you reach the original source
* IP. It will mean that $request->getClientIp()
* always gets the originating client IP, no matter
* how many proxies that client's request has
* subsequently passed through.
*/
'proxies' => [
'192.168.1.10',
],
/*
* Or, to trust all proxies that connect
* directly to your server, uncomment this:
*/
# 'proxies' => '*',
/*
* Or, to trust ALL proxies, including those that
* are in a chain of forwarding, uncomment this:
*/
# 'proxies' => '**',
/*
* Default Header Names
*
* Change these if the proxy does
* not send the default header names.
*
* Note that headers such as X-Forwarded-For
* are transformed to HTTP_X_FORWARDED_FOR format.
*
* The following are Symfony defaults, found in
* \Symfony\Component\HttpFoundation\Request::$trustedHeaders
*
* You may optionally set headers to 'null' here if you'd like
* for them to be considered untrusted instead. Ex:
*
* Illuminate\Http\Request::HEADER_CLIENT_HOST => null,
*
* WARNING: If you're using AWS Elastic Load Balancing or Heroku,
* the FORWARDED and X_FORWARDED_HOST headers should be set to null
* as they are currently unsupported there.
*/
'headers' => [
(defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED',
Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR',
Illuminate\Http\Request::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST',
Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT',
]
];
Illuminate\Http\Request file:
<?php
namespace Illuminate\Http;
use Closure;
use ArrayAccess;
use RuntimeException;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Contracts\Support\Arrayable;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
class Request extends SymfonyRequest implements Arrayable, ArrayAccess
{
use Concerns\InteractsWithContentTypes,
Concerns\InteractsWithFlashData,
Concerns\InteractsWithInput,
Macroable;
/**
* The decoded JSON content for the request.
*
* #var \Symfony\Component\HttpFoundation\ParameterBag|null
*/
protected $json;
/**
* All of the converted files for the request.
*
* #var array
*/
protected $convertedFiles;
/**
* The user resolver callback.
*
* #var \Closure
*/
protected $userResolver;
/**
* The route resolver callback.
*
* #var \Closure
*/
protected $routeResolver;
/**
* Create a new Illuminate HTTP request from server variables.
*
* #return static
*/
public static function capture()
{
static::enableHttpMethodParameterOverride();
return static::createFromBase(SymfonyRequest::createFromGlobals());
}
/**
* Return the Request instance.
*
* #return $this
*/
public function instance()
{
return $this;
}
/**
* Get the request method.
*
* #return string
*/
public function method()
{
return $this->getMethod();
}
/**
* Get the root URL for the application.
*
* #return string
*/
public function root()
{
return rtrim($this->getSchemeAndHttpHost().$this->getBaseUrl(), '/');
}
/**
* Get the URL (no query string) for the request.
*
* #return string
*/
public function url()
{
return rtrim(preg_replace('/\?.*/', '', $this->getUri()), '/');
}
/**
* Get the full URL for the request.
*
* #return string
*/
public function fullUrl()
{
$query = $this->getQueryString();
$question = $this->getBaseUrl().$this->getPathInfo() == '/' ? '/?' : '?';
return $query ? $this->url().$question.$query : $this->url();
}
/**
* Get the full URL for the request with the added query string parameters.
*
* #param array $query
* #return string
*/
public function fullUrlWithQuery(array $query)
{
$question = $this->getBaseUrl().$this->getPathInfo() == '/' ? '/?' : '?';
return count($this->query()) > 0
? $this->url().$question.http_build_query(array_merge($this->query(), $query))
: $this->fullUrl().$question.http_build_query($query);
}
/**
* Get the current path info for the request.
*
* #return string
*/
public function path()
{
$pattern = trim($this->getPathInfo(), '/');
return $pattern == '' ? '/' : $pattern;
}
/**
* Get the current decoded path info for the request.
*
* #return string
*/
public function decodedPath()
{
return rawurldecode($this->path());
}
/**
* Get a segment from the URI (1 based index).
*
* #param int $index
* #param string|null $default
* #return string|null
*/
public function segment($index, $default = null)
{
return Arr::get($this->segments(), $index - 1, $default);
}
/**
* Get all of the segments for the request path.
*
* #return array
*/
public function segments()
{
$segments = explode('/', $this->decodedPath());
return array_values(array_filter($segments, function ($value) {
return $value !== '';
}));
}
/**
* Determine if the current request URI matches a pattern.
*
* #param dynamic $patterns
* #return bool
*/
public function is(...$patterns)
{
foreach ($patterns as $pattern) {
if (Str::is($pattern, $this->decodedPath())) {
return true;
}
}
return false;
}
/**
* Determine if the route name matches a given pattern.
*
* #param dynamic $patterns
* #return bool
*/
public function routeIs(...$patterns)
{
return $this->route() && $this->route()->named(...$patterns);
}
/**
* Determine if the current request URL and query string matches a pattern.
*
* #param dynamic $patterns
* #return bool
*/
public function fullUrlIs(...$patterns)
{
$url = $this->fullUrl();
foreach ($patterns as $pattern) {
if (Str::is($pattern, $url)) {
return true;
}
}
return false;
}
/**
* Determine if the request is the result of an AJAX call.
*
* #return bool
*/
public function ajax()
{
return $this->isXmlHttpRequest();
}
/**
* Determine if the request is the result of an PJAX call.
*
* #return bool
*/
public function pjax()
{
return $this->headers->get('X-PJAX') == true;
}
/**
* Determine if the request is over HTTPS.
*
* #return bool
*/
public function secure()
{
return $this->isSecure();
}
/**
* Get the client IP address.
*
* #return string
*/
public function ip()
{
return $this->getClientIp();
}
/**
* Get the client IP addresses.
*
* #return array
*/
public function ips()
{
return $this->getClientIps();
}
/**
* Get the client user agent.
*
* #return string
*/
public function userAgent()
{
return $this->headers->get('User-Agent');
}
/**
* Merge new input into the current request's input array.
*
* #param array $input
* #return \Illuminate\Http\Request
*/
public function merge(array $input)
{
$this->getInputSource()->add($input);
return $this;
}
/**
* Replace the input for the current request.
*
* #param array $input
* #return \Illuminate\Http\Request
*/
public function replace(array $input)
{
$this->getInputSource()->replace($input);
return $this;
}
/**
* Get the JSON payload for the request.
*
* #param string $key
* #param mixed $default
* #return \Symfony\Component\HttpFoundation\ParameterBag|mixed
*/
public function json($key = null, $default = null)
{
if (! isset($this->json)) {
$this->json = new ParameterBag((array) json_decode($this->getContent(), true));
}
if (is_null($key)) {
return $this->json;
}
return data_get($this->json->all(), $key, $default);
}
/**
* Get the input source for the request.
*
* #return \Symfony\Component\HttpFoundation\ParameterBag
*/
protected function getInputSource()
{
if ($this->isJson()) {
return $this->json();
}
return $this->getRealMethod() == 'GET' ? $this->query : $this->request;
}
/**
* Create an Illuminate request from a Symfony instance.
*
* #param \Symfony\Component\HttpFoundation\Request $request
* #return \Illuminate\Http\Request
*/
public static function createFromBase(SymfonyRequest $request)
{
if ($request instanceof static) {
return $request;
}
$content = $request->content;
$request = (new static)->duplicate(
$request->query->all(), $request->request->all(), $request->attributes->all(),
$request->cookies->all(), $request->files->all(), $request->server->all()
);
$request->content = $content;
$request->request = $request->getInputSource();
return $request;
}
/**
* {#inheritdoc}
*/
public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
{
return parent::duplicate($query, $request, $attributes, $cookies, $this->filterFiles($files), $server);
}
/**
* Filter the given array of files, removing any empty values.
*
* #param mixed $files
* #return mixed
*/
protected function filterFiles($files)
{
if (! $files) {
return;
}
foreach ($files as $key => $file) {
if (is_array($file)) {
$files[$key] = $this->filterFiles($files[$key]);
}
if (empty($files[$key])) {
unset($files[$key]);
}
}
return $files;
}
/**
* Get the session associated with the request.
*
* #return \Illuminate\Session\Store
*
* #throws \RuntimeException
*/
public function session()
{
if (! $this->hasSession()) {
throw new RuntimeException('Session store not set on request.');
}
return $this->session;
}
/**
* Get the session associated with the request.
*
* #return \Illuminate\Session\Store|null
*/
public function getSession()
{
return $this->session;
}
/**
* Set the session instance on the request.
*
* #param \Illuminate\Contracts\Session\Session $session
* #return void
*/
public function setLaravelSession($session)
{
$this->session = $session;
}
/**
* Get the user making the request.
*
* #param string|null $guard
* #return mixed
*/
public function user($guard = null)
{
return call_user_func($this->getUserResolver(), $guard);
}
/**
* Get the route handling the request.
*
* #param string|null $param
*
* #return \Illuminate\Routing\Route|object|string
*/
public function route($param = null)
{
$route = call_user_func($this->getRouteResolver());
if (is_null($route) || is_null($param)) {
return $route;
}
return $route->parameter($param);
}
/**
* Get a unique fingerprint for the request / route / IP address.
*
* #return string
*
* #throws \RuntimeException
*/
public function fingerprint()
{
if (! $route = $this->route()) {
throw new RuntimeException('Unable to generate fingerprint. Route unavailable.');
}
return sha1(implode('|', array_merge(
$route->methods(), [$route->getDomain(), $route->uri(), $this->ip()]
)));
}
/**
* Set the JSON payload for the request.
*
* #param \Symfony\Component\HttpFoundation\ParameterBag $json
* #return $this
*/
public function setJson($json)
{
$this->json = $json;
return $this;
}
/**
* Get the user resolver callback.
*
* #return \Closure
*/
public function getUserResolver()
{
return $this->userResolver ?: function () {
//
};
}
/**
* Set the user resolver callback.
*
* #param \Closure $callback
* #return $this
*/
public function setUserResolver(Closure $callback)
{
$this->userResolver = $callback;
return $this;
}
/**
* Get the route resolver callback.
*
* #return \Closure
*/
public function getRouteResolver()
{
return $this->routeResolver ?: function () {
//
};
}
/**
* Set the route resolver callback.
*
* #param \Closure $callback
* #return $this
*/
public function setRouteResolver(Closure $callback)
{
$this->routeResolver = $callback;
return $this;
}
/**
* Get all of the input and files for the request.
*
* #return array
*/
public function toArray()
{
return $this->all();
}
/**
* Determine if the given offset exists.
*
* #param string $offset
* #return bool
*/
public function offsetExists($offset)
{
return array_key_exists(
$offset, $this->all() + $this->route()->parameters()
);
}
/**
* Get the value at the given offset.
*
* #param string $offset
* #return mixed
*/
public function offsetGet($offset)
{
return $this->__get($offset);
}
/**
* Set the value at the given offset.
*
* #param string $offset
* #param mixed $value
* #return void
*/
public function offsetSet($offset, $value)
{
$this->getInputSource()->set($offset, $value);
}
/**
* Remove the value at the given offset.
*
* #param string $offset
* #return void
*/
public function offsetUnset($offset)
{
$this->getInputSource()->remove($offset);
}
/**
* Check if an input element is set on the request.
*
* #param string $key
* #return bool
*/
public function __isset($key)
{
return ! is_null($this->__get($key));
}
/**
* Get an input element from the request.
*
* #param string $key
* #return mixed
*/
public function __get($key)
{
if (array_key_exists($key, $this->all())) {
return data_get($this->all(), $key);
}
return $this->route($key);
}
}
Thanks
I did this and it works perfectly.
1. composer.json:
From:
"require": {
"php": ">=7.0.0",
"fideloper/proxy": "~3.3",
"laravel/framework": "5.5.*",
"laravel/tinker": "~1.0"
},
To:
"require": {
"php": ">=7.1.3",
"fideloper/proxy": "~4.0",
"laravel/framework": "5.6.*",
"laravel/tinker": "~1.0"
},
2. Replace app\Http\Middleware\TrustedProxies.php file with contents below:
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* #var array
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* #var string
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
3. composer update
Laravel's Request object extends Symfony's Request object. Laravel 5.5 depends on Symfony 3, which has that constant. Laravel 5.6 depends on Symfony 4, which does not have that constant.
Based on your trusted proxies configuration, it looks like you're using the trusted proxies package "outside" of Laravel. Laravel brought the trusted proxies package inside the framework in 5.5, and created a dedicated \App\Http\Middleware\TrustProxies middleware for you to use.
I would suggest moving to use the middleware and configuring it as described in the Laravel documentation. This will help prevent this type of compatibility issue in the future.
To make the switch:
In app/Http/Kernel.php, if \Fideloper\Proxy\TrustProxies::class is in your $middleware array, remove it. If \App\Http\Middleware\TrustProxies::class is not in your $middleware array, add it.
Open your app/Http/Middleware/TrustProxies.php file and update it with your proxies.
Delete your config/trustedproxy.php file.
Remove Fideloper\Proxy\TrustedProxyServiceProvider::class from your providers array in config/app.php.
Update your composer.json file to use "fideloper/proxy": "~4.0". Run composer update fideloper/proxy to update the package.
I have updated from 5.5 to 5.6
composer.json
"minimum-stability":"dev",
"prefer-stable": true,
This will install latest Laravel packages, then there will be issue with TrustedProxies.
Install the latest proxy version for Laravel 5.6.
Please use tag 4.0+ for Laravel 5.6:
composer require fideloper/proxy:~4.0
More details
First install Laravel 5.6 i faced this error as well.
Just follow the few steps below will fix it:
Make sure your file composer.json requirement has:
"require": {
"php": "^7.1.3",
"fideloper/proxy": "^4.0",
},
Then try composer update to make sure your composer is up-to-date
Finally run: composer require fideloper/proxy:~4.0
Done!
To anyone who tried upgrading directly from laravel 5.5 to 5.7, and got this problem too, remove the trustedproxy.php file from app->config->trustedproxy.php.
Hopes that helps someone.
Just need to Change fideloper/proxy in composer.json file:-
Your composer.json file now:-
"fideloper/proxy": "~3.3",
Change it to ^4.0 somthing like this:-
"fideloper/proxy": "^4.0",
After that you need to run update composer that's it.
composer update
Your problem comes from your use of the library TrustedProxy.
It uses Symfony's HEADER_CLIENT_IP constant which was deprecated with Symfony 3.3 and completely removed in Symfony 4.0.
Since Laravel 5.6 has updated to use Symfony 4 components, this will no longer work.
The way to solve it is to do what patricus suggested and use Laravel's TrustProxies middleware.
I did the following things and got my project to run on Laravel 5.6-dev:
Followed what patricus
suggested
Changed fideloper/proxy to "~4.0", and added "minimum-stability":
"dev", "prefer-stable": true at the end of my composer.json file.
Replace app\Http\Middleware\TrustedProxies.php by:
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
protected $proxies;
protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
Replace config\trustedproxy.php by:
<?php
return [
'proxies' => null,
'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
];
None of the suggestions here worked for me for some reason. I am using quickadmin panel and various dependencies which might have something to do with it.
What finally worked was removing laravel/dusk, then updating to "fideloper/proxy": "~4.0", on it's own. Then updating laravel/framework to 5.6, then reinstalling dusk.
I did not need:
"minimum-stability":"dev",
"prefer-stable": true,
Maybe that was fixed with recent updates.
Faced the same issue and got a number of guidelines to resolve this. Unfortunately none of those worked or me. Actually there is no additional step or tasks needed to be addressed to fix this issue.
Just follow the official upgrade guide from https://laravel.com/docs/5.6/upgrade and along with that remove the trustedproxy config file located at config/trustedproxy.php
Had the same issue in Laravel 5.7. You may add TELESCOPE_ENABLED=false in your .env or .env.dusk.local :Source

How to inject a repository on another repository class in Laravel 5 (5.2)

Let's say I have two repositories (UserRepository, RoleRepository) that implements a contract (UserRepositoryInterface, RoleRepositoryInterface).
What I wanted to do is to inject RoleRepository into UserRepository's constructor method and I've been trying to make this work but I'm getting this error:
Target [App\Contracts\UserRepositoryInterface] is not instantiable while building [App\Http\Controllers\UserController].
Here's what I got so far,
composer.json
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.2.*",
"tymon/jwt-auth": "^0.5.9",
"zizaco/entrust": "dev-laravel-5"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
"mockery/mockery": "^0.9.4",
"phpunit/phpunit": "~4.0",
"symfony/css-selector": "2.8.*|3.0.*",
"symfony/dom-crawler": "2.8.*|3.0.*"
},
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"App\\Models\\": "app/Models/",
"App\\Contracts\\": "app/Contracts/",
"App\\Repositories\\": "app/Repositories/"
}
},
"autoload-dev": {
"classmap": [
"tests/TestCase.php",
"tests/MockData.php"
]
}
config/app.php
'providers' => [
/*
* Laravel Framework Service Providers...
*/
...
/**
* Third-party Service Providers
*/
...
/*
* Application Service Providers...
*/
...
/**
* Custom Service Providers...
*/
App\Providers\RepositoryServiceProvider::class,
app/Providers/RepositoryServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$models = [
'Role',
'User',
];
foreach ($models as $model) {
$this->app->bind(
"App\Contracts\\{$model}Interface",
"App\Repositories\\{$model}Repository"
);
}
}
}
app/Controllers/UserController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Contracts\UserRepositoryInterface as UserRepository;
class UserController extends Controller
{
/**
* #var UserRepository
*/
private $repo;
/**
* Class constructor
*
* #param UserRepository $repo
*/
public function __construct(
UserRepository $repo
) {
$this->repo = $repo;
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
*
* #return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
$data = $request->all();
$user = $this->repo->store($data);
return response()->json($user, 201);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
*
* #return \Illuminate\Http\JsonResponse
*/
public function update(Request $request, $id)
{
$data = $request->all();
$user = $this->repo->store($data, $id);
return response()->json($data, 200);
}
app/Contracts/RoleRepositoryInterface.php
<?php
namespace App\Contracts;
interface RoleRepositoryInterface
{
/**
* Attach role to user
*
* #param static $user
* #param string $roleName
*
* #return static
*/
public function role($user, $roleName);
}
app/Contracts/UserRepositoryInterface.php
<?php
namespace App\Contracts;
interface UserRepositoryInterface
{
/**
* Create new or update an existing user
*
* #param array $data
* #param int $id
*
* #return bool|int|array
*/
public function store(array $data, $id = null);
}
app/Repositories/RoleRepository.php
<?php
namespace App\Repositories;
use InvalidArgumentException;
use App\Contracts\RoleRepositoryInterface;
use App\Models\Role;
class RoleRepository extends Role implements RoleRepositoryInterface
{
/**
* Attach a role to user
*
* #param static $user
* #param string $roleName
*
* #return static
*
* #throws \InvalidArgumentException
*/
public function attachRole($user, $roleName)
{
if (!$user instanceof App\Models\User::class) {
throw new InvalidArgumentException("{$user} must be an instance of App\Models\User");
}
// find role
$role = $this->where('name', $roleName)->first();
// attach role to user
$user->attachRole($role);
return $user;
}
}
app/Repositories/UserRepository.php
<?php
namespace App\Repositories;
use App\Contracts\RoleRepositoryInterface as RoleRepository;
use App\Contracts\UserRepositoryInterface;
use App\Models\User;
class UserRepository extends User implements UserRepositoryInterface
{
/**
* #var RoleRepository
*/
private $roleRepo;
/**
* Class constructor
*
* #param RoleRepository $roleRepo
*/
public function __construct(RoleRepository $roleRepo)
{
$this->roleRepo = $roleRepo;
}
/**
* Create new or update an existing user
*
* #param array $data
* #param int $id
*
* #return bool|int|static
*/
public function store(array $data, $id = null)
{
if (is_null($id)) {
$user = $this->create($data);
$userWithRole = $this->roleRepo->attachRole($user, $data['role']);
return $user;
} else {
return $this->where('id', $id)
->update($data);
}
}
}
Any answers is greatly appreciated...
I think you have an error in your code, specifically in the RepositoryServiceProvider. It should be:
foreach ($models as $model) {
$this->app->bind(
"App\Contracts\\{$model}RepositoryInterface",
"App\Repositories\\{$model}Repository"
);
}
Note: the error is in the concatenation, you got "App\Contracts\\{$model}Interface", but it should be "App\Contracts\\{$model}RepositoryInterface"

ReflectionException with Symfony and Sonata, "Class does not exist"

I'm experiencing a problem trying to fit my Entities in the Sonata Admin Bundle. I have something like 5 entities, which are finely listed and viewed in the bundle, but I cannot edit or create a new entry.
When I try to edit or create, I get a ReflectionException error:
Class does not exist
I tried in order to solve that problem to operate on namespaces (moving controller in the same namespace that Admin files, or so) or to tweak the Admin Controller in order to tell it about my entities ("->add('individual', 'entity', array('class' => 'Platform\ProjectBundle\Entity\Individual'))" instead of ->add('individual')).
My entity is named Biosample. Here is the Entity file:
<?php
namespace Platform\ProjectBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="biosample")
*/
class Biosample
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Individual", inversedBy="samples")
* #ORM\JoinColumn(name="individual_id", referencedColumnName="id")
*/
protected $individual;
/**
* #ORM\Column(type="string", length=100)
*/
protected $organ;
/**
* #ORM\Column(type="string", length=100)
*/
protected $sample_name;
/**
* #ORM\Column(type="string", nullable=true)
*/
protected $organ_location;
/**
* #ORM\Column(type="string")
*/
protected $tissue_type;
/**
* #ORM\Column(type="string", nullable=true)
*/
protected $tissue_subtype;
/**
* #ORM\Column(type="datetimetz")
*/
protected $sampling_date;
/**
* #ORM\Column(type="decimal", scale=3, nullable=true)
*/
protected $cellularity;
/**
* #ORM\Column(type="string", nullable=true)
*/
protected $conservation;
/**
* #ORM\Column(type="text", nullable=true)
*/
protected $description;
/**
* #ORM\ManyToMany(targetEntity="Project", mappedBy="biosamples")
*/
protected $projects;
public function __construct()
{
$this->projects = new ArrayCollection();
}
public function __toString()
{
return $this->sample_name;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set organ
*
* #param string $organ
* #return Biosample
*/
public function setOrgan($organ)
{
$this->organ = $organ;
return $this;
}
/**
* Get organ
*
* #return string
*/
public function getOrgan()
{
return $this->organ;
}
/**
* Set organ_location
*
* #param string $organLocation
* #return Biosample
*/
public function setOrganLocation($organLocation)
{
$this->organ_location = $organLocation;
return $this;
}
/**
* Get organ_location
*
* #return string
*/
public function getOrganLocation()
{
return $this->organ_location;
}
/**
* Set tissue_type
*
* #param string $tissueType
* #return Biosample
*/
public function setTissueType($tissueType)
{
$this->tissue_type = $tissueType;
return $this;
}
/**
* Get tissue_type
*
* #return string
*/
public function getTissueType()
{
return $this->tissue_type;
}
/**
* Set tissue_subtype
*
* #param string $tissueSubtype
* #return Biosample
*/
public function setTissueSubtype($tissueSubtype)
{
$this->tissue_subtype = $tissueSubtype;
return $this;
}
/**
* Get tissue_subtype
*
* #return string
*/
public function getTissueSubtype()
{
return $this->tissue_subtype;
}
/**
* Set sampling_date
*
* #param \DateTime $samplingDate
* #return Biosample
*/
public function setSamplingDate($samplingDate)
{
$this->sampling_date = $samplingDate;
return $this;
}
/**
* Get sampling_date
*
* #return \DateTime
*/
public function getSamplingDate()
{
return $this->sampling_date;
}
/**
* Set cellularity
*
* #param string $cellularity
* #return Biosample
*/
public function setCellularity($cellularity)
{
$this->cellularity = $cellularity;
return $this;
}
/**
* Get cellularity
*
* #return string
*/
public function getCellularity()
{
return $this->cellularity;
}
/**
* Set conservation
*
* #param string $conservation
* #return Biosample
*/
public function setConservation($conservation)
{
$this->conservation = $conservation;
return $this;
}
/**
* Get conservation
*
* #return string
*/
public function getConservation()
{
return $this->conservation;
}
/**
* Set description
*
* #param string $description
* #return Biosample
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set individual
*
* #param \Platform\ProjectBundle\Entity\Individual $individual
* #return Biosample
*/
public function setIndividual(\Platform\ProjectBundle\Entity\Individual $individual = null)
{
$this->individual = $individual;
return $this;
}
/**
* Get individual
*
* #return \Platform\ProjectBundle\Entity\Individual
*/
public function getIndividual()
{
return $this->individual;
}
/**
* Add projects
*
* #param \Platform\ProjectBundle\Entity\Project $projects
* #return Biosample
*/
public function addProject(\Platform\ProjectBundle\Entity\Project $projects)
{
$this->projects[] = $projects;
return $this;
}
/**
* Remove projects
*
* #param \Platform\ProjectBundle\Entity\Project $projects
*/
public function removeProject(\Platform\ProjectBundle\Entity\Project $projects)
{
$this->projects->removeElement($projects);
}
/**
* Get projects
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProjects()
{
return $this->projects;
}
/**
* Set sample_name
*
* #param string $sampleName
* #return Biosample
*/
public function setSampleName($sampleName)
{
$this->sample_name = $sampleName;
return $this;
}
/**
* Get sample_name
*
* #return string
*/
public function getSampleName()
{
return $this->sample_name;
}
}`
Here is my BiosampleAdmin.php:
<?php
namespace Platform\ProjectBundle\Controller\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Knp\Menu\ItemInterface as MenuItemInterface;
use Platform\ProjectBundle\Entity\Biosample;
class BiosampleAdmin extends Admin
{
/**
* #param \Sonata\AdminBundle\Show\ShowMapper $showMapper
*
* #return void
*/
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->add('id')
->add('sample_name')
->add('individual', 'entity', array('class' => 'Platform\ProjectBundle\Entity\Individual'))
->add('organ')
->add('organ_location')
->add('tissue_type')
->add('tissue_subtype')
->add('sampling_date')
->add('cellularity')
->add('conservation')
->add('projects', 'entity', array('class' => 'Platform\ProjectBundle\Entity\Project'))
->add('description')
;
}
/**
* #param \Sonata\AdminBundle\Form\FormMapper $formMapper
*
* #return void
*/
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('General')
->add('sample_name')
->add('individual')
->add('organ')
->add('organ_location')
->add('tissue_type')
->add('tissue_subtype')
->end()
->with('Miscelaneous')
->add('sampling_date')
->add('cellularity')
->add('conservation')
->end()
->with('Projects')
->add('projects')
->end()
->with('Description')
->add('description', 'sonata_type_model', array('multiple' => false))
->end()
;
}
/**
* #param \Sonata\AdminBundle\Datagrid\ListMapper $listMapper
*
* #return void
*/
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->add('sample_name')
->add('individual')
->add('projects')
->add('organ')
->add('tissue')
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
'delete' => array(),
)
))
;
}
/**
* #param \Sonata\AdminBundle\Datagrid\DatagridMapper $datagridMapper
*
* #return void
*/
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('sample_name')
->add('individual')
->add('projects')
;
}
}
Here is the admin controller:
<?php
namespace Platform\ProjectBundle\Controller;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Platform\ProjectBundle\Entity\Biosample;
class BiosampleAdminController extends Controller
{
}
And if you need it, here my composer.json:
{
"name": "symfony/framework-standard-edition",
"license": "MIT",
"type": "project",
"description": "The \"Symfony Standard Edition\" distribution",
"autoload": {
"psr-0": { "": "src/", "SymfonyStandard": "app/" }
},
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.6.*",
"doctrine/orm": "~2.2,>=2.2.3,<2.5",
"doctrine/dbal": "<2.5",
"doctrine/doctrine-bundle": "~1.2",
"twig/extensions": "~1.0",
"symfony/assetic-bundle": "~2.3",
"symfony/swiftmailer-bundle": "~2.3",
"symfony/monolog-bundle": "~2.4",
"sensio/distribution-bundle": "~3.0,>=3.0.12",
"sensio/framework-extra-bundle": "~3.0,>=3.0.2",
"jms/security-extra-bundle": "~1.2",
"ircmaxell/password-compat": "~1.0.3",
"stof/doctrine-extensions-bundle": "~1.1#dev",
"friendsofsymfony/user-bundle": "~1.3",
"incenteev/composer-parameter-handler": "~2.0",
"nervo/yuicompressor": "2.4.8",
"sonata-project/admin-bundle": "~2.3",
"sonata-project/doctrine-orm-admin-bundle": "~2.3",
"sonata-project/easy-extends-bundle": "~2.1",
"sonata-project/user-bundle": "~2.2",
"knplabs/knp-menu-bundle": "~1.1",
"mopa/bootstrap-bundle": "~2",
"twbs/bootstrap-sass": "~3.3.0",
"knplabs/knp-paginator-bundle": "dev-master",
"knplabs/knp-menu": "~1.1",
"craue/formflow-bundle": "~2.0"
},
"require-dev": {
"sensio/generator-bundle": "~2.3"
},
"scripts": {
"post-root-package-install": [
"SymfonyStandard\\Composer::hookRootPackageInstall"
],
"post-install-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles"
],
"post-update-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::removeSymfonyStandardFiles"
]
},
"config": {
"bin-dir": "bin"
},
"extra": {
"symfony-app-dir": "app",
"symfony-web-dir": "web",
"symfony-assets-install": "relative",
"incenteev-parameters": {
"file": "app/config/parameters.yml"
},
"branch-alias": {
"dev-master": "2.6-dev"
}
}
}
Finally, here's my service declaration and my config.yml file:
Service.yml:
services:
platform.project.admin.biosample:
class: Platform\ProjectBundle\Controller\Admin\BiosampleAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: Project Manager, label: Biosample }
arguments: [null, Platform\ProjectBundle\Entity\Biosample, PlatformProjectBundle:BiosampleAdmin]
Config.yml:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
framework:
#esi: ~
translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: ~
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# Assetic Configuration
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [ ]
#java: /usr/bin/java
filters:
cssrewrite: ~
#closure:
# jar: "%kernel.root_dir%/Resources/java/compiler.jar"
#yui_css:
# jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar"
# Doctrine Configuration
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
types:
json: Sonata\Doctrine\Types\JsonType
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
fos_user:
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
firewall_name: secured
user_class: Application\Sonata\UserBundle\Entity\User
group:
group_class: Application\Sonata\UserBundle\Entity\Group
group_manager: sonata.user.orm.group_manager
service:
user_manager: sonata.user.orm.user_manager
sonata_doctrine_orm_admin:
entity_manager: ~
sonata_block:
default_contexts: [cms]
blocks:
sonata.admin.block.admin_list:
contexts: [admin]
sonata.user.block.menu: ~
sonata.user.block.account: ~
sonata.block.service.text: ~
sonata_user:
security_acl: true
manager_type: orm
mopa_bootstrap:
form: ~
And last but not least: the full stack trace.
[1] ReflectionException: Class does not exist
at n/a
in /var/www/Project/app/cache/dev/classes.php line 6756
at ReflectionClass->__construct('')
in /var/www/Project/app/cache/dev/classes.php line 6756
at Doctrine\Common\Persistence\AbstractManagerRegistry->getManagerForClass(null)
in /var/www/Project/vendor/sonata-project/doctrine-orm-admin-bundle/Model/ModelManager.php line 220
at Sonata\DoctrineORMAdminBundle\Model\ModelManager->getEntityManager(null)
in /var/www/Project/vendor/sonata-project/doctrine-orm-admin-bundle/Model/ModelManager.php line 54
at Sonata\DoctrineORMAdminBundle\Model\ModelManager->getMetadata(null)
in /var/www/Project/vendor/sonata-project/doctrine-orm-admin-bundle/Model/ModelManager.php line 317
at Sonata\DoctrineORMAdminBundle\Model\ModelManager->getIdentifierFieldNames(null)
in /var/www/Project/app/cache/dev/classes.php line 12663
at Sonata\AdminBundle\Form\ChoiceList\ModelChoiceList->__construct(object(ModelManager), null, null, null, null)
in /var/www/Project/app/cache/dev/classes.php line 13690
at Sonata\AdminBundle\Form\Type\ModelType->Sonata\AdminBundle\Form\Type\{closure}(object(OptionsResolver), object(SimpleChoiceList))
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/OptionsResolver/OptionsResolver.php line 836
at Symfony\Component\OptionsResolver\OptionsResolver->offsetGet('choice_list')
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/OptionsResolver/OptionsResolver.php line 769
at Symfony\Component\OptionsResolver\OptionsResolver->resolve(array('sonata_field_description' => object(FieldDescription), 'class' => null, 'model_manager' => object(ModelManager), 'multiple' => false, 'label_render' => false, 'label' => 'Description'))
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/Form/ResolvedFormType.php line 109
at Symfony\Component\Form\ResolvedFormType->createBuilder(object(FormFactory), 'description', array('sonata_field_description' => object(FieldDescription), 'class' => null, 'model_manager' => object(ModelManager), 'multiple' => false, 'label_render' => false, 'label' => 'Description'))
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/DataCollector/Proxy/ResolvedTypeDataCollectorProxy.php line 82
at Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeDataCollectorProxy->createBuilder(object(FormFactory), 'description', array('sonata_field_description' => object(FieldDescription), 'class' => null, 'model_manager' => object(ModelManager), 'multiple' => false, 'label_render' => false, 'label' => 'Description'))
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/Form/FormFactory.php line 87
at Symfony\Component\Form\FormFactory->createNamedBuilder('description', 'sonata_type_model', null, array('sonata_field_description' => object(FieldDescription), 'class' => null, 'model_manager' => object(ModelManager), 'multiple' => false, 'label_render' => false, 'label' => 'Description'))
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/Form/FormBuilder.php line 106
at Symfony\Component\Form\FormBuilder->create('description', 'sonata_type_model', array('sonata_field_description' => object(FieldDescription), 'class' => null, 'model_manager' => object(ModelManager), 'multiple' => false, 'label_render' => false, 'label' => 'Description'))
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/Form/FormBuilder.php line 268
at Symfony\Component\Form\FormBuilder->resolveChildren()
in /var/www/Project/vendor/symfony/symfony/src/Symfony/Component/Form/FormBuilder.php line 216
at Symfony\Component\Form\FormBuilder->getForm()
in /var/www/Project/app/cache/dev/classes.php line 9671
at Sonata\AdminBundle\Admin\Admin->buildForm()
in /var/www/Project/app/cache/dev/classes.php line 9930
at Sonata\AdminBundle\Admin\Admin->getForm()
in /var/www/Project/vendor/sonata-project/admin-bundle/Controller/CRUDController.php line 353
at Sonata\AdminBundle\Controller\CRUDController->editAction('1')
in line
at call_user_func_array(array(object(CRUDController), 'editAction'), array('1'))
in /var/www/Project/app/bootstrap.php.cache line 3022
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
in /var/www/Project/app/bootstrap.php.cache line 2984
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
in /var/www/Project/app/bootstrap.php.cache line 3133
at Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(object(Request), '1', true)
in /var/www/Project/app/bootstrap.php.cache line 2377
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
in /var/www/Project/web/app_dev.php line 28
Well, the reason for this error was a bad copy/paste from the tutorial.
In the Admin Class, the function configureFormFields contained a field "Description" badly described.
->with('Description')
->add('description', 'sonata_type_model', array('multiple' => false))
->end()
I had to replace it to:
->with('Description')
->add('description')
->end()
I discovered that automatic Admin Class skeleton generation was a function of Sonata Admin Bundle.
In order to automatically generate, execute:
php app/console sonata:admin:generate
Then enter the full path to your entity, in this example:
Platform\ProjectBundle\Entity\Biosample
The admin bundle will parse your entity and :
Generate the Admin Class file
Add an entry in your application bundle's service.yml
Generate optionnaly the CRUD controller
I guess this should be the prefered method when one is starting with sonata admin bundle.
I had the same problem, and for a reason i ignore, not in the past project where i've done exactly the same...
After an hour of search, i realize my table 'fos_user_user_group' has not been created has the mapping is not created. So my solution was simply to override the groups property of my entity User in order to define the Doctrine ORM Mapping :
/**
* The User can have many groups.
* #ORM\ManyToMany(targetEntity="Group")
* #ORM\JoinTable(name="fos_user_user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
After that, doctrine:schema:update --force and the problem was solved ;)
If you did it like me, and created first the database then via the console the yml files and from that the classes, then your annotations are useless.
Sonata is using yml and not annotations. They exist and seem to work but they just don't. To make the "Class does not exist" message go check what you yml definitions are saying. I needed to add the relationships and entity classes there.
If this is really the reason for your errors you might want to activate the annotations by deleting or moving the yml or xml templates somewhere else (..\Resources\config\doctrine).

Categories