Using Symfony2 / doctrine2, while we use the find() function to get a specific object based on the entity selected if there are relations (like OneToMany), Doctrine return all other object.
For example :
$em = $this->get(
'doctrine.orm.entity_manager',
$request->getSession()->get('entity_manager')
);
$product = $em->getRepository('MyBundle:Product')->find($id);
The result on $product will be the Product object + other linked objects like (Store, Category, ...etc.)
How can we control doctrine to determinate which object we need to be returned.
I can use Querybuilder, but i am looking if there are any function all determinate.
Doctrine return all other object
This is not how it works, at least by default.
Doctrine uses what is called lazy loading.
From the official documentation, you have the following example:
<?php
/** #Entity */
class Article
{
/** #Id #Column(type="integer") #GeneratedValue */
private $id;
/** #Column(type="string") */
private $headline;
/** #ManyToOne(targetEntity="User") */
private $author;
/** #OneToMany(targetEntity="Comment", mappedBy="article") */
private $comments;
public function __construct {
$this->comments = new ArrayCollection();
}
public function getAuthor() { return $this->author; }
public function getComments() { return $this->comments; }
}
$article = $em->find('Article', 1);
And the following explanation:
Instead of passing you back a real Author instance and a collection of
comments Doctrine will create proxy instances for you. Only if you
access these proxies for the first time they will go through the
EntityManager and load their state from the database.
Reference: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#entity-object-graph-traversal
More information about the topic: http://www.doctrine-project.org/blog/doctrine-lazy-loading.html
You can configure extra lazy associations to avoid loading of relations in general.
/**
* #ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
*/
protected $property;
Related
I am working on import excel data in Laravel framework and using Maatwebsite/Laravel-Excel package.
Now I have followed the steps but not getting any idea after reading package documentation, so I need help to read data from the second(2nd) sheet as I have multiple sheets in my excel file.
BillingDataImport
<?php
namespace App\Imports;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
class BillingDataImport implements ToCollection
{
/**
* #param Collection $collection
*/
public function collection(Collection $collection)
{
return $collection;
}
}
BillingController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Imports\BillingDataImport;
use App\Http\Controllers\Controller;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Input;
class BillingController extends Controller
{
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$import = new BillingDataImport();
$rawData = Excel::toArray($import, $request->file('company_1'));
var_dump($rawData);
}
}
When I dump the code, I am getting data from the first(1st) sheet but I want to read second(2nd) sheet so can you please guide me as I am not too good Laravel and with this package.
You need to implement WithMultipleSheets interface in your import class. It will require you to add sheets method. You will include them like these;
public function sheets(): array
{
return [
0 => new FirstSheetImport(),
1 => new SecondSheetImport(),
];
}
Then you may select them by index. More info here
I am very new to nodejs and typescript.
I have try to provide an API via express.
I have try to return a custom object on my API who looks like that :
export class Auction {
private _currentPrice:number = 0;
private _auctionName:string;
public constructor(currentPrice: number , auctionName: string) {
this._currentPrice = currentPrice;
this._auctionName = auctionName;
}
/**
* Getter auctionName
* #return {string}
*/
public get auctionName(): string {
return this._auctionName;
}
/**
* Setter auctionName
* #param {string} value
*/
public set auctionName(value: string) {
this._auctionName = value;
}
/**
* Setter currentPrice
* #param {number } value
*/
public set currentPrice(value: number ) {
this._currentPrice = value;
}
/**
* Getter currentPrice
* #return {number }
*/
public get currentPrice(): number {
return this._currentPrice;
}
}
But what I have seen is that the answer of my API is something like :
{"_currentPrice":0,"_auctionName":"toto"}
I was expecting something like
{"currentPrice":0,"auctionName":"toto"}
Is there any way to automaticaly convert it to the format I want ?
This is happening because when the TypeScript is compiled to JavaScript, objects created by that class have public _currentPrice and _auctionName properties (because TypeScript "private" properties are only private in terms of TypeScript's type system) and they don't have their own currentPrice and auctionName properties (they inherit them from their prototype, which has them as accessor properties). JSON.stringify only includes "own" properties.
You can deal with it in a few ways:
By using simple properties for currentPrice and auctionName. You have public accessors for both get and set for both properties, so there doesn't seem to be any reason to use private properties to hold their values. Or,
By providing your own toJSON method for the class:
toJSON() {
return {currentPrice: this._currentPrice, auctionName: this._auctionName};
}
Despite the name "toJSON", this method isn't supposed to return JSON; it's supposed to return the value for the object that should be converted to JSON. So in this case, you return an object with the properties you want the returned JSON to have.
A third solution would be to use JavaScript's own private properties (they're supported in up-to-date Node.js versions) and "own" accessors for them on the objects, but I don't think TypeScript supports JavaScript's private properties yet.
An aggregate (Article) has an entity (SmsContent) with a property (enabled) that only can change if a condition on the aggregate is met.
e.g.
<?php
//Aggregate
class Article {
/** #var User */
protected $user;
/** #var SmsOutput */
protected sms;
...
public function enableSms() {
if($this->user->hasPermission('sms')) {
throw new PermissionDeniedException('sms');
}
$this->sms->enable();
retutn $this;
}
public function getSms() {
return $this->sms;
}
...
}
//Entity
class SmsOutput {
/** #var boolean */
protected enabled = false;
...
public function enable() {
$this->enable = true;
}
...
}
How should you get the SmsContent entity from the Article without being able to change the enabled property from outside the aggregate?
For example:
$article->getSms()->enable();
How is this handled in DDD?
You have multiple options, depending on the architecture.
1. Use CQRS
In CQRS the Write is separated from the Read. This means that you don't interrogate the Aggregate, ever. You don't have any getters, only command handlers. If you can't interrogate the Aggregate you can't access any nested entity either. If you need to get data you do it only from a projection/read model that are read-only by default.
2. Use a different interface for returned entities
In this case you return the entity but it is type-hinted as being a sub-set of the actual entity. In your case you could have something like this:
<?php
interface SmsOutput
{
//...
public function isEnabled(): bool;
//...
}
//Entity
class SmsOutputWritable implements SmsOutput
{
/** #var boolean */
private $enabled = false;
//...
public function enable()
{
$this->enabled = true;
}
public function isEnabled(): bool
{
return $this->enabled;
}
//...
}
//Aggregate
class Article
{
/** #var User */
private $user;
/** #var SmsOutputWritable */
private $sms;
//...
public function enableSms(): void //no return values, see CQS
{
if ($this->user->hasPermission('sms')) {
throw new PermissionDeniedException('sms');
}
$this->sms->enable();
}
public function getSms(): SmsOutput
{
return $this->sms;
}
//...
}
Although the caller gets a SmsOutputWritable it does not know about this.
P.S. Anyway, even if the caller knows (or casts) that the returned value is SmsOutputWritable and call SmsOutputWritable::enable() nothing really happens because the caller can't persist the changes to the repository, only entire aggregates can be persisted not individual nested entities. This is because aggregates and/or nested entities don't persist themselves, only an Application service can do this, using a repository.
How should you get the SmsContent entity from the Article without being able to change the enabled property from outside the aggregate?
Short answer: You don't. You get an immutable representation (ie: a value type) of the SmsContent.State from the Aggregate Root.
That's the approach taken by Evans in Domain Driven Design. There have been a couple of innovations that have gained traction since then.
One is the idea that a single entity can serve in multiple roles. Rather than having a single repository that serves many different use cases, you might have many repositories that handle specific cases. Here, that might look like a repository that returns the Aggregate Root when you want to be able to change something, and a different repository that returns a view/projection for use cases that only inspect the data.
This separation goes really well with ideas like lazy loading; if you aren't going to need some data for a particular use case, you interact with a repository that doesn't load it.
Udi Dahan's essay Better Domain-Driven Design Implementation provides a high level overview.
This looks a lot like the CQRS suggestion of Constantin. I mean, when you start using different repositories for reads and writes, then you're already with one feet in CQRS
It does, but there are a few intermediate steps along the way; CQS, responsibility driven design.
I'm trying to get data for a new field added in login page. What I've done:
Modify AccountController.php login function adding new parameter: $this->_app->login($user, $client, !empty($data['rememberme']))
In Userfrosting.php login function i've set it in application: $this->client = $client;
In setupTwigUserVariables funtion added twig global: $twig->addGlobal("client", $this->client);
The problem is that in a template, {{client.id}} returns nothing. Any help will be appreciated.
In UserFrosting 4, you should create a Twig extension in your Sprinkle's src/Twig/ directory, and add the variable to the return value for getGlobals.
Your situation is a little tricky, since I'm not sure how client can be a global variable but at the same time depend on $data['client_id'] - which appears to be a request parameter. For now, I'll assume that you're submitting this parameter with any requests that require the client variable.
<?php
/**
* Stack Overflow
*
* #link https://stackoverflow.com
*/
namespace UserFrosting\Sprinkle\Site\Twig;
use Interop\Container\ContainerInterface;
use UserFrosting\Sprinkle\Site\Database\Models\Client;
/**
* Extends Twig functionality for the Site sprinkle.
*
* #author Jose Luis
*/
class Extension extends \Twig_Extension
{
protected $services;
protected $config;
public function __construct(ContainerInterface $services)
{
$this->services = $services;
$this->config = $services->config;
}
public function getName()
{
return 'myproject';
}
public function getGlobals()
{
try {
$currentUser = $this->services->currentUser;
// Assumes the client_id is being submitted as a query string (url) parameter
$clientId = $this->services->request->getQueryParam('client_id');
$client = Client::where('client_id', clientId)->where('userid', $currentUser->id)->first();
} catch (\Exception $e) {
$client = null;
}
return [
'client' => $client
];
}
}
You will then need to register this extension in your Sprinkle's service provider class:
<?php
/**
* Stack Overflow
*
* #link https://stackoverflow.com
*/
namespace UserFrosting\Sprinkle\Site\ServicesProvider;
use UserFrosting\Sprinkle\Site\Twig\Extension as JoseExtension;
/**
* Services provider for the Site sprinkle.
*
* #author Jose Luis
*/
class ServicesProvider
{
/**
* Register extended user fields services.
*
* #param Container $container A DI container implementing ArrayAccess and container-interop.
*/
public function register($container)
{
/**
* Extends the 'view' service with Jose's Twig Extension.
*/
$container->extend('view', function ($view, $c) {
$twig = $view->getEnvironment();
$extension = new JoseExtension($c);
$twig->addExtension($extension);
return $view;
});
}
}
Yes, I know that there is a lot of boilerplate here. However once you set these up the first time, it is easy to add new variables/functions/filters to the Twig environment and new services to your Sprinkle in the future.
A lot of times in a Zend Framework 2 view I'll be calling $this->escapeHtml() to make sure my data is safe. Is there a way to switch this behaviour from a blacklist to a whitelist?
PS: Read an article from Padraic Brady that suggests that automatic escaping is a bad idea. Additional thoughts?
You could write your own ViewModel class which escapes data when variables are assigned to it.
Thanks to Robs comment, I extended the ZF2 ViewModel as follows:
namespace Application\View\Model;
use Zend\View\Model\ViewModel;
use Zend\View\Helper\EscapeHtml;
class EscapeViewModel extends ViewModel
{
/**
* #var Zend\View\Helper\EscapeHtml
*/
protected $escaper = null;
/**
* Proxy to set auto-escape option
*
* #param bool $autoEscape
* #return ViewModel
*/
public function autoEscape($autoEscape = true)
{
$this->options['auto_escape'] = (bool) $autoEscape;
return $this;
}
/**
* Property overloading: get variable value;
* auto-escape if auto-escape option is set
*
* #param string $name
* #return mixed
*/
public function __get($name)
{
if (!$this->__isset($name)) {
return;
}
$variables = $this->getVariables();
if($this->getOption('auto_escape'))
return $this->getEscaper()->escape($variables[$name]);
return $variables[$name];
}
/**
* Get instance of Escaper
*
* #return Zend\View\Helper\EscapeHtml
*/
public function getEscaper()
{
if (null === $this->escaper) {
$this->escaper = new EscapeHtml;
}
return $this->escaper;
}
}
In a Controller it could be used like this:
public function fooAction()
{
return new EscapeViewModel(array(
'foo' => '<i>bar</i>'
));
//Turn off auto-escaping:
return new EscapeViewModel(array(
'foo' => '<i>bar</i>'
),['auto_escape' => false]);
}
Question:
I would appreciate it if soemebody would comment, if this is best practice or if there is a better and ecp. more efficient and resource-saving way?