PHP - Creating Doctrine Inherited Class
I am trying to class type inheritance with Doctrine. Eventually, I will be defining things using XML, but all the examples are done using doctags. I found the following and it seems to work. <?php use Doctrine\ORM\Mapping as ORM; /** * Inventory entity * * @ORM\Entity(repositoryClass="Inventory") * @ORM\Table(name="inventory") * @ORM\InheritanceType("JOINED") * @ORM\DiscriminatorColumn(name="discriminator_column", type="string") * @ORM\DiscriminatorMap({"inventory" = "AbstractItem", "inventory_room" = "Room"}) */ abstract class AbstractItem { /** * @ORM\Id @ORM\Column(name="inventory_id") @ORM\GeneratedValue * @var int */ protected $inventory_id; /** * @ORM\Column(type="string") * @var string */ protected $category; /** * @ORM\Column(type="string") * @var string */ protected $part_number; } use Doctrine\ORM\Mapping as ORM; /** * Inventory Room entity * @ORM\Entity * @ORM\Table(name="inventory_room") */ class Room extends AbstractItem { /** * @ORM\Column(type="string") * @var string */ protected $room_type; /** * @ORM\Column(type="string") * @var string */ protected $rack_limit;
But then I convert it to XML or YAML, and I get a Entity class 'Room' used in the discriminator map of class 'AbstractItem' does not exist error when trying to build the classes. I've also tried changing the type to mappedSuperclass, but no success. Any ideas? Also, what is the purpose of the DiscriminatorColumn? Thanks
AbstractItem: type: entity table: inventory inheritanceType: JOINED discriminatorColumn: name: discriminator_column type: string discriminatorMap: inventory: AbstractItem inventory_room: Room repositoryClass: Inventory id: inventory_id: type: string fields: category: type: string part_number: type: string Room: type: entity table: inventory_room fields: room_type: type: string rack_limit: type: string
<?xml version="1.0" encoding="utf-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity repository-class="Inventory" name="AbstractItem" table="inventory" inheritance-type="JOINED"> <discriminator-column name="discriminator_column" type="string" length="255"/> <discriminator-map> <discriminator-mapping value="inventory" class="AbstractItem"/> <discriminator-mapping value="inventory_room" class="Room"/> </discriminator-map> <id name="inventory_id" type="string" column="inventory_id"> <generator strategy="IDENTITY"/> </id> <field name="category" type="string" column="category" precision="0" scale="0" nullable="false"/> <field name="part_number" type="string" column="part_number" precision="0" scale="0" nullable="false"/> </entity> </doctrine-mapping> <?xml version="1.0" encoding="utf-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Room" table="inventory_room"> <id name="inventory_id" type="string" column="inventory_id"> <generator strategy="IDENTITY"/> </id> <field name="room_type" type="string" column="room_type" precision="0" scale="0" nullable="false"/> <field name="rack_limit" type="string" column="rack_limit" precision="0" scale="0" nullable="false"/> <field name="category" type="string" column="category" precision="0" scale="0" nullable="false"/> <field name="part_number" type="string" column="part_number" precision="0" scale="0" nullable="false"/> </entity> </doctrine-mapping>
Similar TutorialsHi, when i extend a class containing a private variable and then access the variable in the extended class it doesn't produce any error and works fine and when i access the variable using the object of the extended class it works even then, i think private variable should not be accessable in an extended class neither by object of that extended class here is the code <?php class textbox{ var $body_text, $body_text1; private $body_private="this is private value"; protected $body_protect="this is protected value"; function __construct($text_in, $text_out){ $this->body_text=$text_in; $this->body_text1=$text_out; } function display(){ echo "$this->body_text<br>"; echo "<i>"; echo "$this->body_text1</i><br>"; echo "$this->body_private<br/>"; echo "$this->body_protect<br/>"; } function test_new(){ echo "see if this private echo works"; } } $box=new textbox("any new value","any old value" ); $box->display(); $box->body_text="this is public thats why i can access it"; $box->body_text1="this is public thats why i can access it"; /*$box->body_private="this is private value changed"; //you will see we can't access the private and protected memebers from outside $box->body_protect="this is protected value changed"; */ $box->display(); $box->test_new(); class textboxbold extends textbox{ function __construct($text_on, $text_off, $text_get, $text_go) {$this->body_text=$text_on; $this->body_text1=$text_off; $this->body_protect=$text_get; $this->body_private=$text_go; } function display(){ echo "<b>$this->body_text</b><br>"; echo "<b>$this->body_text1</b><br>"; echo "<b>$this->body_protect</b><br>"; echo "<i>$this->body_private</i><br>"; } } $boxnew=new textboxbold("new Bold text", "text in bold","protected member","private"); $boxnew->display(); $boxnew->body_private="this is simple text taken from outside"; $boxnew->display(); $boxnew->test_new(); ?> please recommend, is it working as it should be Trying to create a model where Parent1 and Parent2 extend Grandparent, and Child1_1 and Child1_2 extend Parent1 as well as Child2_1 and Child2_2 extend Parent2. I set up my definitions: Grandparent: type: entity table: grandparent_table inheritanceType: JOINED discriminatorColumn: name: discriminator_column_grandparent type: string repositoryClass: GrandParent id: id: type: integer generator: strategy: AUTO fields: GrandParent_Item1: type: string GrandParent_Item2: type: string Parent1: type: entity table: parent_table1 extends: Grandparent inheritanceType: JOINED discriminatorColumn: name: discriminator_column_parent1 type: string id: id: associationKey: true fields: Parent1_Item1: type: string Parent1_Item2: type: string Parent2: type: entity table: parent_table2 extends: Grandparent inheritanceType: JOINED discriminatorColumn: name: discriminator_column_parent2 type: string id: id: associationKey: true fields: Parent2_Item1: type: string Parent2_Item2: type: string Child1_1: extends: Parent1 type: entity table: child1_1_table id: id: associationKey: true fields: Child1_1_Item1: type: string Child1_1_Item2: type: string Child1_2: extends: Parent1 type: entity table: child1_2_table id: id: associationKey: true fields: Child1_2_Item1: type: string Child1_2_Item2: type: string Child2_1: extends: Parent2 type: entity table: child2_1_table id: id: associationKey: true fields: Child2_1_Item1: type: string Child2_1_Item2: type: string Child2_2: extends: Parent2 type: entity table: child2_2_table id: id: associationKey: true fields: Child2_2_Item1: type: string Child2_2_Item2: type: string And then generate my entities: $ vendor/bin/doctrine orm:generate-entities -vvv src Processing entity "Child1_1" Processing entity "Child1_2" Processing entity "Child2_1" Processing entity "Child2_2" Processing entity "Grandparent" Processing entity "Parent1" Processing entity "Parent2" [OK] Entity classes generated to "/var/www/doctrine/src" Note that I needed to manually edit the Parent1 and 2 classes to extend Grandparent as well as the individual Child classes to extend their applicable Parent. Next, I create the schema: $ vendor/bin/doctrine orm:schema-tool:create --dump-sql The following SQL statements will be executed: CREATE TABLE child1_1_table (id INT NOT NULL, Child1_1_Item1 VARCHAR(255) NOT NULL, Child1_1_Item2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; CREATE TABLE child1_2_table (id INT NOT NULL, Child1_2_Item1 VARCHAR(255) NOT NULL, Child1_2_Item2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; CREATE TABLE child2_1_table (id INT NOT NULL, Child2_1_Item1 VARCHAR(255) NOT NULL, Child2_1_Item2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; CREATE TABLE child2_2_table (id INT NOT NULL, Child2_2_Item1 VARCHAR(255) NOT NULL, Child2_2_Item2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; CREATE TABLE grandparent_table (id INT AUTO_INCREMENT NOT NULL, GrandParent_Item1 VARCHAR(255) NOT NULL, GrandParent_Item2 VARCHAR(255) NOT NULL, discriminator_column_grandparent VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; CREATE TABLE parent_table1 (id INT NOT NULL, Parent1_Item1 VARCHAR(255) NOT NULL, Parent1_Item2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; CREATE TABLE parent_table2 (id INT NOT NULL, Parent2_Item1 VARCHAR(255) NOT NULL, Parent2_Item2 VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB; ALTER TABLE child1_1_table ADD CONSTRAINT FK_3445750EBF396750 FOREIGN KEY (id) REFERENCES grandparent_table (id) ON DELETE CASCADE; ALTER TABLE child1_2_table ADD CONSTRAINT FK_5AD6F93BF396750 FOREIGN KEY (id) REFERENCES grandparent_table (id) ON DELETE CASCADE; ALTER TABLE child2_1_table ADD CONSTRAINT FK_DC849CBBF396750 FOREIGN KEY (id) REFERENCES grandparent_table (id) ON DELETE CASCADE; ALTER TABLE child2_2_table ADD CONSTRAINT FK_3C205356BF396750 FOREIGN KEY (id) REFERENCES grandparent_table (id) ON DELETE CASCADE; ALTER TABLE parent_table1 ADD CONSTRAINT FK_5386E15BBF396750 FOREIGN KEY (id) REFERENCES grandparent_table (id) ON DELETE CASCADE; ALTER TABLE parent_table2 ADD CONSTRAINT FK_CA8FB0E1BF396750 FOREIGN KEY (id) REFERENCES grandparent_table (id) ON DELETE CASCADE; I see how Grandparent has discriminatorColumn discriminator_column_grandparent as expected. But why doesn't Parent1 and Parent2 have discriminatorColumn's discriminator_column_parent1 and discriminator_column_parent2? Note that I've also tried making Grandparent, Parent1, and Parent2 abstract but get the same results. I've also messed around with Mapped Superclasses, but I don't think they are applicable for my use (correct me if you think I am wrong). Thanks! I would to create my own php class for my website but i dunno the fundamentals of PHP CLASSES. Can anyone teach me how to create and use php class. best if you go into deeper explanations. My main subject is to create a social net site Write a class for feeding a horse. The Horse object should keep track of the last time it was fed and calculate when it is hungry. Assume there is another class that checks the horse every 10 minutes to see if it is hungry and if it is, it calls another method which feeds it. There should be about 3 methods on the class, but more can be added if needed. Hi there, I am just wondering which way is the correct one if you want to create object properties/attribute dynamically at run time using magic method __set(), __get(), for example: class Foo{ public $data = array(); public function __set($name,$value){ $this->data[$name] = $value; } public function __get($name){ if ( isset($this->data[$name]) ){ return $this->data[$name]; } } } Or using the below way class Foo{ public function assign(array $data){ foreach($data as $key => $value){ $this->$key = $value; } } } I just encountered the second way in many places and I am totally confused . Is the __set() method called implicitly by the PHP engine in the second way or what? how come this is considered as a valid code ? your usual help is appreciated Hey, this is my first time using this forum, so I apologize if I miss something and I'd like to thank you in advance for your help. I inherited some code from a different php programmer and it's not quite working right. The basics: We have a form for users to fill out where they select a Township from a drop down menu, then based on the township they choose there is a 2nd drop down populated with Range values. I can get the Township drop down to populate from the mysql database, but once you select the Township, the 2nd drop down does not populate as expected. This worked on the old web server (which I regrettably no longer have access to), but it's not working on the new web server. I hope that the problem is just a version issue where some syntax changed, but I'm not sure. Here's the function: Code: [Select] <?php echo "<form method='post' name='tsform' id='tsform' action='".$_SERVER['PHP_SELF']."'><input type=hidden name='page' id='page' value='viewfntown'>"; echo "<table><tr VALIGN=baseline><td></td>"; echo "<td>Township: <select name='ts' id='ts'><option value=''></option>"; $sql="SELECT distinct(township) from `linksurv_field_notes` WHERE `township`!='' order by `township`;"; $result=mysql_query($sql) or die("ts sel:".mysql_error()); $NumResults=mysql_num_rows($result); for ($q=1;$q<=$NumResults;$q++) { $row=mysql_fetch_row($result); $township=$row[0]; echo "<option value='".$township."'>".$township."</option>"; } echo "</select></td>"; echo "<td>Range: <select name='rg' id='rg'><option value=''></option>"; $sql="SELECT distinct(range) from `linksurv_field_notes` WHERE `range`!='' order by `range`;"; $result=mysql_query($sql) or die("rg sel:".mysql_error()); $NumResults=mysql_num_rows($result); for ($q=1;$q<=$NumResults;$q++) { $row=mysql_fetch_row($result); $range=$row[0]; echo "<option value='".$range."'>".$range."</option>"; } echo "</select></td>"; echo "<td><button type=button onClick=\"return submitCorner('NA','NA');\">Show All Corners</button></td>"; echo "</tr>"; echo "</table>"; ?> Also, here is the error I see in Firebug: Code: [Select] rg sel:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'range) from `linksurv_field_notes` WHERE `range`!='' order by `range`' at line 1 I've been stumped on this for a few weeks and any help you can give is appreciated. If I left some details out, just ask. Thanks. So, I was given the task of editing a website. It was done in PHP for the most part.
If you visit the page http://cre-finance.com/?Contact-Us, I'm attempting to edit the contact info at the bottom but I have no idea where to find it in the website files. If you the view the source, it's right there like it's taunting me but none of the php files have that info in it. There is a contactus.php (I attached the code for it) but all it has is the code for the form at the bottom of the Contact Us page.
I've noticed references to "?p=Contact-Us" in the source, and also in the sitemap.xml file but I have no idea what that really means because there are no other "contactus" pages other than the one I mentioned above. I guess I'm not really looking for help with actual coding but perhaps to be pointed in the right direction to edit that information.
HELP!
Attached Files
contact_us.php 3.55KB
0 downloads I think I am close, but not sure if I am quite there. Am I doing this correctly? I have several entity classes which will use class type inheritance:
MyNamespace\MyApp\Vehicle\Vehicle #MyNamespace.MyApp.Vehicle.Vehicle.dcm.yml MyNamespace\MyApp\Vehicle\Vehicle: type: entity table: vehicle_table inheritanceType: JOINED discriminatorColumn: name: discriminator_column type: string discriminatorMap: vehicle: Vehicle groundVehicle: MyNamespace\MyApp\Vehicle\GroundVehicle\GroundVehicle airVehicle: MyNamespace\MyApp\Vehicle\AirVehicle\AirVehicle repositoryClass: Vehicle id: id: type: integer generator: strategy: AUTO fields: grandParentItem1: type: string grandParentItem2: type: string #MyNamespace.MyApp.Vehicle.AirVehicle.AirVehicle.dcm.yml MyNamespace\MyApp\Vehicle\AirVehicle\AirVehicle: type: entity table: air_vehicle extends: MyNamespace\MyApp\Vehicle\Vehicle inheritanceType: JOINED discriminatorMap: airVehicle: AirVehicle airplane: MyNamespace\MyApp\Vehicle\AirVehicle\Airplane\Airplane rocket: MyNamespace\MyApp\Vehicle\AirVehicle\Rocket\Rocket repositoryClass: AirVehicle id: id: associationKey: true fields: parentItem1: type: string parentItem2: type: string #MyNamespace.MyApp.Vehicle.AirVehicle.Rocket.Rocket.dcm.yml MyNamespace\MyApp\Vehicle\AirVehicle\Rocket\Rocket: extends: MyNamespace\MyApp\Vehicle\AirVehicle\AirVehicle type: entity table: rocket_table id: id: associationKey: true repositoryClass: Rocket fields: childItem1: type: string childItem2: type: string I haven't shown GroundVehicle or Train, Car, and Airplane, but they are almost identical to AirVehicle and Rocket, respectively.
I've discovered that the barebone entities need to be manually created prior to using orm:generate-entities else I get class not found errors, and have created them as shown below. [michael@devserver doctrine]$ find inheritance_src -name "*.php" -exec cat {} \; <?php namespace MyNamespace\MyApp\Vehicle\AirVehicle\Airplane; class Airplane extends \MyNamespace\MyApp\Vehicle\AirVehicle\AirVehicle{} <?php namespace MyNamespace\MyApp\Vehicle\AirVehicle\Rocket; class Rocket extends \MyNamespace\MyApp\Vehicle\AirVehicle\AirVehicle{} <?php namespace MyNamespace\MyApp\Vehicle\AirVehicle; abstract class AirVehicle extends \MyNamespace\MyApp\Vehicle\Vehicle{} <?php namespace MyNamespace\MyApp\Vehicle\GroundVehicle\Car; class Car extends \MyNamespace\MyApp\Vehicle\GroundVehicle\GroundVehicle{} <?php namespace MyNamespace\MyApp\Vehicle\GroundVehicle\Train; class Train extends \MyNamespace\MyApp\Vehicle\GroundVehicle\GroundVehicle{} <?php namespace MyNamespace\MyApp\Vehicle\GroundVehicle; abstract class GroundVehicle extends \MyNamespace\MyApp\Vehicle\Vehicle{} <?php namespace MyNamespace\MyApp\Vehicle; abstract class Vehicle{} I then am able to successfully create the entities using orm:generate-entities, schema using orm:schema-tool:create, and repositories using orm:generate-repositories. Does everything seem correct? A couple of issues which I have my doubts: Locating the classes in inheritance_src/MyNamespace/MyApp instead of inheritance_src/MyApp. I tried to do the later and modify my psr-4 autoloader to use "MyNamespace\\": "inheritance_src/", but could not get it working without first creating the entities, editing them to add the "abstract" and "extend" portions, and then moving them to one directory lower. Needing to manually create the barebone classes in the first place. My meta-data definitions includes "extends: MyNamespace\MyApp\Vehicle\Vehicle", so I would thought it would not be necessary. Locate both the entities and repositories in the same folder. For that matter, I will probably be locating my service in the same folder as well. It seems that most frameworks will locate all the entities in one folder (with of course subdirectories), repositories in another, services in another, etc. The way I am doing seems to be organized domain modules as described by https://mnapoli.fr/organizing-code-into-domain-modules/. Any compelling reasons to do it one way or the other?
Thank you Hoping to get some thoughts on how Doctrine array collections should be used when the position of the items in the collection must be controlled. For instance, I have a Chart object which has various primitive properties as well as a series property which is an array collection. Each member in the series collection is a Serie object which has various primitive properties as well as a data property which is an array collection. Each member in the data collection is a Datum object which includes various primitive properties. The following just refers to the series collection, however, will be doing the same with the data collection. Chart will have methods to add a Serie to the end of the series collection, modify a Serie for a given position, delete a Serie for a given position, swap the position of two Serie, and retrieve all Serie(s) in their designated position order. To implement this, my thought is to include a integer position property in Serie, and when retrieving the results will just ORDER BY this column if using DQL or maybe will use Criteria to filter the results. I am not, however, sure how to implement some of the other methods. When adding a new Serie to the end of the collection, should I do something like: class Chart { public function addSerie(array $params):Chart { $serie=new Serie(); $serie->setName($params['name']); $position=$this->series->count(); $serie->setPosition($position); $this->addSeries($serie); } }
class Chart { public function __construct() { $this->series->getIterator()->uasort(function ($first, $second) { return (int) $first->getPosition() > (int) $second->getPosition() ? 1 : -1; }); } }
PS. Originally, I was using the name "Series" instead of "Serie", but the lack of separate forms for singular and plural was messing with me. Was thinking of using SeriesNode instead, but didn't want to need to follow this same naming convention for other items... The following metadata... <?xml version="1.0" encoding="utf-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="NotionCommotion\App\Account\PublicAccountIdIncrementor" table="public_account_id_incrementor"> <id name="account" association-key="true"/> <field name="chart_id" type="integer"> <options> <option name="default">0</option> </options> </field> <field name="source_id" type="integer"> <options> <option name="default">0</option> </options> </field> <one-to-one field="account" target-entity="NotionCommotion\App\Account\Account" fetch="LAZY" inversed-by="idPublicIncrementor"> <join-columns> <join-column name="id" referenced-column-name="id" nullable="false"/> </join-columns> </one-to-one> </entity> </doctrine-mapping> <?xml version="1.0" encoding="utf-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="NotionCommotion\App\Account\Account" table="account"> <id name="id" type="integer"/> <one-to-one field="idPublicIncrementor" target-entity="NotionCommotion\App\Account\PublicAccountIdIncrementor" mapped-by="account"/> </entity> </doctrine-mapping> creates the following methods... <?php class Account { /** * Set idPublicIncrementor. * * @param \NotionCommotion\App\Account\PublicAccountIdIncrementor|null $idPublicIncrementor * * @return Account */ public function setIdPublicIncrementor(\NotionCommotion\App\Account\PublicAccountIdIncrementor $idPublicIncrementor = null) { $this->idPublicIncrementor = $idPublicIncrementor; return $this; } /** * Get idPublicIncrementor. * * @return \NotionCommotion\App\Account\PublicAccountIdIncrementor|null */ public function getIdPublicIncrementor() { return $this->idPublicIncrementor; } } As seen, Account::idPublicIncrementor allows NULL value. Is this by design since PublicAccountIdIncrementor's primary key is Account's primary key? If not, how do I instruct Doctrine to prevent NULL? This topic has been moved to Other Libraries and Frameworks. http://www.phpfreaks.com/forums/index.php?topic=324009.0 I'm starting in Doctrine 2.4 and I'm developing a system where I separate the core files and application files, as follows:
/root |-- /Src |-- /App |-- /Model |-- ** (Application Entities) ** |-- /Core |-- /Model |-- ** (Core Entities) **In the Doctrine documentation shows the following form to set 1 directory for Esntitys: $config = Setup::createAnnotationMetadataConfiguration(array(__DIR__. "/src"), $isDevMode);But when I have to configure more than one directory that will contain the Entitys of my application, how to proceed? Thanks in advance! Finally getting around to giving Doctrine a try. Looks like YAML is depreciated, so my choices are DocBlocks or XML. I am sure it is personal choice, however, I would like to start off with what most feel is the best path. Any recommendations? Thanks Anyone know why the following results in an error? Not a big deal as memory is not an issue and I can (and have) just changed it to create a new array instead of using a generator, but still curious. Thanks <?php foreach($doctrineCollection as $doctrineEntity){ yield new MyWrapper($doctrineEntity); /* After around 4 iterations, results in the following error: syslog Apr 06 15:25:25 myserver.net kernel: php-fpm[42889]: segfault at 7f8156a14100 ip 000055bb1d79acfd sp 00007ffd0b50a968 error 4 in php-fpm[55bb1d47c000+46e000] /var/log/php-fpm/error.log [Mon Apr 06 20:06:38.781360 2020] [proxy_fcgi:error] [pid 1501:tid 140210423629568] (104)Connection reset by peer: [client 12.345.67.890:45574] AH01075: Error dispatching request to : /var/log/httpd/error_log [06-Apr-2020 20:04:52] WARNING: [pool michael] child 5524 exited on signal 11 (SIGSEGV) after 0.138268 seconds from start [06-Apr-2020 20:04:52] NOTICE: [pool michael] child 5526 started */ } class MyWrapper { private $doctrineEntity; public function __construct($doctrineEntity) { $this->doctrineEntity=$doctrineEntity; } }
I am doing something stupid, and just can't see it and hoping someone has better eyes than mine. I have two Doctrine entities which extend another class using single class inheritance, but when retrieving the collection of either of the two child classes, I get the collection of the parent (i.e. combination of both child classes). I've experimented with making the parent abstract and not including it in the discriminator map but no change. In hopes to identifying my mistake, I created a new Symfony project with just the relevant classes and show all steps below. Initial install by running the following: symfony new test composer update composer require doctrine/orm composer require migrations composer require maker --dev composer require security Using "php bin/console make:user", I created three users: AbstractUser, OwnerUser, VendorUser. I then edited all three entities and the owner and vendor repositories as follows: <?php namespace App\Entity; use App\Repository\AbstractUserRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\UserInterface; /** * @ORM\Entity(repositoryClass=AbstractUserRepository::class) * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="discr", type="string") * @ORM\DiscriminatorMap({"owner" = "OwnerUser", "vendor" = "VendorUser", "abstract" = "AbstractUser"}) */ class AbstractUser implements UserInterface { // No changes made }
<?php namespace App\Entity; use App\Repository\OwnerUserRepository; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=OwnerUserRepository::class) */ class OwnerUser extends AbstractUser { }
<?php namespace App\Entity; use App\Repository\VendorUserRepository; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass=VendorUserRepository::class) */ class VendorUser extends AbstractUser { } No change to AbstractUserRepository. <?php namespace App\Repository; class OwnerUserRepository extends AbstractUserRepository { }
<?php namespace App\Repository; class VendorUserRepository extends AbstractUserRepository { } Then I migrated the DB. php bin/console doctrine:schema:drop --full-database --force rm migrations/* php bin/console make:migration php bin/console doctrine:migrations:migrate Next I created two OwnerUsers and one VendorUser using a command script I wrote shown at the end of this post. # php bin/console app:tester create OwnerUser roles=[] # php bin/console app:tester create OwnerUser roles=[] # php bin/console app:tester create VendorUser roles=[] Checked the PostSQL database. facdocs=> \d List of relations Schema | Name | Type | Owner --------+-----------------------------+----------+--------- public | abstract_user | table | facdocs public | abstract_user_id_seq | sequence | facdocs public | doctrine_migration_versions | table | facdocs (3 rows) facdocs=> select * from abstract_user; id | email | roles | password | discr ----+-------------+-------+----------------+-------- 1 | setEmail158 | [] | setPassword146 | owner 2 | setEmail87 | [] | setPassword101 | owner 3 | setEmail62 | [] | setPassword20 | vendor (3 rows) facdocs=>
Next, I retrieved the entities using Doctrine along with the beforementioned test script. [michael@devserver test]$ php bin/console app:tester read VendorUser Test Entity Manager ============ command: read entity: VendorUser class: \App\Entity\VendorUser properties: [] array(3) { [0]=> object(stdClass)#293 (5) { ["__CLASS__"]=> string(20) "App\Entity\OwnerUser" ["id:App\Entity\AbstractUser:private"]=> int(1) ["email:App\Entity\AbstractUser:private"]=> string(11) "setEmail158" ["roles:App\Entity\AbstractUser:private"]=> string(8) "Array(0)" ["password:App\Entity\AbstractUser:private"]=> string(14) "setPassword146" } [1]=> object(stdClass)#294 (5) { ["__CLASS__"]=> string(20) "App\Entity\OwnerUser" ["id:App\Entity\AbstractUser:private"]=> int(2) ["email:App\Entity\AbstractUser:private"]=> string(10) "setEmail87" ["roles:App\Entity\AbstractUser:private"]=> string(8) "Array(0)" ["password:App\Entity\AbstractUser:private"]=> string(14) "setPassword101" } [2]=> object(stdClass)#358 (5) { ["__CLASS__"]=> string(21) "App\Entity\VendorUser" ["id:App\Entity\AbstractUser:private"]=> int(3) ["email:App\Entity\AbstractUser:private"]=> string(10) "setEmail62" ["roles:App\Entity\AbstractUser:private"]=> string(8) "Array(0)" ["password:App\Entity\AbstractUser:private"]=> string(13) "setPassword20" } } [michael@devserver test]$ [michael@devserver test]$ php bin/console app:tester read OwnerUser Test Entity Manager ============ command: read entity: OwnerUser class: \App\Entity\OwnerUser properties: [] array(3) { [0]=> object(stdClass)#293 (5) { ["__CLASS__"]=> string(20) "App\Entity\OwnerUser" ["id:App\Entity\AbstractUser:private"]=> int(1) ["email:App\Entity\AbstractUser:private"]=> string(11) "setEmail158" ["roles:App\Entity\AbstractUser:private"]=> string(8) "Array(0)" ["password:App\Entity\AbstractUser:private"]=> string(14) "setPassword146" } [1]=> object(stdClass)#294 (5) { ["__CLASS__"]=> string(20) "App\Entity\OwnerUser" ["id:App\Entity\AbstractUser:private"]=> int(2) ["email:App\Entity\AbstractUser:private"]=> string(10) "setEmail87" ["roles:App\Entity\AbstractUser:private"]=> string(8) "Array(0)" ["password:App\Entity\AbstractUser:private"]=> string(14) "setPassword101" } [2]=> object(stdClass)#358 (5) { ["__CLASS__"]=> string(21) "App\Entity\VendorUser" ["id:App\Entity\AbstractUser:private"]=> int(3) ["email:App\Entity\AbstractUser:private"]=> string(10) "setEmail62" ["roles:App\Entity\AbstractUser:private"]=> string(8) "Array(0)" ["password:App\Entity\AbstractUser:private"]=> string(13) "setPassword20" } } [michael@devserver test]$
As seen, when requesting a collection of either OwnerUsers or VendorUsers, I am retrieving the combination of both collections. I am sure it is totally user (i.e. me) error, but just don't see it. Are you able to see my stupid mistake? Thanks
<?php namespace App\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Common\Util\Debug; class Tester extends Command { // the name of the command (the part after "bin/console") protected static $defaultName = 'app:tester'; private $entityManager; public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; parent::__construct(); } protected function configure() { $this ->setDescription('Doctrine Object Tester. --help') ->setHelp('This command allows you to query a single entity...') ->addArgument('cmd', InputArgument::REQUIRED, 'The command name [create, read].') ->addArgument('entity', InputArgument::REQUIRED, 'The name of the entity.') ->addArgument('properties', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'properies (foo=foo bla=[]') ; } private function getProperties($input) { $properties=[]; foreach($input as $property) { $property=explode('=', $property); $name = trim($property[0]); $value = trim($property[1]); if($value === '[]') { $value = []; } elseif($value === 'null') { $value = null; } elseif(substr($value, 0, 1) === '/') { $value = explode('/', substr($value, 1)); $class = ucfirst(substr($value[0], 0, -1)); $class = '\App\Entity\\'.$class; if(count($value)===1) { $value = $this->entityManager->getRepository($class)->findAll(); } else { $value = $this->entityManager->getRepository($class)->find($value[1]); } } $properties[$name] = $value; } return $properties; } protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln([ 'Test Entity Manager', '============', '', ]); // retrieve the argument value using getArgument() $cmd = $input->getArgument('cmd'); $output->writeln('command: '.$cmd); $entity = $input->getArgument('entity'); $output->writeln('entity: '.$entity); $class = '\App\Entity\\'.$entity; $output->writeln('class: '.$class); $properties = $this->getProperties($input->getArgument('properties')); $output->writeln('properties: '.json_encode($properties)); switch($cmd) { case 'create': $entity = new $class; foreach(get_class_methods($entity) as $method) { if(substr($method, 0, 3)==='set') { $m = lcfirst(substr($method, 3)); $entity->$method(array_key_exists($m, $properties)?$properties[$m]:$method.rand(0,200)); } } $this->entityManager->persist($entity); $this->entityManager->flush(); $output->writeln('entity created'); break; case 'read': Debug::dump($this->entityManager->getRepository($class)->findAll()); break; default: $output->writeln('INVALID COMMAND: '.$cmd.'. Only create and read are supported.'); } return Command::SUCCESS; } }
I am a little confused with the difference between Symfony Events and Event Listners and Doctrine Events. The Doctrine events look pretty straight forward and are primary used for entity persistence, and I have outlined my understanding below: Doctrine Lifecycle Callbacks. Single entity and single Doctrine event. Method in class. Good performance. Don't have access to Symfony services (all others do) Doctrine Lifecycle Listeners. All entities and single Doctrine event. Separate class and configured in config.service.yaml. Doctrine Entity Listeners. Single entities and single Doctrine event. Separate class and configured in config.service.yaml. Doctrine Lifecycle Subscribers. All entities and multiple Doctrine event. Must implement EventSubscriber (or probably EventSubscriberInterface) Separate class and configured in config.service.yaml.I am more confused with the Symfony events and my interpretation as listed below is likely incorrect. Symfony Event Listeners. Single Symfony event. Separate class and configured in config.service.yaml. More flexible because bundles can enable or disable each of them conditionally depending on some configuration value. Symfony Event Subscribers. All specified Symfony events. Must implement EventSubscriberInterface Separate class but NOT configured in config.service.yaml but in class. Easier to reuse because the knowledge of the events is kept in the class rather than in the service definition.Are they used for totally different purposes or can one use Symfony events to also deal with entities? Where would one want to use these Symfony events? Is there a reason why Doctrine Lifecycle Subscribers are located in src/EventListener and not src/EventSubscriber Are Doctrine Lifecycle and Entity Listeners really only for a single event as I interpret the documentation states, or is it one method per Doctrine event such as the following? App\EventListener\SearchIndexer: tags: - name: 'doctrine.event_listener' event: 'postPersist' - name: 'doctrine.event_listener' event: 'postUpdate'
I have mysqli object in Database class base: [color=]database class:[/color] class Database { private $dbLink = null; public function __construct() { if (is_null($this->dbLink)) { // load db information to connect $init_array = parse_ini_file("../init.ini.inc", true); $this->dbLink = new mysqli($init_array['database']['host'], $init_array['database']['usr'], $init_array['database']['pwd'], $init_array['database']['db']); if (mysqli_connect_errno()) { $this->dbLink = null; } } } public function __destruct() { $this->dbLink->close(); } } Class derived is Articles where I use object dBLink in base (or parent) class and I can't access to mysqli methods (dbLink member of base class): Articles class: require_once ('./includes/db.inc'); class Articles extends Database{ private $id, .... .... $visible = null; public function __construct() { // Set date as 2009-07-08 07:35:00 $this->lastUpdDate = date('Y-m-d H:i:s'); $this->creationDate = date('Y-m-d H:i:s'); } // Setter .... .... // Getter .... .... public function getArticlesByPosition($numArticles) { if ($result = $this->dbLink->query('SELECT * FROM articles ORDER BY position LIMIT '.$numArticles)) { $i = 0; while ($ret = $result->fetch_array(MYSQLI_ASSOC)) { $arts[$i] = $ret; } $result->close(); return $arts; } } } In my front page php I use article class: include_once('./includes/articles.inc'); $articlesObj = new articles(); $articles = $articlesObj->getArticlesByPosition(1); var_dump($articles); [color=]Error that go out is follow[/color] Notice: Undefined property: Articles::$dbLink in articles.inc on line 89 Fatal error: Call to a member function query() on a non-object in articles.inc on line 89 If I remove constructor on derived class Articles result don't change Please help me If a class has a constructor but also has a static method, if I call the static method does the constructor run so that I can use an output from the constructor in my static method? --Kenoli Hi Can you call Class A's methods or properties from Class B's methods? Thanks. Ok. I know you can pass the object of a class as an argument. Example: class A { function test() { echo "This is TEST from class A"; } } class B { function __construct( $obj ) { $this->a = $obj; } function test() { $this->a->test(); } } Then you could do: $a = new A(); $b = new B($a); Ok so that's one way i know of. I also thought that you could make a method static, and do this: (assuming class A's test is 'static') class B { function test() { A::test(); } } But that is not working. I'd like to know all possible ways of accomplishing this. Any hints are appreciated. thanks |