Edit and export continuously

It is as simple as it can be. Try it now.

  • Entity
  • Bundle
  • Project
Skipper diagram - entity Skipper diagram - bundle Skipper diagram - project

1. Visually edit your project model.

  • Attributes
  • Annotations
  • XML
  • YML
  • Code
<?php
use Doctrine\ORM\Mapping as ORM;
 
#[ORM\Entity]
#[ORM\Table(name: "ecommerce_order", options: ["charset"=>"utf8","collate"=>"utf8_unicode_ci"])]
#[ORM\ChangeTrackingPolicy("DEFERRED_IMPLICIT")]
class EcommerceOrder
{
    #[ORM\Id]
    #[ORM\Column(type: "integer")]
    #[ORM\GeneratedValue(strategy: "AUTO")]
    private $id;
 
    #[ORM\Column(type: "timestamp", length: 255, nullable: true)]
    private $ordered_at;
 
    #[ORM\Column(type: "string", nullable: true)]
    private $customer_note;
 
    #[ORM\Column(type: "string", nullable: true)]
    private $internal_note;
 
    #[ORM\OneToOne(targetEntity: "Address", inversedBy: "EcommerceOrders")]
    #[ORM\JoinColumn(name: "billing_address_id", referencedColumnName: "id", unique: true)]
    private $BillingAddress;
 
    #[ORM\OneToOne(targetEntity: "Address", inversedBy: "EcommerceOrdersDelivery")]
    #[ORM\JoinColumn(name: "delivery_address_id", referencedColumnName: "id", unique: true)]
    private $DeliveryAddress;
}
<?php
use Doctrine\ORM\Mapping AS ORM;
 
/**
 * @ORM\Entity
 * @ORM\Table(schema="ecommerce_order", options={"charset":"utf8","collate":"utf8_unicode_ci"})
 * @ORM\ChangeTrackingPolicy("DEFERRED_IMPLICIT")
 */
class EcommerceOrder
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer", length=4, options={"unsigned":true})
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     */
    private $id;
 
    /**
     * @ORM\Column(type="timestamp", nullable=true)
     */
    private $ordered_at;
 
    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $customer_note;
 
    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $internal_note;
 
    /**
     * @ORM\OneToOne(targetEntity="Address")
     * @ORM\JoinColumn(name="billing_address_id", referencedColumnName="id", unique=true)
     */
    private $BillingAddress;
 
    /**
     * @ORM\ManyToOne(targetEntity="Address")
     * @ORM\JoinColumn(name="delivery_address_id", referencedColumnName="id")
     */
    private $DeliveryAddress;
}
<?xml version="1.0"?>
<doctrine-mapping 
 xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" 
 xsi="http://www.w3.org/2001/XMLSchema-instance" 
 schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
  <entity 
	 name="EcommerceOrder" 
	 change-tracking-policy="DEFERRED_IMPLICIT" 
	 schema="ecommerce_order" 
	 repository-class="Doctrine\ORM\EntityRepository">
    <id name="id" type="integer" length="4">
      <generator strategy="SEQUENCE"/>
      <options>
        <option name="unsigned" value="true"/>
      </options>
    </id>
    <field name="ordered_at" type="timestamp" nullable="true"/>
    <field name="customer_note" type="string" nullable="true" version="true"/>
    <field name="internal_note" type="string" nullable="true" version="true"/>
    <many-to-one field="DeliveryAddress" target-entity="Address">
      <join-columns>
        <join-column 
				 name="delivery_address_id" 
				 referenced-column-name="id" 
				 on-delete="CASCADE"/>
      </join-columns>
    </many-to-one>
    <one-to-one field="BillingAddress" target-entity="Address">
      <join-columns>
        <join-column 
				 name="billing_address_id" 
				 referenced-column-name="id" 
				 unique="true" 
				 on-delete="CASCADE"/>
      </join-columns>
    </one-to-one>
    <options>
      <option name="charset" value="utf8"/>
      <option name="collate" value="utf8_unicode_ci"/>
    </options>
  </entity>
</doctrine-mapping>
EcommerceOrder:
  type: entity
  changeTrackingPolicy: DEFERRED_IMPLICIT
  schema: ecommerce_order
  repositoryClass: Doctrine\ORM\EntityRepository
  fields:
    id:
      id: true
      type: integer
      length: 4
      generator:
        strategy: SEQUENCE
      options:
        unsigned: true
    ordered_at:
      type: timestamp
      nullable: true
    customer_note:
      type: string
      nullable: true
      version: true
    internal_note:
      type: string
      nullable: true
      version: true
  options:
    charset: utf8
    collate: utf8_unicode_ci
  oneToOne:
    BillingAddress:
      targetEntity: Address
      joinColumns:
        billing_address_id:
          referencedColumnName: id
          unique: true
          onDelete: CASCADE
  manyToOne:
    DeliveryAddress:
      targetEntity: Address
      joinColumns:
        delivery_address_id:
          referencedColumnName: id
          onDelete: CASCADE
<?php
namespace App\Models\Base;
use Illuminate\Database\Eloquent\Model;
 
class EcommerceOrder extends Model
{
  /**  
  * Do not automatically manage timestamps by Eloquent
  * 
  * @var bool
  */
  protected $timestamps=false;
   
  /**  
  * The attributes that should be cast to native types.
  * 
  * @var array
  */
  protected $casts=[
    'id'=>'integer',
    'ecommerce_order_state_id'=>'integer',
    'contact_id'=>'integer',
    'delivery_address_id'=>'integer',
    'billing_address_id'=>'integer',
    'ordered_at'=>'datetime',
    'customer_note'=>'string',
    'internal_note'=>'string'
  ];
  /**  
  * The guarded property should contain an array of attributes that you do not want to be mass assignable.
  * 
  * @var array
  */
  protected $is_guarded=['internal_note'];
  /**  
  * The attributes that are mass assignable.
  * 
  * @var array
  */
  protected $is_fillable=[
    'id',
    'ecommerce_order_state_id',
    'contact_id',
    'delivery_address_id',
    'billing_address_id',
    'ordered_at',
    'customer_note'
  ];
  public function Contact()
  {
    return $this->belongsTo('\App\Models\Contact','contact_id','id');
  }
  public function DeliveryAddress()
  {
    return $this->belongsTo('\App\Models\Address','delivery_address_id','id');
  }
  public function BillingAddress()
  {
    return $this->belongsTo('\App\Models\Address','billing_address_id','id');
  }
  public function OrderItem()
  {
    return $this->hasMany('\App\Models\EcommerceOrderItem','ecommerce_order_id','id');
  }
  public function OrderSimpleItem()
  {
    return $this->hasMany('\App\Models\EcommerceOrderSimpleItem','ecommerce_order_id','id');
  }
}

2. Export it to complete definition files.


What more Skipper brings you

Four times faster development

Replace manual coding with visual modeling and increase your work efficiency.

Emphasis on logic,
not syntax

Focus only on project logic. Syntax and keywords are completed by Skipper.

Perfect knowledge
of projects

Visual model lets you discover logic of any imported project simply and quickly.

Wide
customizability

Create your own templates or adjust ORM properties to fit your project needs.

See all the features

Over 5,000 companies use Skipper every day


It saved us a lot of time designing and configuring complex data models. It is impressive to see what this software achieves on its own.

Michael Stoye, ColorGATE

We use Skipper on our daily basis for ecommerce software development. It lets us visualize at a glance the data models and work on them in a simple and easy way.

Dario Schilman, IDS Soluciones Ecommerce

It simplifies our work because it saves us time. With features added over time like adding behaviors to Propel in Skipper it has become an unmissable tool in our organisation.

Erwin te Bos, aXtion

Skipper is a stable and easy to use schema designing tool! No documentation, just design and everything is documented!

Siebe Vos, Inform'aid

Simply put, for us, Skipper is not just a tool to master, but a mastermind that teaches us the best programming practices.

Can Berkol, Biber Ltd

Skipper is especially helpful in the initial data modeling phase. Exporting the data model and scaffolding makes it really easy to get a first prototype up and running in a matter of minutes.

Jörn Wagner, Explicatis

It is faster and gives less errors to have Skipper create the mapping code instead of writing it myself. Later in the development process I often use the Skipper diagram as a quick reference.

Herman Peeren, Yepr

We have good use of the tool. It simplifies our daily work, saves us time and is simple and intuitive to use.

Thomas Somoen, Try/Apt

More user stories