I don't understand the purpose of code snippet - zend-framework2

In Zend Frameword 2.5 a review and saw some code, it works fine but my IDE shows error about it.
I don't know purpose of this code snippet.
Why to write: $this->table = clone $this->table;
Github Link: https://github.com/zendframework/zend-db/blob/master/src/TableGateway/AbstractTableGateway.php
Function: rows 529-544
Please explain to me about it.
public function __clone()
{
$this->resultSetPrototype = (isset($this->resultSetPrototype)) ? clone $this->resultSetPrototype : null;
$this->sql = clone $this->sql;
if (is_object($this->table)) {
$this->table = clone $this->table;
} elseif (
is_array($this->table)
&& count($this->table) == 1
&& is_object(reset($this->table))
) {
foreach ($this->table as $alias => &$tableObject) {
$tableObject = clone $tableObject;
}
}
}

I can't understand Zend purpose but i hope after run two below code snippet, from different two results, you can understand
<?php
class A {
public $foo = 1;
}
class B {
protected $value = 1;
protected $bar = null;//
public function __construct() {
$this->bar = new A();
}
public function setValue($foo = 3){
$this->value = $foo;
}
public function setFooBar($foo = 3){
$this->bar->foo = $foo;
}
public function __clone() {
$this->bar = clone($this->bar);
}
}
$a = new B();
$c = clone($a);
$c->setFooBar(3);
$c->setValue(6);
var_dump($a);
echo "\n";
var_dump($c);
?>
<?php
class A {
public $foo = 1;
}
class B {
protected $value = 1;
protected $bar = null;//
public function __construct() {
$this->bar = new A();
}
public function setValue($foo = 3){
$this->value = $foo;
}
public function setFooBar($foo = 3){
$this->bar->foo = $foo;
}
}
$a = new B();
$c = clone($a);
$c->setFooBar(3);
$c->setValue(6);
var_dump($a);
echo "\n";
var_dump($c);
?>

clone (or __clone) is a so called magic method. Check for reference on other magic methods the php documentation on magic methods here.
Check also the specific documentation for clone where they explain the working of this magic method:
An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). An object's __clone() method cannot be called directly.
In other words it allows you to define custom cloning behavior for an object instance inside its class definition using a public __clone method. This method will be called "magically" when you do:
$clone = clone $instance;

Related

Fatfree php (v3.6.5) dependency injection CONTAINER

Does anybody have a simple example of usage?
https://fatfreeframework.com/3.6/quick-reference#CONTAINER page
seem to me not really explanatory, but generally i need to figure a nice way to auto-inject $db_connection object just when/where needed, e.g.
In class's beforeRoute() method for smooth route resolving
When porting selfoss to use DI, I chose Dice as suggested in the docs you linked. I set up the container to use only a single shared instance of the DB class and pass it the connection string:
$f3 = Base::instance();
$dice = new Dice\Dice;
$host = $f3->get('db_host');
$database = $f3->get('db_database');
$dsn = "pgsql:host=$host; dbname=$database";
$dbParams = [
$dsn,
$f3->get('db_username'),
$f3->get('db_password')
];
$dice->addRule(DB\SQL::class, [
'constructParams' => $dbParams,
'shared' => true,
]);
$f3->set('CONTAINER', function($class) use ($dice) {
return $dice->create($class);
});
Then F3 will use the Dice container to create classes so controllers and any of their dependencies will be passed the instantiated dependencies in the constructor:
namespace daos;
class Items {
private DB\SQL $db;
public function __construct(DB\SQL $db) {
$this->db = $db;
}
public function fetchAll() {
$entries = $this->db->exec(…);
…
}
}
See the selfoss source code for a full example of how to configure the dependency container.
So, i've opted for singleton:
// Database class
class DB
{
private static $_instance = null;
private $dbconn = null;
// config files should better be located in more secure dir
const DB_HOST = '127.0.0.1';
const DB_NAME = 'my_db_name';
const DB_USER = 'my_db__user';
const DB_PASS = 'my_db_passw';
const CHARSET = 'utf8';
const DB_PREFIX = '';
///////////////////////////////////
private function __construct () {
$this->dbconn=new DB\SQL(
'mysql:host='.self::DB_HOST.';port='.self::DB_PORT.';dbname='.self::DB_NAME,
self::DB_USER,
self::DB_PASSW,
$options = array(
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_PERSISTENT => FALSE)
);
}
////////////////////////////////////
public static function getInstance() {
if (!self::$_instance) {
self::$_instance = new DB();
}
return self::$_instance;
}
//////////////////////////////////
public function connect() {
if ($this->dbconn) {
echo 'Hooray - 1st stage connected!';
return $this->dbconn;
}
else echo '<br>Sad enough, no connection :(((';
}
///////////// ///////////////// ////////////////////
private function __clone() { }
private function __wakeup() { }
}
Sorry for dummyness, i've just discovered for myself built in \Prefab class (to be extended for singletons), so the above DB connection i'd rather do LIKE%:
class DB extends \Prefab {
private $dbconn;
// ..then just do connection thing
public function connect() {
//////
}
}

Xtext validation across (unreferenced) files

I am struggling to validate (non-duplication) globally, across multiple files that do not explicitly reference each other.
Consider the standard initally-generated grammar
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
greetings+=Greeting*;
Greeting:
'Hello' name=ID '!';
It is simple to validate that no file contains greeting for the same name.
package org.xtext.example.mydsl.validation
import org.eclipse.xtext.validation.Check
import org.xtext.example.mydsl.myDsl.Greeting
import org.xtext.example.mydsl.myDsl.Model
import org.xtext.example.mydsl.myDsl.MyDslPackage
class MyDslValidator extends AbstractMyDslValidator {
public static val LOCALLY_DUPLICATE_NAME = 'LOCALLY_DUPLICATE_NAME'
#Check
def checkGreetingLocallyUnique(Greeting greeting) {
for(greeting_ : (greeting.eContainer as Model).greetings) {
if(greeting!==greeting_ && greeting.name==greeting_.name) {
warning('Greeting duplication',
MyDslPackage.Literals.GREETING__NAME,
LOCALLY_DUPLICATE_NAME)
}
}
}
}
I do not understand how to validate non-duplication against all the files known to the global-index.
The stub of the method is
#Check
def checkGreetingGloballyUnique(Greeting greeting) {
for(greeting_ : /*???*/ ) {
if(greeting!==greeting_ && greeting.name==greeting_.name) {
warning('Global Greeting duplication',
MyDslPackage.Literals.GREETING__NAME,
GLOBALLY_DUPLICATE_NAME)
}
}
}
How do I get access to the global index from within the validator?
the easiest way for a local duplicate validation is to enable it in the workflow and regenerate the language (this does not check locally though)
validator = {
composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
}
to search the index
#Inject
IContainer.Manager containermanager;
#Inject
ResourceDescriptionsProvider resourceDescriptionsProvider;
public .... getAllEntitiesFor( EObject eObject ) {
....
IResourceDescriptions resourceDescriptions = resourceDescriptionsProvider.getResourceDescriptions( eObject.eResource() );
IResourceDescription resourceDescription = resourceDescriptions.getResourceDescription( eObject.eResource().getURI() );
List<IContainer> visiblecontainers = containermanager.getVisibleContainers( resourceDescription, resourceDescriptions );
for (IContainer container : visiblecontainers) {
for (IEObjectDescription eobjectDescription : container.getExportedObjects()) {
EObject eObjectOrProxy = eobjectDescription.getEObjectOrProxy();
.....
}
}
....
}
After much hacking, I obtained the following.
public static val GLOBALLY_DUPLICATE_NAME = 'GLOBALLY_DUPLICATE_NAME'
#com.google.inject.Inject
IResourceDescriptions iResourceDescriptions
#Inject
Provider<XtextResourceSet> resourceSetProvider;
#Check
def checkGreetingGloballyUnique(Greeting greeting) {
for (resourceDescriptions : iResourceDescriptions.allResourceDescriptions) {
for (_greetingDescription : resourceDescriptions.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
val _greeting = resourceSetProvider.get.getEObject(_greetingDescription.EObjectURI, true) as Greeting
// don't use equality, ALWAYS not equal!!
if (greeting.eResource.URI != _greeting.eResource.URI) {
// this means distinct files, all greetings in same file have same uri
if (greeting.name == _greeting.name) {
warning('Global greeting duplication', MyDslPackage.Literals.GREETING__NAME,
LOCALLY_DUPLICATE_NAME)
}
}
}
}
}
Rewrite, based on #Christian Dietrich's comments, I have the following solution.
#Inject
IContainer.Manager containerManager;
#com.google.inject.Inject
IResourceDescriptions resourceDescriptions
#Inject
Provider<XtextResourceSet> resourceSetProvider;
#Check
def checkGreetingGloballyUnique(Greeting greeting) {
var greeting_description = resourceDescriptions.getResourceDescription(greeting.eResource.URI)
var visibleContainers = containerManager.getVisibleContainers(greeting_description, resourceDescriptions)
for (visibleContainer : visibleContainers) {
for (_greetingDescription : visibleContainer.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
val _greeting = resourceSetProvider.get.getEObject(_greetingDescription.EObjectURI, true) as Greeting
// don't use equality, ALWAYS greeting != _greeting !!
if (greeting.eResource.URI != _greeting.eResource.URI) {
// this means distinct files, all greetings in same file have same uri
if (greeting.name == _greeting.name) {
warning('Global greeting duplication', MyDslPackage.Literals.GREETING__NAME,
GLOBALLY_DUPLICATE_NAME)
}
}
}
}
}

TinyIoC Returning Same instance

I am new to the dependency injection pattern and I am having issues getting a new instance of a class from container.Resolve in tinyioc it just keeps returning the same instance rather than a new instance. Now for the code
public abstract class HObjectBase : Object
{
private string _name = String.Empty;
public string Name
{
get
{
return this._name;
}
set
{
if (this._name == string.Empty && value.Length > 0 && value != String.Empty)
this._name = value;
else if (value.Length < 1 && value == String.Empty)
throw new FieldAccessException("Objects names cannot be blank");
else
throw new FieldAccessException("Once the internal name of an object has been set it cannot be changed");
}
}
private Guid _id = new Guid();
public Guid Id
{
get
{
return this._id;
}
set
{
if (this._id == new Guid())
this._id = value;
else
throw new FieldAccessException("Once the internal id of an object has been set it cannot be changed");
}
}
private HObjectBase _parent = null;
public HObjectBase Parent
{
get
{
return this._parent;
}
set
{
if (this._parent == null)
this._parent = value;
else
throw new FieldAccessException("Once the parent of an object has been set it cannot be changed");
}
}
}
public abstract class HZoneBase : HObjectBase
{
public new HObjectBase Parent
{
get
{
return base.Parent;
}
set
{
if (value == null || value.GetType() == typeof(HZoneBase))
{
base.Parent = value;
}
else
{
throw new FieldAccessException("Zones may only have other zones as parents");
}
}
}
private IHMetaDataStore _store;
public HZoneBase(IHMetaDataStore store)
{
this._store = store;
}
public void Save()
{
this._store.SaveZone(this);
}
}
And the derived class is a dummy at the moment but here it is
public class HZone : HZoneBase
{
public HZone(IHMetaDataStore store)
: base(store)
{
}
}
Now since this is meant to be an external library I have a faced class for accessing
everything
public class Hadrian
{
private TinyIoCContainer _container;
public Hadrian(IHMetaDataStore store)
{
this._container = new TinyIoCContainer();
this._container.Register(store);
this._container.AutoRegister();
}
public HZoneBase NewZone()
{
return _container.Resolve<HZoneBase>();
}
public HZoneBase GetZone(Guid id)
{
var metadataStore = this._container.Resolve<IHMetaDataStore>();
return metadataStore.GetZone(id);
}
public List<HZoneBase> ListRootZones()
{
var metadataStore = this._container.Resolve<IHMetaDataStore>();
return metadataStore.ListRootZones();
}
}
However the test is failing because the GetNewZone() method on the Hadrian class keeps returning the same instance.
Test Code
[Fact]
public void ListZones()
{
Hadrian instance = new Hadrian(new MemoryMetaDataStore());
Guid[] guids = { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
int cnt = 0;
foreach (Guid guid in guids)
{
HZone zone = (HZone)instance.NewZone();
zone.Id = guids[cnt];
zone.Name = "Testing" + cnt.ToString();
zone.Parent = null;
zone.Save();
cnt++;
}
cnt = 0;
foreach (HZone zone in instance.ListRootZones())
{
Assert.Equal(zone.Id, guids[cnt]);
Assert.Equal(zone.Name, "Testing" + cnt.ToString());
Assert.Equal(zone.Parent, null);
}
}
I know its probably something simple I'm missing with the pattern but I'm not sure, any help would be appreciated.
First, please always simplify the code to what is absolutely necessary to demonstrate the problem, but provide enough that it will actually run; I had to guess what MemoryMetaDataStore does and implement it myself to run the code.
Also, please say where and how stuff fails, to point others straight to the issue. I spent a few minues figuring out that the exception I was getting was your problem and you weren't even getting to the assertions.
That said, container.Resolve<HZoneBase>() will always return the same instance because that's how autoregistration in TinyIoC works - once an abstraction has been resolved, the same instance is always returned for subsequent calls.
To change this, add the following line to the Hadrian constructor:
this._container.Register<HZoneBase, HZone>().AsMultiInstance();
This will tell the container to create a new instance for each resolution request for HZoneBase.
Also, Bassetassen's answer about the Assert part is correct.
In general, if you want to learn DI, you should read Mark Seemann's excellent book "Dependency Injection in .NET" - not quite an easy read as the whole topic is inherently complex, but it's more than worth it and will let you get into it a few years faster than by learning it on your own.
In your assert stage you are not incrementing cnt. You are also using the actual value as the expected one in the assert. This will be confusing, becuase it says something is excpected when it actually is the actual value that is returned.
The assert part should be:
cnt = 0;
foreach (HZone zone in instance.ListRootZones())
{
Assert.Equal(guids[cnt], zone.Id);
Assert.Equal("Testing" + cnt.ToString(), zone.Name);
Assert.Equal(null, zone.Parent);
cnt++;
}

Adding a parameter to GetItems in DotNetNuke sample Module

Below is the code from the DotNetNuke Sample module that gets a collection of items from the database that belong to a particular module. What I want is add a second parameter for it filter by. I'm guessing this has something to do with modifying the scope item.cs class but am not sure how exactly.
public IEnumerable<Item> GetItems(int moduleId)
{
IEnumerable<Item> t;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<Item>();
t = rep.Get(moduleId);
}
return t;
}
Any ideas?
Another way to do it in DAL2 is using the .Find() method. This is good if you want to query on an indexed field in your table and you don't care about caching scope:
public IEnumerable<Item> GetItemByName(int moduleId, string itemname)
{
IEnumerable<Item> t;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<Item>();
t = rep.Find("WHERE ModuleId = #0 AND ItemName LIKE #1", moduleId, itemname);
}
return t;
}
Here's some sample code from my SignalRChat module that uses DAL2 (http://signalrchat.codeplex.com/SourceControl/changeset/view/71473#1272188)
public IEnumerable<Message> GetRecentMessages(int moduleId, int hoursBackInTime, int maxRecords)
{
var messages = (from a in this.GetMessages(moduleId) where a.MessageDate.Subtract(DateTime.UtcNow).TotalHours <= hoursBackInTime select a).Take(maxRecords).Reverse();
return messages.Any() ? messages : null;
}
That is one approach, you can also use a SQL statement within the controller as well (http://signalrchat.codeplex.com/SourceControl/changeset/view/71473#1272186)
public ConnectionRecord GetConnectionRecordByConnectionId(string connectionId)
{
ConnectionRecord t;
using (IDataContext ctx = DataContext.Instance())
{
var connections = ctx.ExecuteQuery<ConnectionRecord>(CommandType.Text,
string.Format(
"select top 1 * from {0}{1}SignalRChat_ConnectionRecords where ConnectionId = '{2}'",
_databaseOwner,
_objectQualifier,
connectionId)).ToList();
if (connections.Any())
{
t = connections[0];
}
else
return null;
}
return t;
}

Overwrite doctrine setters when we are using i18n actAs

I want know if is possible (and how?) overwrite doctrine setters when we use i18n actAs...
I'm trying something like this:
class Category extends BaseCategory
{
/*
* Overwrite save method
*/
public function save(Doctrine_Connection $conn = null)
{
$conn = $conn ? $conn : $this->getTable()->getConnection();
$conn->beginTransaction();
try
{
$this->setSlug();
$ret = parent::save($conn);
$conn->commit();
return $ret;
}
catch (Exception $e)
{
$conn->rollBack();
throw $e;
}
}
public function setSlug()
{
$slug = $this->getName() . 'lala lala';
parent::_set('slug', $slug);
}
.....
But only save the $slug value in one lang (I have 2 languages).
Any Idea??
Thanks A Lot!
Thanks for replaying. I solved it like this:
$cultures =
sfConfig::get('app_cultures');
// seteamos slug
foreach($cultures as $culture)
{
parent::_set('slug', 'lala lala');
} ...
You can simply loop through the translations:
foreach($this->Translations as $lang => $t) {
$t->slug = $t->name.'lala';
}

Resources